Пример #1
0
/* parse command line & set command arguments.  returns the index of
 * non-option arguments, -1 if there is an error.
 */
int
parse_args(char **argv,
        int     what,           /* OF_CMDLINE or OF_SET */
        int     *setargsp)
{
        static char cmd_opts[NELEM(options) + 3]; /* o:\0 */
        static char set_opts[NELEM(options) + 5]; /* Ao;s\0 */
        char *opts;
        char *array = (char *) 0;
        Getopt go;
        int i, optc, set, sortargs = 0, arrayset = 0;

        /* First call?  Build option strings... */
        if (cmd_opts[0] == '\0') {
                char *p, *q;

                /* see cmd_opts[] declaration */
                strlcpy(cmd_opts, "o:", sizeof cmd_opts);
                p = cmd_opts + strlen(cmd_opts);
                /* see set_opts[] declaration */
                strlcpy(set_opts, "A:o;s", sizeof set_opts);
                q = set_opts + strlen(set_opts);
                for (i = 0; i < NELEM(options); i++) {
                        if (options[i].c) {
                                if (options[i].flags & OF_CMDLINE)
                                        *p++ = options[i].c;
                                if (options[i].flags & OF_SET)
                                        *q++ = options[i].c;
                        }
                }
                *p = '\0';
                *q = '\0';
        }

        if (what == OF_CMDLINE) {
                opts = cmd_opts;
        } else
                opts = set_opts;
        ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT);
        while ((optc = ksh_getopt(argv, &go, opts)) != -1) {
                set = (go.info & GI_PLUS) ? 0 : 1;
                switch (optc) {
                  case 'A':
                        arrayset = set ? 1 : -1;
                        array = go.optarg;
                        break;

                  case 'o':
                        if (go.optarg == (char *) 0) {
                                /* lone -o: print options
                                 *
                                 * Note that on the command line, -o requires
                                 * an option (ie, can't get here if what is
                                 * OF_CMDLINE).
                                 */
                                printoptions(set);
                                break;
                        }
                        i = option(go.optarg);
                        if (i >= 0 && set == Flag(i))
                                /* Don't check the context if the flag
                                 * isn't changing - makes "set -o interactive"
                                 * work if you're already interactive.  Needed
                                 * if the output of "set +o" is to be used.
                                 */
                                ;
                        else if (i >= 0 && (options[i].flags & what))
                                change_flag((enum sh_flag) i, what, set);
                        else {
                                bi_errorf("%s: bad option", go.optarg);
                                return -1;
                        }
                        break;

                  case '?':
                        return -1;

                  default:
                        /* -s: sort positional params (at&t ksh stupidity) */
                        if (what == OF_SET && optc == 's') {
                                sortargs = 1;
                                break;
                        }
                        for (i = 0; i < NELEM(options); i++)
                                if (optc == options[i].c
                                    && (what & options[i].flags))
                                {
                                        change_flag((enum sh_flag) i, what,
                                                set);
                                        break;
                                }
                        if (i == NELEM(options)) {
                                internal_errorf(1, "parse_args: `%c'", optc);
                                return -1; /* not reached */
                        }
                }
        }
        if (!(go.info & GI_MINUSMINUS) && argv[go.optind] &&
                (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') &&
                argv[go.optind][1] == '\0')
        {
                /* lone - clears -v and -x flags */
                if (argv[go.optind][0] == '-' && !Flag(FPOSIX))
                        Flag(FVERBOSE) = Flag(FXTRACE) = 0;
                /* set skips lone - or + option */
                go.optind++;
        }
        if (setargsp)
                /* -- means set $#/$* even if there are no arguments */
                *setargsp = !arrayset && ((go.info & GI_MINUSMINUS) ||
                        argv[go.optind]);

        if (arrayset && (!*array || *skip_varname(array, false))) {
                bi_errorf("%s: is not an identifier", array);
                return -1;
        }
        if (sortargs) {
                for (i = go.optind; argv[i]; i++)
                        ;
                qsortp((void **) &argv[go.optind], (size_t) (i - go.optind),
                        xstrcmp);
        }
        if (arrayset) {
                set_array(array, arrayset, argv + go.optind);
                for (; argv[go.optind]; go.optind++)
                        ;
        }

        return go.optind;
}
Пример #2
0
static int
x_command_glob(int flags, const char *str, int slen, char ***wordsp)
{
	char *toglob;
	char *pat;
	char *fpath;
	int nwords;
	XPtrV w;
	struct block *l;

	if (slen < 0)
		return 0;

	toglob = add_glob(str, slen);

	/* Convert "foo*" (toglob) to a pattern for future use */
	pat = evalstr(toglob, DOPAT|DOTILDE);
	afree(toglob, ATEMP);

	XPinit(w, 32);

	glob_table(pat, &w, &keywords);
	glob_table(pat, &w, &aliases);
	glob_table(pat, &w, &builtins);
	for (l = e->loc; l; l = l->next)
		glob_table(pat, &w, &l->funs);

	glob_path(flags, pat, &w, path);
	if ((fpath = str_val(global("FPATH"))) != null)
		glob_path(flags, pat, &w, fpath);

	nwords = XPsize(w);

	if (!nwords) {
		*wordsp = NULL;
		XPfree(w);
		return 0;
	}

	/* Sort entries */
	if (flags & XCF_FULLPATH) {
		/* Sort by basename, then path order */
		struct path_order_info *info;
		struct path_order_info *last_info = NULL;
		char **words = (char **) XPptrv(w);
		int path_order = 0;
		int i;

		info = areallocarray(NULL, nwords,
		    sizeof(struct path_order_info), ATEMP);

		for (i = 0; i < nwords; i++) {
			info[i].word = words[i];
			info[i].base = x_basename(words[i], NULL);
			if (!last_info || info[i].base != last_info->base ||
			    strncmp(words[i], last_info->word, info[i].base) != 0) {
				last_info = &info[i];
				path_order++;
			}
			info[i].path_order = path_order;
		}
		qsort(info, nwords, sizeof(struct path_order_info),
			path_order_cmp);
		for (i = 0; i < nwords; i++)
			words[i] = info[i].word;
		afree(info, ATEMP);
	} else {
		/* Sort and remove duplicate entries */
		char **words = (char **) XPptrv(w);
		int i, j;

		qsortp(XPptrv(w), (size_t) nwords, xstrcmp);

		for (i = j = 0; i < nwords - 1; i++) {
			if (strcmp(words[i], words[i + 1]))
				words[j++] = words[i];
			else
				afree(words[i], ATEMP);
		}
		words[j++] = words[i];
		nwords = j;
		w.cur = (void **) &words[j];
	}

	XPput(w, NULL);
	*wordsp = (char **) XPclose(w);

	return nwords;
}