config root man

Current Path : /usr/src/usr.sbin/asf/

FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64
Upload File :
Current File : //usr/src/usr.sbin/asf/asf.c

/*-
 * Copyright (c) 2002, 2003 Greg Lehey
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * This software is provided by the author ``as is'' and any express
 * or implied warranties, including, but not limited to, the implied
 * warranties of merchantability and fitness for a particular purpose
 * are disclaimed.  In no event shall the author be liable for any
 * direct, indirect, incidental, special, exemplary, or consequential
 * damages (including, but not limited to, procurement of substitute
 * goods or services; loss of use, data, or profits; or business
 * interruption) however caused and on any theory of liability,
 * whether in contract, strict liability, or tort (including
 * negligence or otherwise) arising in any way out of the use of this
 * software, even if advised of the possibility of such damage.
 */
/* $Id: asf.c,v 1.4 2003/05/04 02:55:20 grog Exp grog $ */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: release/9.1.0/usr.sbin/asf/asf.c 165372 2006-12-20 06:20:04Z yar $");

#include <sys/types.h>
#include <sys/queue.h>
#include <sys/stat.h>
#include <ctype.h>
#include <err.h>
#include <errno.h>
#include <fts.h>
#include <inttypes.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include "asf.h"

struct kfile {
    char	       *name;
    caddr_t		addr;
    int			seen;
    STAILQ_ENTRY(kfile)	link;
};

static STAILQ_HEAD(,kfile) kfile_head = STAILQ_HEAD_INITIALIZER(kfile_head);

void
kfile_add(const char *name, caddr_t addr)
{
    struct kfile *kfp;

    if ((kfp = malloc(sizeof(*kfp))) == NULL ||
	(kfp->name = strdup(name)) == NULL)
	    errx(2, "out of memory");
    kfp->addr = addr;
    kfp->seen = 0;
    STAILQ_INSERT_TAIL(&kfile_head, kfp, link);
}

static struct kfile *
kfile_find(const char *name)
{
    struct kfile *kfp;

    STAILQ_FOREACH(kfp, &kfile_head, link)
	if (strcmp(kfp->name, name) == 0)
	    return (kfp);	/* found */

    return (NULL);		/* not found */
}

static int
kfile_allseen(void)
{
    struct kfile *kfp;

    STAILQ_FOREACH(kfp, &kfile_head, link)
	if (!kfp->seen)
	    return (0);	/* at least one unseen */

    return (1);		/* all seen */
}

static int
kfile_empty(void)
{
    return (STAILQ_EMPTY(&kfile_head));
}

/*
 * Take a blank separated list of tokens and turn it into a list of
 * individual nul-delimited strings.  Build a list of pointers at
 * token, which must have enough space for the tokens.  Return the
 * number of tokens, or -1 on error (typically a missing string
 * delimiter).
 */
int
tokenize(char *cptr, char *token[], int maxtoken)
{
    char delim;				/* delimiter to search for */
    int tokennr;			/* index of this token */

    for (tokennr = 0; tokennr < maxtoken;) {
	while (isspace(*cptr))
	    cptr++;			/* skip initial white space */
	if ((*cptr == '\0') || (*cptr == '\n')
	    || (*cptr == '#'))		/* end of line */
	    return tokennr;		/* return number of tokens found */
	delim = *cptr;
	token[tokennr] = cptr;		/* point to it */
	tokennr++;			/* one more */
	if (tokennr == maxtoken)	/* run off the end? */
	    return tokennr;
	if ((delim == '\'') || (delim == '"')) { /* delimitered */
	    for (;;) {
		cptr++;
		if ((*cptr == delim)
		    && (cptr[-1] != '\\')) { /* found the partner */
		    cptr++;		/* move on past */
		    if (!isspace(*cptr)) /* no space after closing quote */
			return -1;
		    *cptr++ = '\0';	/* delimit */
		} else if ((*cptr == '\0')
		    || (*cptr == '\n'))	/* end of line */
		    return -1;
	    }
	} else {			/* not quoted */
	    while ((*cptr != '\0') && (!isspace(*cptr)) && (*cptr != '\n'))
		cptr++;
	    if (*cptr != '\0')		/* not end of the line, */
		*cptr++ = '\0';		/* delimit and move to the next */
	}
    }
    return maxtoken;			/* can't get here */
}

