Пример #1
0
/*
 * Read lines from a file stream (normally STDIN)
 * Returns the number of regular files to be watched or -1 if max_files is
 * exceeded
 */
int
process_input(FILE *file, WatchFile *files[], int max_files) {
	char buf[PATH_MAX];
	char *p, *path;
	int n_files = 0;
	struct stat sb;
	int i, matches;

	while (fgets(buf, sizeof(buf), file) != NULL) {
		buf[PATH_MAX-1] = '\0';
		if ((p = strchr(buf, '\n')) != NULL)
			*p = '\0';
		if (buf[0] == '\0')
			continue;

		if (xstat(buf, &sb) == -1) {
			xwarnx("unable to stat '%s'", buf);
			continue;
		}
		if (S_ISREG(sb.st_mode) != 0) {
			files[n_files] = malloc(sizeof(WatchFile));
			strlcpy(files[n_files]->fn, buf, MEMBER_SIZE(WatchFile, fn));
			files[n_files]->is_dir = 0;
			files[n_files]->file_count = 0;
			files[n_files]->mode = sb.st_mode;
			n_files++;
		}
		/* also watch the directory if it's not already in the list */
		if (dirwatch_opt == 1) {
			if (S_ISDIR(sb.st_mode) != 0)
				path = &buf[0];
			else
				if ((path = dirname(buf)) == 0)
					err(1, "dirname '%s' failed", buf);
			for (matches=0, i=0; i<n_files; i++)
				if (strcmp(files[i]->fn, path) == 0) matches++;
			if (matches == 0) {
				files[n_files] = malloc(sizeof(WatchFile));
				strlcpy(files[n_files]->fn, path,
				    MEMBER_SIZE(WatchFile, fn));
				files[n_files]->is_dir = 1;
				files[n_files]->file_count = xlist_dir(path);
				files[n_files]->mode = sb.st_mode;
				n_files++;
			}
		}
		if (n_files+1 > max_files)
			return -1;
	}
	return n_files;
}
Пример #2
0
/*
 * The Event Notify Test Runner
 * run arbitrary commands when files change
 */
int
main(int argc, char *argv[]) {
	struct rlimit rl;
	int kq;
	struct sigaction act;
	int ttyfd;
	short argv_index;
	int n_files;
	int i;

	if ((*test_runner_main))
		return(test_runner_main(argc, argv));

	/* set up pointers to real functions */
	xstat = stat;
	xkevent = kevent;
	xkillpg = killpg;
	xexecvp = execvp;
	xwaitpid = waitpid;
	xfork = fork;
	xopen = open;
	xrealpath = realpath;
	xfree = free;
	xwarnx = warnx;
	xerrx = errx;
	xlist_dir = list_dir;

	/* call usage() if no command is supplied */
	if (argc < 2) usage();
	argv_index = set_options(argv);

	/* normally a user will exit this utility by do_execting Ctrl-C */
	act.sa_flags = 0;
	act.sa_flags = SA_RESETHAND;
	act.sa_handler = handle_exit;
	if (sigemptyset(&act.sa_mask) & (sigaction(SIGINT, &act, NULL) != 0))
		err(1, "Failed to set SIGINT handler");
	if (sigemptyset(&act.sa_mask) & (sigaction(SIGTERM, &act, NULL) != 0))
		err(1, "Failed to set TERM handler");

	/* raise soft limit */
	getrlimit(RLIMIT_NOFILE, &rl);
	rl.rlim_cur = min((rlim_t)sysconf(_SC_OPEN_MAX), rl.rlim_max);
	if (setrlimit(RLIMIT_NOFILE, &rl) != 0)
		err(1, "setrlimit cannot set rlim_cur to %d", (int)rl.rlim_cur);

	/* prevent interactive utilities from paging output */
	setenv("PAGER", "/bin/cat", 0);

	/* sequential scan may depend on a 0 at the end */
	files = calloc(rl.rlim_cur+1, sizeof(WatchFile *));

	if ((kq = kqueue()) == -1)
		err(1, "cannot create kqueue");

	/* read input and populate watch list, skipping non-regular files */
	n_files = process_input(stdin, files, rl.rlim_cur);
	if (n_files == 0)
		errx(1, "No regular files to watch");
	if (n_files == -1)
		errx(1, "Too many files listed; the hard limit for your login"
		    " class is %d. Please consult"
		    " http://entrproject.org/limits.html", (int)rl.rlim_cur);
	for (i=0; i<n_files; i++)
		watch_file(kq, files[i]);

	/* Attempt to open a tty so that editors don't complain */
	ttyfd = xopen(_PATH_TTY, O_RDONLY);
	if (ttyfd > STDIN_FILENO) {
		if (dup2(ttyfd, STDIN_FILENO) != 0)
			xwarnx("can't dup2 to stdin");
		close(ttyfd);
	}

	watch_loop(kq, argv+argv_index);
	return 1;
}
Пример #3
0
/*
 * getopt_long --
 *      Parse argc/argv argument vector.
 */