static void
doobj(const char *path, caddr_t addr, FILE *out)
{
    uintmax_t	base = (uintptr_t)addr;
    uintmax_t	textaddr = 0;
    uintmax_t	dataaddr = 0;
    uintmax_t	bssaddr = 0;
    uintmax_t  *up;
    int		octokens;
    char       *octoken[MAXTOKEN];
    char	ocbuf[LINE_MAX + PATH_MAX];
    FILE       *objcopy;

    snprintf(ocbuf, sizeof(ocbuf),
	     "/usr/bin/objdump --section-headers %s", path);
    if ((objcopy = popen(ocbuf, "r")) == NULL)
	err(2, "can't start %s", ocbuf);
    while (fgets(ocbuf, sizeof(ocbuf), objcopy)) {
	octokens = tokenize(ocbuf, octoken, MAXTOKEN);
	if (octokens <= 1)
	    continue;
	up = NULL;
	if (strcmp(octoken[1], ".text") == 0)
	    up = &textaddr;
	else if (strcmp(octoken[1], ".data") == 0)
	    up = &dataaddr;
	else if (strcmp(octoken[1], ".bss") == 0)
	    up = &bssaddr;
	if (up == NULL)
	    continue;
	*up = strtoumax(octoken[3], NULL, 16) + base;
    }
    if (textaddr) {	/* we must have a text address */
	fprintf(out, "add-symbol-file %s 0x%jx", path, textaddr);
	if (dataaddr)
	    fprintf(out, " -s .data 0x%jx", dataaddr);
	if (bssaddr)
	    fprintf(out, " -s .bss 0x%jx", bssaddr);
	fprintf(out, "\n");
    }
}

static void
findmodules(char *path_argv[], const char *sfx[], FILE *out)
{
    char	       *p;
    FTS		       *fts;
    FTSENT	       *ftsent;
    struct kfile       *kfp;
    int			i;
    int			sl;

    /* Have to fts once per suffix to find preferred suffixes first */
    do {
	sl = *sfx ? strlen(*sfx) : 0;	/* current suffix length */
	fts = fts_open(path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
	if (fts == NULL)
	    err(2, "can't begin traversing module path");
	while ((ftsent = fts_read(fts)) != NULL) {
	    if (ftsent->fts_info == FTS_DNR ||
		ftsent->fts_info == FTS_ERR ||
		ftsent->fts_info == FTS_NS) {
		    errno = ftsent->fts_errno;
		    err(2, "error while traversing path %s", ftsent->fts_path);
	    }
	    if (ftsent->fts_info != FTS_F)
		continue;			/* not a plain file */

	    if (sl > 0) {
		/* non-blank suffix; see if file name has it */
		i = ftsent->fts_namelen - sl;
		if (i <= 0 || strcmp(ftsent->fts_name + i, *sfx) != 0)
		    continue;		/* no such suffix */
		if ((p = strdup(ftsent->fts_name)) == NULL)
		    errx(2, "out of memory");
		p[i] = '\0';		/* remove suffix in the copy */
		kfp = kfile_find(p);
		free(p);
	    } else
		kfp = kfile_find(ftsent->fts_name);

	    if (kfp && !kfp->seen) {
		doobj(ftsent->fts_path, kfp->addr, out);
		kfp->seen = 1;
		/* Optimization: stop fts as soon as seen all loaded modules */
		if (kfile_allseen()) {
		    fts_close(fts);
		    return;
		}
	    }
	}
	if (ftsent == NULL && errno != 0)
	    err(2, "couldn't complete traversing module path");
	fts_close(fts);
    } while (*sfx++);
}

static void
usage(const char *myname)
{
    fprintf(stderr,
	"Usage:\n"
	"%s [-afKksVx] [-M core] [-N system] [-o outfile] [-X suffix]\n"
	"%*s [modules-path [outfile]]\n\n"
	"\t-a\tappend to outfile\n"
	"\t-f\tfind the module in any subdirectory of modules-path\n"
	"\t-K\tuse kld(2) to get the list of modules\n"
	"\t-k\ttake input from kldstat(8)\n"
	"\t-M\tspecify core name for kvm(3)\n"
	"\t-N\tspecify system name for kvm(3)\n"
	"\t-o\tuse outfile instead of \".asf\"\n"
	"\t-s\tdon't prepend subdir for module path\n"
	"\t-V\tuse kvm(3) to get the list of modules\n"
	"\t-X\tappend suffix to list of possible module file name suffixes\n"
	"\t-x\tclear list of possible module file name suffixes\n",
	myname, (int)strlen(myname), "");
    exit(2);
}

#define	MAXPATHS	15
#define	MAXSUFFIXES	15

/* KLD file names end in this */
static int	   nsuffixes = 2;
static const char *suffixes[MAXSUFFIXES + 1] = {
    ".debug",
    ".symbols",
    NULL
};

int
main(int argc, char *argv[])
{
    char basename[PATH_MAX];
    char path[PATH_MAX];
    char *modules_argv[MAXPATHS + 1];
    char *copy, *p;
    char **ap;
    const char *filemode = "w";		/* mode for outfile */
    const char *modules_path = "modules"; /* path to kernel build directory */
    const char *outfile = ".asf";	/* and where to write the output */
    const char *corefile = NULL;	/* for kvm(3) */
    const char *sysfile = NULL;		/* for kvm(3) */
    const char **sfx;
    struct kfile *kfp;
    struct stat st;
    FILE *out;				/* output file */
    int dofind = 0;
    int dokld = 0;
    int dokvm = 0;
    int nosubdir = 0;
    int runprog = 0;
    int i;
    const int sl = strlen(KLDSUFFIX);

    while ((i = getopt(argc, argv, "afKkM:N:o:sVX:x")) != -1)
	switch (i) {
	case 'a':
	    filemode = "a";	/* append to outfile */
	    break;
	case 'f':
	    dofind = 1;		/* find .ko (recursively) */
	    break;
	case 'K':
	    dokld = 1;		/* use kld(2) interface */
	    break;
	case 'k':
	    runprog = 1;	/* get input from kldstat(8) */
	    break;
	case 'M':
	    corefile = optarg;	/* core file for kvm(3) */
	    break;
	case 'N':
	    sysfile = optarg;	/* system file (kernel) for kvm(3) */
	    break;
	case 'o':
	    outfile = optarg;	/* output file name */
	    break;
	case 's':
	    nosubdir = 1;	/* don't descend into subdirs */
	    break;
	case 'V':
	    dokvm = 1;		/* use kvm(3) interface */
	    break;
	case 'X':
	    if (nsuffixes >= MAXSUFFIXES)
		errx(2, "only %d suffixes can be specified", MAXSUFFIXES);
	    suffixes[nsuffixes++] = optarg;
	    suffixes[nsuffixes] = NULL;
	    break;
	case 'x':
	    nsuffixes = 0;
	    suffixes[0] = NULL;
	    break;
	default:
	    usage(argv[0]);
	}

    argc -= optind;
    argv += optind;

    if (argc > 0) {
	modules_path = argv[0];
	argc--, argv++;
    }
    if (argc > 0) {
	outfile = argv[0];
	argc--, argv++;
    }
    if (argc > 0)
	usage(argv[0]);

    if (strcmp(outfile, "-") == 0)
	out = stdout;
    else
	if ((out = fopen(outfile, filemode)) == NULL)
	    err(2, "can't open output file %s", outfile);

    if (dokvm || corefile || sysfile) {
	if (dokld || runprog)
	    warnx("using kvm(3) instead");
	asf_kvm(sysfile, corefile);
    } else if (dokld) {
	if (runprog)
	    warnx("using kld(2) instead");
	asf_kld();
    } else
	asf_prog(runprog);

    /* Avoid long operations like module tree traversal when nothing to do */
    if (kfile_empty()) {
	warnx("no kernel modules loaded");
	return (0);
    }

    if ((copy = strdup(modules_path)) == NULL)
	errx(2, "out of memory");
    for (
	ap = modules_argv, p = copy;
	(*ap = strsep(&p, ";")) != NULL && ap < &modules_argv[MAXPATHS];
	ap++
    );
    if (*ap)
	errx(2, "only %d module path elements can be specified", MAXPATHS);

    if (!dofind)
	STAILQ_FOREACH(kfp, &kfile_head, link) {
	    for (ap = modules_argv; *ap; ap++) {
		if (!nosubdir) {
		    /* prepare basename of KLD, w/o suffix */
		    strlcpy(basename, kfp->name, sizeof(basename) - 1);
		    i = strlen(basename);
		    if (i > sl && strcmp(basename + i - sl, KLDSUFFIX) == 0)
			i -= sl;
		    basename[i] = '/';
		    basename[i + 1] = '\0';
		}
		for (sfx = suffixes;; sfx++) {
		    snprintf(path, sizeof(path),
			     "%s/%s%s%s",
			     *ap,
			     nosubdir ? "" : basename,
			     kfp->name,
			     *sfx ? *sfx : "");
		    if (stat(path, &st) == 0) {
			doobj(path, kfp->addr, out);
			goto found;
		    }
		    if (*sfx == NULL)
			break;
		}
	    }
	    warnx("module %s not found in search path", kfp->name);
found:
	    ;
	}
    else
    	findmodules(modules_argv, suffixes, out);

    free(copy);
    return (0);
}

Man Man