int
getopt_long(int nargc,
            char * const *nargv,
            const char *options,
            const struct option *long_options,
            int *idx)
{
        int retval;

        _DIAGASSERT(nargv != NULL);
        _DIAGASSERT(options != NULL);
        _DIAGASSERT(long_options != NULL);
        /* idx may be NULL */

        progname = nargv[0];

	/* fprintf(stderr, "FYI: using private getoptlong.c implementation\n"); */

        if ((retval = getopt_internal(nargc, nargv, options)) == -2) {
                char *current_argv, *has_equal;
                size_t current_argv_len;
                int i, match;

                current_argv = place;
                match = -1;

                optind++;
                place = EMSG;

                if (*current_argv == '\0') {            /* found "--" */
                        /*
                         * We found an option (--), so if we skipped
                         * non-options, we have to permute.
                         */
                        if (nonopt_end != -1) {
                                permute_args(nonopt_start, nonopt_end,
                                    optind, nargv);
                                optind -= nonopt_end - nonopt_start;
                        }
                        nonopt_start = nonopt_end = -1;
                        return -1;
                }
                if ((has_equal = strchr(current_argv, '=')) != NULL) {
                        /* argument found (--option=arg) */
                        current_argv_len = has_equal - current_argv;
                        has_equal++;
                } else
                        current_argv_len = strlen(current_argv);

                for (i = 0; long_options[i].name; i++) {
                        /* find matching long option */
                        if (strncmp(current_argv, long_options[i].name,
                            current_argv_len))
                                continue;

                        if (strlen(long_options[i].name) ==
                            (unsigned)current_argv_len) {
                                /* exact match */
                                match = i;
                                break;
                        }
                        if (match == -1)                /* partial match */
                                match = i;
                        else {
                                /* ambiguous abbreviation */
                                if (PRINT_ERROR)
                                        xwarnx(ambig, (int)current_argv_len,
                                             current_argv);
                                optopt = 0;
                                return BADCH;
                        }
                }
                if (match != -1) {                      /* option found */
                        if (long_options[match].has_arg == no_argument
                            && has_equal) {
                                if (PRINT_ERROR)
                                        xwarnx(noarg, (int)current_argv_len,
                                             current_argv);
                                /*
                                 * XXX: GNU sets optopt to val regardless of
                                 * flag
                                 */
                                if (long_options[match].flag == NULL)
                                        optopt = long_options[match].val;
                                else
                                        optopt = 0;
                                /* XXX: GNU returns '?' if options[0] != ':' */
fprintf(stdout, "Sanity: 5\n");fprintf(stderr, "SANITY: 5\n");
                             //   if (options[0] != ':')
                              //          return BADCH;
                                optopt = BADCH;
                                //        return BADCH;
                                return BADARG;
                        }
                        if (long_options[match].has_arg == required_argument ||
                            long_options[match].has_arg == optional_argument) {
                                if (has_equal)
                                        optarg = has_equal;
                                else if (long_options[match].has_arg ==
                                    required_argument) {
                                        /*
                                         * optional argument doesn't use
                                         * next nargv
                                         */
                                        if (optind >= nargc) {          /* end of argument vector */
//fprintf(stdout, "Sanity: 8\n");fprintf(stderr, "SANITY: 8\n");
                                                optarg = 0;
                                        } else {
//fprintf(stdout, "Sanity: 9\n");fprintf(stderr, "SANITY: 9\n");
                                                optarg = nargv[optind++];
                                        }
                                }
                        }
                        if ((long_options[match].has_arg == required_argument)
                            && (optarg == NULL)) {
                                /*
                                 * Missing argument; leading ':'
                                 * indicates no error should be generated
                                 */
                                if (PRINT_ERROR)
                                        xwarnx(recargstring, current_argv);
                                /*
                                 * XXX: GNU sets optopt to val regardless
                                 * of flag
                                 */
                                if (long_options[match].flag == NULL)
                                        optopt = long_options[match].val;
                                else
                                        optopt = 0;
                                /* XXX: GNU returns '?' if options[0] != ':' */
                                //--optind;
//fprintf(stdout, "Sanity: 6\n");fprintf(stderr, "SANITY: 6\n");
                                return BADARG;
                        }
                } else {                        /* unknown option */
                        if (PRINT_ERROR)
                                xwarnx(illoptstring, current_argv);
                        optopt = 0;
                        optarg = current_argv;
                        return BADCH;
                }
                if (long_options[match].flag) {
                        *long_options[match].flag = long_options[match].val;
                        retval = 0;
                } else
                        retval = long_options[match].val;
                if (idx)
                        *idx = match;
        }
//fprintf(stdout, "Terminal: %d\n",retval);fprintf(stderr, "TERMINAL: %d\n",retval);
        return retval;
}
Пример #4
0
/*
 * getopt_internal --
 *      Parse argc/argv argument vector.  Called by user level routines.
 *  Returns -2 if -- is found (can be long option or end of options marker).
 */
static int
getopt_internal(int nargc, char * const *nargv, const char *options)
{
        char *oli;                              /* option letter list index */
        int optchar;

        _DIAGASSERT(nargv != NULL);
        _DIAGASSERT(options != NULL);

        optarg = NULL;

        /*
         * XXX Some programs (like rsyncd) expect to be able to
         * XXX re-initialize optind to 0 and have getopt_long(3)
         * XXX properly function again.  Work around this braindamage.
         */
        if (optind == 0)
                optind = 1;

        if (optreset)
                nonopt_start = nonopt_end = -1;
start:
        if (optreset || !*place) {              /* update scanning pointer */
                optreset = 0;
                if (optind >= nargc) {          /* end of argument vector */
                        place = EMSG;
                        if (nonopt_end != -1) {
                                /* do permutation, if we have to */
                                permute_args(nonopt_start, nonopt_end,
                                    optind, nargv);
                                optind -= nonopt_end - nonopt_start;
                        }
                        else if (nonopt_start != -1) {
                                /*
                                 * If we skipped non-options, set optind
                                 * to the first of them.
                                 */
                                optind = nonopt_start;
                        }
                        nonopt_start = nonopt_end = -1;
                        return -1;
                }
                if (*(place = nargv[optind]) != '-') {  /* found non-option */
                        place = EMSG;
                        if (IN_ORDER) {
                                /*
                                 * GNU extension: 
                                 * return non-option as argument to option 1
                                 */
                                optarg = nargv[optind++];
                                return INORDER;
                        }
                        if (!PERMUTE) {
                                /*
                                 * if no permutation wanted, stop parsing
                                 * at first non-option
                                 */
                                return -1;
                        }
                        /* do permutation */
                        if (nonopt_start == -1)
                                nonopt_start = optind;
                        else if (nonopt_end != -1) {
                                permute_args(nonopt_start, nonopt_end,
                                    optind, nargv);
                                nonopt_start = optind -
                                    (nonopt_end - nonopt_start);
                                nonopt_end = -1;
                        }
                        optind++;
                        /* process next argument */
                        goto start;
                }
                if (nonopt_start != -1 && nonopt_end == -1)
                        nonopt_end = optind;
                if (place[1] && *++place == '-') {      /* found "--" */
                        place++;
                        return -2;
                }
        }
        if ((optchar = (int)*place++) == (int)':' ||
            (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
                /* option letter unknown or ':' */
                if (!*place)
                        ++optind;
                if (PRINT_ERROR)
                        xwarnx(illoptchar, optchar);
                optopt = optchar;
                return BADCH;
        }
        if (optchar == 'W' && oli[1] == ';') {          /* -W long-option */
                /* XXX: what if no long options provided (called by getopt)? */
                if (*place)
                        return -2;

                if (++optind >= nargc) {        /* no arg */
                        place = EMSG;
                        if (PRINT_ERROR)
                                xwarnx(recargchar, optchar);
                        optopt = optchar;
                        /* XXX: GNU returns '?' if options[0] != ':' */
fprintf(stdout, "Sanity: 2\n");fprintf(stderr, "SANITY: 2\n");
                        return BADARG;
                } else                          /* white space */
                        place = nargv[optind];
                /*
                 * Handle -W arg the same as --arg (which causes getopt to
                 * stop parsing).
                 */
                return -2;
        }
        if (*++oli != ':') {                    /* doesn't take argument */
                if (!*place)
                        ++optind;
        } else {                                /* takes (optional) argument */
                optarg = NULL;
                if (*place)                     /* no white space */
                        optarg = place;
                /* XXX: disable test for :: if PC? (GNU doesn't) */
                else if (oli[1] != ':') {       /* arg not optional */
                        if (++optind >= nargc) {        /* no arg */
                                place = EMSG;
                                if (PRINT_ERROR)
                                        xwarnx(recargchar, optchar);
                                optopt = optchar;
                                /* XXX: GNU returns '?' if options[0] != ':' */
fprintf(stdout, "Sanity: 3\n");fprintf(stderr, "SANITY: 3\n");
                                return BADARG;
                        } else
                                optarg = nargv[optind];
                }
                place = EMSG;
                ++optind;
        }
        /* dump back option letter */
        return optchar;
}
Пример #5
0
static bool
_rtld_load_by_name(const char *name, Obj_Entry *obj, Needed_Entry **needed,
    int flags)
{
	Library_Xform *x = _rtld_xforms;
	Obj_Entry *o = NULL;
	size_t j;
	ssize_t i;
	bool got = false;
	union {
		int i;
		u_quad_t q;
		char s[16];
	} val;

	dbg(("load by name %s %p", name, x));
	for (; x; x = x->next) {
#ifdef __minix
		continue;
#else
		if (strcmp(x->name, name) != 0)
			continue;

		j = sizeof(val);
		if ((i = _rtld_sysctl(x->ctlname, &val, &j)) == -1) {
			xwarnx(_PATH_LD_HINTS ": invalid/unknown sysctl for %s (%d)",
			    name, errno);
			break;
		}

		switch (i) {
		case CTLTYPE_QUAD:
			xsnprintf(val.s, sizeof(val.s), "%" PRIu64, val.q);
			break;
		case CTLTYPE_INT:
			xsnprintf(val.s, sizeof(val.s), "%d", val.i);
			break;
		case CTLTYPE_STRING:
			break;
		default:
			xwarnx("unsupported sysctl type %d", (int)i);
			break;
		}

		dbg(("sysctl returns %s", val.s));

		for (i = 0; i < RTLD_MAX_ENTRY && x->entry[i].value != NULL;
		    i++) {
			dbg(("entry %ld", (unsigned long)i));
			if (strcmp(x->entry[i].value, val.s) == 0)
				break;
		}

		if (i == RTLD_MAX_ENTRY) {
			xwarnx("sysctl value %s not found for lib%s",
			    val.s, name);
			break;
		}

		for (j = 0; j < RTLD_MAX_LIBRARY &&
		    x->entry[i].library[j] != NULL; j++) {
			o = _rtld_load_library(x->entry[i].library[j], obj,
			    flags);
			if (o == NULL) {
				xwarnx("could not load %s for %s",
				    x->entry[i].library[j], name);
				continue;
			}
			got = true;
			if (j == 0)
				(*needed)->obj = o;
			else {
				/* make a new one and put it in the chain */
				Needed_Entry *ne = xmalloc(sizeof(*ne));
				ne->name = (*needed)->name;
				ne->obj = o;
				ne->next = (*needed)->next;
				(*needed)->next = ne;
				*needed = ne;
			}
				
		}
		
#endif
	}

	if (got)
		return true;

	return ((*needed)->obj = _rtld_load_library(name, obj, flags)) != NULL;
}
Пример #6
0
/*
 * Process library mappings of the form:
 *	<library_name>	<machdep_variable> <value,...:library_name,...> ... 
 */
static void
_rtld_process_mapping(Library_Xform **lib_p, const char *bp, const char *ep)
{
	Library_Xform *hwptr = NULL;
	const char *ptr, *key, *ekey, *lib, *elib, *l;
	int i, j;
	
	dbg((" processing mapping \"%.*s\"", (int)(ep - bp), bp));

	if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp)
		return;

	dbg((" library \"%.*s\"", (int)(bp - ptr), ptr));

	hwptr = xmalloc(sizeof(*hwptr));
	memset(hwptr, 0, sizeof(*hwptr));
	hwptr->name = exstrdup(ptr, bp);

	bp++;

	if ((ptr = getword(&bp, ep, WS)) == NULL || ptr == bp) {
		xwarnx("missing sysctl variable name");
		goto cleanup;
	}

	dbg((" sysctl \"%.*s\"", (int)(bp - ptr), ptr));

	hwptr->ctlname = exstrdup(ptr, bp);

	for (i = 0; bp++, (ptr = getword(&bp, ep, WS)) != NULL;) {
		dbg((" ptr = %.*s", (int)(bp - ptr), ptr));
		if (ptr == bp)
			continue;

		if (i == RTLD_MAX_ENTRY) {
no_more:
			xwarnx("maximum library entries exceeded `%s'",
			    hwptr->name);
			goto cleanup;
		}
		if ((key = getstr(&ptr, bp, ":")) == NULL) {
			xwarnx("missing sysctl variable value for `%s'",
			    hwptr->name);
			goto cleanup;
		}
		ekey = ptr++;
		if ((lib = getstr(&ptr, bp, ":")) == NULL) {
			xwarnx("missing sysctl library list for `%s'",
			    hwptr->name);
			goto cleanup;
		}
		elib = ptr;		/* No need to advance */
		for (j = 0; (l = getstr(&lib, elib, ",")) != NULL;
		    j++, lib++) {
			if (j == RTLD_MAX_LIBRARY) {
				xwarnx("maximum library entries exceeded `%s'",
				    hwptr->name);
				goto cleanup;
			}
			dbg((" library \"%.*s\"", (int)(lib - l), l));
			hwptr->entry[i].library[j] = exstrdup(l, lib);
		}
		if (j == 0) {
			xwarnx("No library map entries for `%s/%.*s'",
			    hwptr->name, (int)(bp - ptr), ptr);
			goto cleanup;
		}
		j = i;
		for (; (l = getstr(&key, ekey, ",")) != NULL; i++, key++) {
			/*
			 * Allow empty key (it is valid as string
			 * value).  Thus, we loop at least once and
			 * `i' is incremented.
			 */

			dbg((" key \"%.*s\"", (int)(key - l), l));
			if (i == RTLD_MAX_ENTRY)
				goto no_more;
			if (i != j)
				(void)memcpy(hwptr->entry[i].library, 
				    hwptr->entry[j].library,
				    sizeof(hwptr->entry[j].library));
			hwptr->entry[i].value = exstrdup(l, key);
		}
	}

	if (i == 0) {
		xwarnx("No library entries for `%s'", hwptr->name);
		goto cleanup;
	}

	hwptr->next = *lib_p;
	*lib_p = hwptr;

	return;

cleanup:
	if (hwptr->name)
		xfree(hwptr->name);
	xfree(hwptr);
}