Beispiel #1
0
Datei: args.c Projekt: att/ast
// This routine turns options on and off.
// The options "PDicr" are illegal from set command.
// The -o option is used to set option by name.
// This routine returns the number of non-option arguments.
int sh_argopts(int argc, char *argv[], void *context) {
    Shell_t *shp = context;
    int n, o;
    Arg_t *ap = shp->arg_context;
    Lex_t *lp = shp->lex_context;
    Shopt_t newflags;
    int setflag = 0, action = 0, trace = (int)sh_isoption(shp, SH_XTRACE);
    Namval_t *np = NULL;
    const char *sp;
    char *keylist = NULL;
    int verbose, f, unsetnp = 0;
    Optdisc_t disc;

    newflags = shp->options;
    memset(&disc, 0, sizeof(disc));
    disc.version = OPT_VERSION;
    disc.infof = infof;
    opt_info.disc = &disc;

    if (argc > 0) {
        setflag = 4;
    } else {
        argc = -argc;
    }

    while ((n = optget(argv, setflag ? sh_optset : sh_optksh))) {
        o = 0;
        f = *opt_info.option == '-' && (opt_info.num || opt_info.arg);
        switch (n) {
            case 'A': {
                np = nv_open(opt_info.arg, shp->var_tree, NV_ARRAY | NV_VARNAME);
                if (f) unsetnp = 1;
                continue;
            }
            case 'K': {
                keylist = opt_info.arg;
                continue;
            }
#if SHOPT_BASH
            case 'O': {  // shopt options, only in bash mode
                if (!sh_isoption(shp, SH_BASH)) {
                    errormsg(SH_DICT, ERROR_exit(1), e_option, opt_info.name);
                    __builtin_unreachable();
                }
            }
#endif
            // FALLTHRU
            case 'o': {  // set options
            byname:
                if (!opt_info.arg || !*opt_info.arg || *opt_info.arg == '-') {
                    action = PRINT;
                    // print style: -O => shopt options.
                    // bash => print unset options also, no heading.
                    verbose = (f ? PRINT_VERBOSE : PRINT_NO_HEADER) | (n == 'O' ? PRINT_SHOPT : 0) |
                              (sh_isoption(shp, SH_BASH) ? PRINT_ALL | PRINT_NO_HEADER : 0) |
                              ((opt_info.arg && (!*opt_info.arg || *opt_info.arg == '-'))
                                   ? (PRINT_TABLE | PRINT_NO_HEADER)
                                   : 0);
                    continue;
                }
                o = sh_lookopt(opt_info.arg, &f);
                if (o <= 0 || (!sh_isoption(shp, SH_BASH) && (o & SH_BASHEXTRA)) ||
                    ((!sh_isoption(shp, SH_BASH) || n == 'o') && (o & SH_BASHOPT))

                    || (setflag && (o & SH_COMMANDLINE))) {
                    errormsg(SH_DICT, 2, e_option, opt_info.arg);
                    error_info.errors++;
                }
                o &= 0xff;
                if (sh_isoption(shp, SH_RESTRICTED) && !f && o == SH_RESTRICTED) {
                    errormsg(SH_DICT, ERROR_exit(1), e_restricted, opt_info.arg);
                    __builtin_unreachable();
                }
                break;
            }
#if SHOPT_BASH
            case -1: {  // --rcfile
                shp->gd->rcfile = opt_info.arg;
                continue;
            }
            case -2: {  // --noediting
                if (!f) {
                    off_option(&newflags, SH_VI);
                    off_option(&newflags, SH_EMACS);
                    off_option(&newflags, SH_GMACS);
                }
                continue;
            }
            case -3: {  // --profile
                n = 'l';
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case -4: {  // --posix
                // Mask lower 8 bits to find char in optksh string.
                n &= 0xff;
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case -5: {  // --version
                sfputr(sfstdout, "ksh bash emulation, version ", -1);
                np = nv_open("BASH_VERSION", shp->var_tree, 0);
                sfputr(sfstdout, nv_getval(np), -1);
                np = nv_open("MACHTYPE", shp->var_tree, 0);
                sfprintf(sfstdout, " (%s)\n", nv_getval(np));
                sh_exit(shp, 0);
            }
#endif
            case -6: {  // --default
                const Shtable_t *tp;
                for (tp = shtab_options; (o = tp->sh_number); tp++) {
                    if (!(o & SH_COMMANDLINE) && is_option(&newflags, o & 0xff)) {
                        off_option(&newflags, o & 0xff);
                    }
                }
                continue;
            }
            case -7: {
                f = 0;
                goto byname;
            }
            case 'D': {
                on_option(&newflags, SH_NOEXEC);
                // Cppcheck doesn't recognize the "goto" in the preceding case and thus thinks we
                // might fall through and call strchr() with n == -7.  Even though this it
                // technically a bug in cppcheck it is one reason why `goto` shouldn't be used; at
                // least inside `switch` blocks.
                // cppcheck-suppress invalidFunctionArg
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case 'T': {
                if (opt_info.num) {
                    shp->test |= opt_info.num;
                } else {
                    shp->test = 0;
                }
                continue;
            }
            case 's': {
                if (setflag) {
                    action = SORT;
                    continue;
                }
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case 'R': {
                if (setflag) {
                    n = ':';
                } else {
                    ap->kiafile = opt_info.arg;
                    n = 'n';
                }
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
            case ':': {
                if (opt_info.name[0] == '-' && opt_info.name[1] == '-') {
                    opt_info.arg = argv[opt_info.index - 1] + 2;
                    f = 1;
                    goto byname;
                }
                errormsg(SH_DICT, 2, "%s", opt_info.arg);
                continue;
            }
            case '?': {
                errormsg(SH_DICT, ERROR_usage(0), "%s", opt_info.arg);
                return -1;
            }
            default: {
                sp = strchr(optksh, n);
                if (sp) o = flagval[sp - optksh];
                break;
            }
        }
        if (f) {
            if (o == SH_VI || o == SH_EMACS || o == SH_GMACS) {
                off_option(&newflags, SH_VI);
                off_option(&newflags, SH_EMACS);
                off_option(&newflags, SH_GMACS);
            }
            on_option(&newflags, o);
            off_option(&shp->offoptions, o);
        } else {
            if (o == SH_RESTRICTED && sh_isoption(shp, SH_RESTRICTED)) {
                errormsg(SH_DICT, ERROR_exit(1), e_restricted, "r");
                __builtin_unreachable();
            }
            if (o == SH_XTRACE) trace = 0;
            off_option(&newflags, o);
            if (setflag == 0) on_option(&shp->offoptions, o);
        }
    }
    if (error_info.errors) {
        errormsg(SH_DICT, ERROR_usage(2), "%s", optusage(NULL));
        __builtin_unreachable();
    }
    // Check for '-' or '+' argument.
    sp = argv[opt_info.index];
    if (sp && sp[1] == 0 && (*sp == '+' || *sp == '-') && strcmp(argv[opt_info.index - 1], "--")) {
        opt_info.index++;
        off_option(&newflags, SH_XTRACE);
        off_option(&newflags, SH_VERBOSE);
        trace = 0;
    }
    if (trace) sh_trace(shp, argv, 1);
    argc -= opt_info.index;
    argv += opt_info.index;
    if (action == PRINT) sh_printopts(shp, newflags, verbose, 0);
    if (setflag) {
        if (action == SORT) {
            int (*sortfn)(const char *, const char *) = strcoll;
            Namarr_t *arp;
            struct Value *args;
            unsigned char *bits;
            if (argc > 0) {
                strsort(argv, argc, sortfn);
            } else if (np && (arp = nv_arrayptr(np)) && (args = nv_aivec(np, &bits))) {
                char *cp;
                int i, c, keys = 0;

                if (keylist) {
                    for (cp = keylist; (c = *cp); cp++) {
                        if (c == ',') keys++;
                    }
                    keys++;
                } else {
                    keylist = "";
                }
                arp->nelem = nv_aipack(arp);
                cp = nv_name(np);
                c = strlen(cp);
                // This used to multiply by `(keys - 1)` but `keys` can be zero which means the
                // nodesize can be less than `sizeof(struct Node)` which is obviously wrong.
                // Whether multiplying by `keys` is correct is unclear.
                // See issue #824.
                size_t nodesize = sizeof(struct Node) + keys * sizeof(Namval_t *);
                struct Sort *sp =
                    malloc(sizeof(struct Sort) + strlen(keylist) + (sizeof(char *) + 1) * keys +
                           (arp->nelem + 1) * (nodesize + sizeof(void *)) + c + 3);
                sp->shp = shp;
                sp->np = np;
                if (!(sp->root = shp->last_root)) sp->root = shp->var_tree;
                sp->vp = args;
                sp->cur = 0;
                sp->nodes = (struct Node *)&sp->keys[keys + 2];
                memset(sp->nodes, 0, arp->nelem * nodesize);
                sp->nptrs = (struct Node **)((char *)sp->nodes + arp->nelem * nodesize);
                sp->flags = (char *)&sp->nptrs[arp->nelem + 1];
                memset(sp->flags, 0, keys + 1);
                sp->name = sp->flags + keys + 1;
                memcpy(sp->name, cp, c + 1);
                sp->keys[0] = sp->name + c + 1;
                strcpy(sp->keys[0], keylist);
                cp = (char *)sp->nodes;
                for (c = 0; c < arp->nelem; c++) {
                    if (*keylist && *keylist != ':') {
                        struct Namval *np = FETCH_VT(args[c], np);
                        ((struct Node *)cp)->index = strtol(np->nvname, NULL, 10);
                        ((struct Node *)cp)->bits = bits[c];
                    } else {
                        ((struct Node *)cp)->index = c;
                    }
                    ((struct Node *)cp)->vp = args[c];
                    sp->nptrs[c] = (struct Node *)cp;
                    cp += nodesize;
                }
                if (!(cp = sp->keys[0])) cp = keylist;
                for (keys = 0; (c = *cp); cp++) {
                    if (c == ',') {
                        *cp++ = 0;
                        sp->keys[++keys] = cp;
                        sp->flags[keys] = 0;
                    } else if (c == ':') {
                    again:
                        *cp++ = 0;
                        c = *cp;
                        if (c == 'r') {
                            sp->flags[keys] |= SORT_reverse;
                            c = cp[1];
                        } else if (c == 'n') {
                            sp->flags[keys] |= SORT_numeric;
                            c = cp[1];
                        }
                        if (c == 'n' || c == 'r') goto again;
                    }
                }
                sp->keys[++keys] = 0;
                Sp = sp;
                if (sp->keys[0] && *sp->keys[0]) {
                    sortfn = arraysort;
                } else if (sp->flags[0] & SORT_numeric) {
                    sortfn = numsort;
                } else {
                    sortfn = alphasort;
                }
                strsort((char **)sp->nptrs, arp->nelem, sortfn);
                cp = (char *)sp->nodes;
                for (c = 0; c < arp->nelem; c++) {
                    i = (char *)sp->nptrs[c] - (char *)&sp->nodes[0];
                    if (i / nodesize != c) {
                        args[c] = ((struct Node *)(cp + i))->vp;
                        bits[c] = ((struct Node *)(cp + i))->bits;
                    }
                }
                free(sp);
                nv_close(np);
                np = NULL;
            } else {
                strsort(shp->st.dolv + 1, shp->st.dolc, sortfn);
            }
        }
        if (np) {
            if (unsetnp) nv_unset(np);
            nv_setvec(np, 0, argc, argv);
            nv_close(np);
        } else if (argc > 0 || ((sp = argv[-1]) && strcmp(sp, "--") == 0)) {
            sh_argset(ap, argv - 1);
        }
    } else if (is_option(&newflags, SH_CFLAG)) {
        if (!(shp->comdiv = *argv++)) {
            errormsg(SH_DICT, 2, e_cneedsarg);
            errormsg(SH_DICT, ERROR_usage(2), optusage(NULL));
            __builtin_unreachable();
        }
        argc--;
    }
    // Handling SH_INTERACTIVE and SH_PRIVILEGED has been moved to
    // sh_applyopts(), so that the code can be reused from b_shopt(), too.
    sh_applyopts(shp, newflags);
    if (!ap->kiafile) return argc;

    if (!argv[0]) {
        errormsg(SH_DICT, ERROR_usage(2), "-R requires scriptname");
        __builtin_unreachable();
    }
    if (!(lp->kiafile = sfopen(NULL, ap->kiafile, "w+"))) {
        errormsg(SH_DICT, ERROR_system(3), e_create, ap->kiafile);
        __builtin_unreachable();
    }
    if (!(lp->kiatmp = sftmp(2 * SF_BUFSIZE))) {
        errormsg(SH_DICT, ERROR_system(3), e_tmpcreate);
        __builtin_unreachable();
    }
    sfputr(lp->kiafile, ";vdb;CIAO/ksh", '\n');
    lp->kiabegin = sftell(lp->kiafile);
    lp->entity_tree = dtopen(&_Nvdisc, Dtbag);
    lp->scriptname = strdup(sh_fmtq(argv[0]));
    lp->script = kiaentity(lp, lp->scriptname, -1, 'p', -1, 0, 0, 's', 0, "");
    lp->fscript = kiaentity(lp, lp->scriptname, -1, 'f', -1, 0, 0, 's', 0, "");
    lp->unknown = kiaentity(lp, "<unknown>", -1, 'p', -1, 0, 0, '0', 0, "");
    kiaentity(lp, "<unknown>", -1, 'p', 0, 0, lp->unknown, '0', 0, "");
    lp->current = lp->script;
    ap->kiafile = NULL;

    return argc;
}
Beispiel #2
0
/*
 *  This routine turns options on and off
 *  The options "PDicr" are illegal from set command.
 *  The -o option is used to set option by name
 *  This routine returns the number of non-option arguments
 */
int sh_argopts(int argc,register char *argv[], void *context)
{
	Shell_t		*shp = (Shell_t*)context;
	register int	n,o;
	register Arg_t	*ap = (Arg_t*)(shp->arg_context);
	Lex_t		*lp = (Lex_t*)(shp->lex_context);
	Shopt_t		newflags;
	int setflag=0, action=0, trace=(int)sh_isoption(SH_XTRACE);
	Namval_t *np = NIL(Namval_t*);
	const char *cp;
	int verbose,f;
	Optdisc_t disc;
	newflags=ap->sh->options;
	memset(&disc, 0, sizeof(disc));
	disc.version = OPT_VERSION;
	disc.infof = infof;
	opt_info.disc = &disc;

	if(argc>0)
		setflag = 4;
	else
		argc = -argc;
	while((n = optget(argv,setflag?sh_optset:sh_optksh)))
	{
		o=0;
		f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
		switch(n)
		{
	 	    case 'A':
			np = nv_open(opt_info.arg,ap->sh->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
			if(f)
				nv_unset(np);
			continue;
#if SHOPT_BASH
		    case 'O':	/* shopt options, only in bash mode */
			if(!sh_isoption(SH_BASH))
				errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
#endif
		    case 'o':	/* set options */
		    byname:
			if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
			{
				action = PRINT;
				/* print style: -O => shopt options
				 * bash => print unset options also, no heading
				 */
				verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
					  (n=='O'?PRINT_SHOPT:0)|
					  (sh_isoption(SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
					  ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
				continue;
			}
			o = sh_lookopt(opt_info.arg,&f);
			if(o<=0
				|| (!sh_isoption(SH_BASH) && (o&SH_BASHEXTRA))
				|| ((!sh_isoption(SH_BASH) || n=='o') && (o&SH_BASHOPT))

				|| (setflag && (o&SH_COMMANDLINE)))
			{
				errormsg(SH_DICT,2, e_option, opt_info.arg);
				error_info.errors++;
			}
			o &= 0xff;
			if(sh_isoption(SH_RESTRICTED) && !f && o==SH_RESTRICTED)
				errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
			break;
#if SHOPT_BASH
		    case -1:	/* --rcfile */
			ap->sh->gd->rcfile = opt_info.arg;
			continue;
		    case -2:	/* --noediting */
			if (!f)
			{
				off_option(&newflags,SH_VI);
				off_option(&newflags,SH_EMACS);
				off_option(&newflags,SH_GMACS);
			}
			continue;
		    case -3:	/* --profile */
			n = 'l';
			goto skip;
		    case -4:	/* --posix */
			/* mask lower 8 bits to find char in optksh string */
			n&=0xff;
			goto skip;
		    case -5:	/* --version */
			sfputr(sfstdout, "ksh bash emulation, version ",-1);
			np = nv_open("BASH_VERSION",ap->sh->var_tree,0);
			sfputr(sfstdout, nv_getval(np),-1);
			np = nv_open("MACHTYPE",ap->sh->var_tree,0);
			sfprintf(sfstdout, " (%s)\n", nv_getval(np));
			sh_exit(0);
#endif
		    case -6:	/* --default */
			{
				register const Shtable_t *tp;
				for(tp=shtab_options; o = tp->sh_number; tp++)
					if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
						off_option(&newflags,o&0xff);
			}
		    	continue;
	 	    case -7:
			f = 0;
		    	goto byname;
	 	    case 'D':
			on_option(&newflags,SH_NOEXEC);
			goto skip;
		    case 'T':
			if (opt_info.num)
				ap->sh->test |= opt_info.num;
			else
				ap->sh->test = 0;
		    	continue;
		    case 's':
			if(setflag)
			{
				action = SORT;
				continue;
			}
#if SHOPT_KIA
			goto skip;
		    case 'R':
			if(setflag)
				n = ':';
			else
			{
				ap->kiafile = opt_info.arg;
				n = 'n';
			}
			/*FALLTHROUGH*/
#endif /* SHOPT_KIA */
#if SHOPT_REGRESS
			goto skip;
		    case 'I':
			continue;
#endif /* SHOPT_REGRESS */
		    skip:
		    default:
			if(cp=strchr(optksh,n))
				o = flagval[cp-optksh];
			break;
		    case ':':
			if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
			{
				opt_info.arg = argv[opt_info.index-1] + 2;
				f = 1;
				goto byname;
			}
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			continue;
		    case '?':
			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
			return(-1);
		}
		if(f)
		{
			if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
			{
				off_option(&newflags,SH_VI);
				off_option(&newflags,SH_EMACS);
				off_option(&newflags,SH_GMACS);
			}
			on_option(&newflags,o);
			off_option(&ap->sh->offoptions,o);
		}
		else
		{
			if(o==SH_XTRACE)
				trace = 0;
			off_option(&newflags,o);
			if(setflag==0)
				on_option(&ap->sh->offoptions,o);
		}
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
	/* check for '-' or '+' argument */
	if((cp=argv[opt_info.index]) && cp[1]==0 && (*cp=='+' || *cp=='-') &&
		strcmp(argv[opt_info.index-1],"--"))
	{
		opt_info.index++;
		off_option(&newflags,SH_XTRACE);
		off_option(&newflags,SH_VERBOSE);
		trace = 0;
	}
	if(trace)
		sh_trace(shp,argv,1);
	argc -= opt_info.index;
	argv += opt_info.index;
	if(action==PRINT)
		sh_printopts(newflags,verbose,0);
	if(setflag)
	{
		if(action==SORT)
		{
			if(argc>0)
				strsort(argv,argc,strcoll);
			else
				strsort(ap->sh->st.dolv+1,ap->sh->st.dolc,strcoll);
		}
		if(np)
		{
			nv_setvec(np,0,argc,argv);
			nv_close(np);
		}
		else if(argc>0 || ((cp=argv[-1]) && strcmp(cp,"--")==0))
			sh_argset(ap,argv-1);
	}
	else if(is_option(&newflags,SH_CFLAG))
	{
		if(!(ap->sh->comdiv = *argv++))
		{
			errormsg(SH_DICT,2,e_cneedsarg);
			errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
		}
		argc--;
	}
Beispiel #3
0
int test_unop(Shell_t *shp,register int op,register const char *arg)
{
	struct stat statb;
	int f;
	switch(op)
	{
	    case 'r':
		return(permission(arg, R_OK));
	    case 'w':
		return(permission(arg, W_OK));
	    case 'x':
		return(permission(arg, X_OK));
	    case 'V':
#if SHOPT_FS_3D
	    {
		register int offset = staktell();
		if(stat(arg,&statb)<0 || !S_ISREG(statb.st_mode))
			return(0);
		/* add trailing / */
		stakputs(arg);
		stakputc('/');
		stakputc(0);
		arg = (const char*)stakptr(offset);
		stakseek(offset);
		/* FALL THRU */
	    }
#else
		return(0);
#endif /* SHOPT_FS_3D */
	    case 'd':
		return(test_stat(arg,&statb)>=0 && S_ISDIR(statb.st_mode));
	    case 'c':
		return(test_stat(arg,&statb)>=0 && S_ISCHR(statb.st_mode));
	    case 'b':
		return(test_stat(arg,&statb)>=0 && S_ISBLK(statb.st_mode));
	    case 'f':
		return(test_stat(arg,&statb)>=0 && S_ISREG(statb.st_mode));
	    case 'u':
		return(test_mode(arg)&S_ISUID);
	    case 'g':
		return(test_mode(arg)&S_ISGID);
	    case 'k':
#ifdef S_ISVTX
		return(test_mode(arg)&S_ISVTX);
#else
		return(0);
#endif /* S_ISVTX */
#if SHOPT_TEST_L
	    case 'l':
#endif
	    case 'L':
	    case 'h': /* undocumented, and hopefully will disappear */
		if(*arg==0 || arg[strlen(arg)-1]=='/' || lstat(arg,&statb)<0)
			return(0);
		return(S_ISLNK(statb.st_mode));

	    case 'C':
#ifdef S_ISCTG
		return(test_stat(arg,&statb)>=0 && S_ISCTG(statb.st_mode));
#else
		return(0);
#endif	/* S_ISCTG */
	    case 'H':
#ifdef S_ISCDF
	    {
		register int offset = staktell();
		if(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode))
			return(1);
		stakputs(arg);
		stakputc('+');
		stakputc(0);
		arg = (const char*)stakptr(offset);
		stakseek(offset);
		return(test_stat(arg,&statb)>=0 && S_ISCDF(statb.st_mode));
	    }
#else
		return(0);
#endif	/* S_ISCDF */

	    case 'S':
		return(isasock(arg,&statb));
	    case 'N':
		return(test_stat(arg,&statb)>=0 && tmxgetmtime(&statb) > tmxgetatime(&statb));
	    case 'p':
		return(isapipe(arg,&statb));
	    case 'n':
		return(*arg != 0);
	    case 'z':
		return(*arg == 0);
	    case 's':
		sfsync(sfstdout);
	    case 'O':
	    case 'G':
		if(*arg==0 || test_stat(arg,&statb)<0)
			return(0);
		if(op=='s')
			return(statb.st_size>0);
		else if(op=='O')
			return(statb.st_uid==shp->gd->userid);
		return(statb.st_gid==shp->gd->groupid);
	    case 'a':
	    case 'e':
		if(memcmp(arg,"/dev/",5)==0 && sh_open(arg,O_NONBLOCK))
			return(1);
		return(permission(arg, F_OK));
	    case 'o':
		f=1;
		if(*arg=='?')
			return(sh_lookopt(arg+1,&f)>0);
		op = sh_lookopt(arg,&f);
		return(op && (f==(sh_isoption(op)!=0)));
	    case 't':
	    {
		char *last;
		op = strtol(arg,&last, 10);
		return(*last?0:tty_check(op));
	    }
	    case 'v':
	    case 'R':
	    {
		Namval_t *np;
		Namarr_t *ap;
		int isref;
		if(!(np = nv_open(arg,shp->var_tree,NV_VARNAME|NV_NOFAIL|NV_NOADD|NV_NOREF)))
			return(0);
		isref = nv_isref(np);
		if(op=='R')
			return(isref);
		if(isref)
		{
			if(np->nvalue.cp)
				np = nv_refnode(np);
			else
				return(0);
			
		}
		if(ap = nv_arrayptr(np))
			return(nv_arrayisset(np,ap));
		return(!nv_isnull(np) || nv_isattr(np,NV_INTEGER));
	    }
	    default:
	    {
		static char a[3] = "-?";
		a[1]= op;
		errormsg(SH_DICT,ERROR_exit(2),e_badop,a);
		/* NOTREACHED  */
		return(0);
	    }
	}
}
Beispiel #4
0
int     b_shopt(int argc,register char *argv[],void *extra)
{
        Shell_t *shp = (Shell_t*)extra;
	int n, f, ret=0;
	Shopt_t newflags=shp->options, opt;
	int verbose=PRINT_SHOPT|PRINT_ALL|PRINT_NO_HEADER|PRINT_VERBOSE;
	int setflag=0, quietflag=0, oflag=0;
	memset(&opt,0,sizeof(opt));
#if SHOPT_RAWONLY
	on_option(&newflags,SH_VIRAW);
#endif
	while((n = optget(argv,sh_optshopt)))
	{
		switch(n)
		{
		case 'p':
			verbose&=~PRINT_VERBOSE;
			break;
		case 's':
		case 'u':
			setflag|=n=='s'?SET_SET:SET_UNSET;
			if(setflag==(SET_SET|SET_UNSET))
			{
				errormsg(SH_DICT,ERROR_ERROR,"cannot set and unset options simultaneously");
				error_info.errors++;
			}
			break;
		case 'q':
			quietflag=1;
			break;
		case 'o':
			oflag=1;
			verbose&=~PRINT_SHOPT;
			break;
		case ':':
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			continue;
		case '?':
			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
			return(-1);
		}
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
	argc -= opt_info.index;
	if(argc==0)
	{
		/* no args, -s => mask=current options, -u mask=~(current options)
		   else mask=all bits */
		if(setflag&SET_SET)
			opt=newflags;
		else if(setflag&SET_UNSET)
			for(n=0;n<4;n++)
				opt.v[n]=~newflags.v[n];
		else
			memset(&opt,0xff,sizeof(opt));
		setflag=SET_NOARGS;
	}
	while(argc>0)
	{
		f=1;
		n=sh_lookopt(argv[opt_info.index],&f);
		if(n<=0||(setflag 
			&& (is_option(&opt,SH_INTERACTIVE)
			    || is_option(&opt,SH_RESTRICTED)
			    || is_option(&opt,SH_RESTRICTED2)
			    || is_option(&opt,SH_BASH)
			    || is_option(&opt,SH_LOGIN_SHELL)))
			||(oflag&&(n&SH_BASHOPT)))
		{
			errormsg(SH_DICT,ERROR_ERROR, e_option, argv[opt_info.index]);
			error_info.errors++;
			ret=1;
		}
		else if(f)
			on_option(&opt,n&0xff);
		else
			off_option(&opt,n&0xff);
		opt_info.index++;
		argc--;
	}
	if(setflag&(SET_SET|SET_UNSET))
	{
		if(setflag&SET_SET)
		{
			if(sh_isoption(SH_INTERACTIVE))
				off_option(&opt,SH_NOEXEC);
			if(is_option(&opt,SH_VI)||is_option(&opt,SH_EMACS)||is_option(&opt,SH_GMACS))
			{
				off_option(&newflags,SH_VI);
				off_option(&newflags,SH_EMACS);
				off_option(&newflags,SH_GMACS);
			}
			for(n=0;n<4;n++)
				newflags.v[n] |= opt.v[n];
		}
		else if(setflag&SET_UNSET)
			for(n=0;n<4;n++)
				newflags.v[n] &= ~opt.v[n];
		sh_applyopts(shp,newflags);
		shp->options = newflags;
		if(is_option(&newflags,SH_XTRACE))
			sh_trace(argv,1);
	}
	else if(!(setflag&SET_NOARGS)) /* no -s,-u but args, ret=0 if opt&mask==mask */
	{
		for(n=0;n<4;n++)
			ret+=((newflags.v[n]&opt.v[n])!=opt.v[n]);
	}
	if(!quietflag&&!(setflag&(SET_SET|SET_UNSET)))
		sh_printopts(newflags,verbose,&opt);
	return(ret);
}
Beispiel #5
0
/*
 *  This routine turns options on and off
 *  The options "PDicr" are illegal from set command.
 *  The -o option is used to set option by name
 *  This routine returns the number of non-option arguments
 */
int sh_argopts(int argc,register char *argv[], void *context)
{
	Shell_t		*shp = (Shell_t*)context;
	register int	n,o;
	register Arg_t	*ap = (Arg_t*)(shp->arg_context);
	Lex_t		*lp = (Lex_t*)(shp->lex_context);
	Shopt_t		newflags;
	int setflag=0, action=0, trace=(int)sh_isoption(shp,SH_XTRACE);
	Namval_t *np = NIL(Namval_t*);
	const char *sp;
	char *keylist=0;
	int verbose,f,unsetnp=0;
	Optdisc_t disc;
	newflags=shp->options;
	memset(&disc, 0, sizeof(disc));
	disc.version = OPT_VERSION;
	disc.infof = infof;
	opt_info.disc = &disc;

	if(argc>0)
		setflag = 4;
	else
		argc = -argc;
	while((n = optget(argv,setflag?sh_optset:sh_optksh)))
	{
		o=0;
		f=*opt_info.option=='-' && (opt_info.num || opt_info.arg);
		switch(n)
		{
	 	    case 'A':
			np = nv_open(opt_info.arg,shp->var_tree,NV_NOASSIGN|NV_ARRAY|NV_VARNAME);
			if(f)
				unsetnp=1;
			continue;
	 	    case 'K':
			keylist = opt_info.arg;
			continue;
#if SHOPT_BASH
		    case 'O':	/* shopt options, only in bash mode */
			if(!sh_isoption(shp,SH_BASH))
				errormsg(SH_DICT,ERROR_exit(1), e_option, opt_info.name);
#endif
		    case 'o':	/* set options */
		    byname:
			if(!opt_info.arg||!*opt_info.arg||*opt_info.arg=='-')
			{
				action = PRINT;
				/* print style: -O => shopt options
				 * bash => print unset options also, no heading
				 */
				verbose = (f?PRINT_VERBOSE:PRINT_NO_HEADER)|
					  (n=='O'?PRINT_SHOPT:0)|
					  (sh_isoption(shp,SH_BASH)?PRINT_ALL|PRINT_NO_HEADER:0)|
					  ((opt_info.arg&&(!*opt_info.arg||*opt_info.arg=='-'))?(PRINT_TABLE|PRINT_NO_HEADER):0);
				continue;
			}
			o = sh_lookopt(opt_info.arg,&f);
			if(o<=0
				|| (!sh_isoption(shp,SH_BASH) && (o&SH_BASHEXTRA))
				|| ((!sh_isoption(shp,SH_BASH) || n=='o') && (o&SH_BASHOPT))

				|| (setflag && (o&SH_COMMANDLINE)))
			{
				errormsg(SH_DICT,2, e_option, opt_info.arg);
				error_info.errors++;
			}
			o &= 0xff;
			if(sh_isoption(shp,SH_RESTRICTED) && !f && o==SH_RESTRICTED)
				errormsg(SH_DICT,ERROR_exit(1), e_restricted, opt_info.arg);
			break;
#if SHOPT_BASH
		    case -1:	/* --rcfile */
			shp->gd->rcfile = opt_info.arg;
			continue;
		    case -2:	/* --noediting */
			if (!f)
			{
				off_option(&newflags,SH_VI);
				off_option(&newflags,SH_EMACS);
				off_option(&newflags,SH_GMACS);
			}
			continue;
		    case -3:	/* --profile */
			n = 'l';
			goto skip;
		    case -4:	/* --posix */
			/* mask lower 8 bits to find char in optksh string */
			n&=0xff;
			goto skip;
		    case -5:	/* --version */
			sfputr(sfstdout, "ksh bash emulation, version ",-1);
			np = nv_open("BASH_VERSION",shp->var_tree,0);
			sfputr(sfstdout, nv_getval(np),-1);
			np = nv_open("MACHTYPE",shp->var_tree,0);
			sfprintf(sfstdout, " (%s)\n", nv_getval(np));
			sh_exit(shp,0);
#endif
		    case -6:	/* --default */
			{
				register const Shtable_t *tp;
				for(tp=shtab_options; o = tp->sh_number; tp++)
					if(!(o&SH_COMMANDLINE) && is_option(&newflags,o&0xff))
						off_option(&newflags,o&0xff);
			}
		    	continue;
	 	    case -7:
			f = 0;
		    	goto byname;
	 	    case 'D':
			on_option(&newflags,SH_NOEXEC);
			goto skip;
		    case 'T':
			if (opt_info.num)
				shp->test |= opt_info.num;
			else
				shp->test = 0;
		    	continue;
		    case 's':
			if(setflag)
			{
				action = SORT;
				continue;
			}
#if SHOPT_KIA
			goto skip;
		    case 'R':
			if(setflag)
				n = ':';
			else
			{
				ap->kiafile = opt_info.arg;
				n = 'n';
			}
			/*FALLTHROUGH*/
#endif /* SHOPT_KIA */
#if SHOPT_REGRESS
			goto skip;
		    case 'I':
			continue;
#endif /* SHOPT_REGRESS */
		    skip:
		    default:
			if(sp=strchr(optksh,n))
				o = flagval[sp-optksh];
			break;
		    case ':':
			if(opt_info.name[0]=='-'&&opt_info.name[1]=='-')
			{
				opt_info.arg = argv[opt_info.index-1] + 2;
				f = 1;
				goto byname;
			}
			errormsg(SH_DICT,2, "%s", opt_info.arg);
			continue;
		    case '?':
			errormsg(SH_DICT,ERROR_usage(0), "%s", opt_info.arg);
			return(-1);
		}
		if(f)
		{
			if(o==SH_VI || o==SH_EMACS || o==SH_GMACS)
			{
				off_option(&newflags,SH_VI);
				off_option(&newflags,SH_EMACS);
				off_option(&newflags,SH_GMACS);
			}
			on_option(&newflags,o);
			off_option(&shp->offoptions,o);
		}
		else
		{
			if(o==SH_XTRACE)
				trace = 0;
			off_option(&newflags,o);
			if(setflag==0)
				on_option(&shp->offoptions,o);
		}
	}
	if(error_info.errors)
		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage(NIL(char*)));
	/* check for '-' or '+' argument */
	if((sp=argv[opt_info.index]) && sp[1]==0 && (*sp=='+' || *sp=='-') &&
		strcmp(argv[opt_info.index-1],"--"))
	{
		opt_info.index++;
		off_option(&newflags,SH_XTRACE);
		off_option(&newflags,SH_VERBOSE);
		trace = 0;
	}
	if(trace)
		sh_trace(shp,argv,1);
	argc -= opt_info.index;
	argv += opt_info.index;
	if(action==PRINT)
		sh_printopts(shp,newflags,verbose,0);
	if(setflag)
	{
		if(action==SORT)
		{
			int	(*sortfn)(const char*,const char*) = strcoll;
			Namarr_t	*arp;
			union Value	*args;
			unsigned char	*bits;
			if(argc>0)
				strsort(argv,argc,sortfn);
			else if(np && (arp=nv_arrayptr(np)) && (args = nv_aivec(np,&bits)))
			{
				struct Sort	*sp;
				char		*cp;
				int		i, c, keys=0;
				size_t		nodesize;
				if(keylist)
				{
					for(cp=keylist;c= *cp; cp++)
					{
						if(c==',')
							keys++;
					}
					keys++;
				}
				else
					keylist = Empty;
				arp->nelem = nv_aipack(arp);;
				cp = nv_name(np);
				c = strlen(cp);
				nodesize = sizeof(struct Node)+(keys-1)*sizeof(Namval_t*);
				sp = (struct Sort*)malloc(sizeof(struct Sort)+strlen(keylist)+(sizeof(char*)+1)*keys+(arp->nelem+1)*(nodesize+sizeof(void*))+c+3);
				sp->shp = shp;
				sp->np = np;
				if(!(sp->root = shp->last_root))
					sp->root = shp->var_tree;
				sp->vp = args;
				sp->cur = 0;
				sp->nodes = (struct Node*)&sp->keys[keys+2];
				memset(sp->nodes, 0, arp->nelem*nodesize);
				sp->nptrs = (struct Node**)((char*)sp->nodes+arp->nelem*nodesize);
				sp->flags = (char*)&sp->nptrs[arp->nelem+1];
				memset(sp->flags,0,keys+1);
				sp->name = sp->flags + keys+1;
				memcpy(sp->name,cp,c+1);
				sp->keys[0] = sp->name+c+1;
				strcpy(sp->keys[0],keylist);
				cp = (char*)sp->nodes;
				for(c=0; c < arp->nelem; c++)
				{
					if(keylist!=Empty && *keylist!=':')
					{
						((struct Node*)cp)->index = strtol(args[c].np->nvname,NULL,10);
						((struct Node*)cp)->bits = bits[c];
					}
					else
						((struct Node*)cp)->index = c;
					((struct Node*)cp)->vp = args[c];
					sp->nptrs[c] = (struct Node*)cp;
					cp += nodesize;
				}
				if(!(cp = sp->keys[0]))
					cp = keylist;
				for(keys=0;c= *cp; cp++)
				{
					if(c==',')
					{
						*cp++ = 0;
						sp->keys[++keys] = cp;
						sp->flags[keys] = 0;
					}
					else if(c==':')
					{
					again:
						*cp++ = 0;
						if((c= *cp) == 'r')
						{
							sp->flags[keys] |= SORT_reverse; 
							c = cp[1];
						}
						else if(c=='n')
						{
							sp->flags[keys] |= SORT_numeric; 
							c = cp[1];
						}
						if(c=='n' || c=='r')
							goto again;
						 
					}
				}
				sp->keys[++keys] = 0;
				Sp = sp;
				if(sp->keys[0] && *sp->keys[0])
					sortfn = arraysort;
				else if(sp->flags[0]&SORT_numeric)
					sortfn = numsort;
				else
					sortfn = alphasort;
				strsort((char**)sp->nptrs,arp->nelem,sortfn);
				cp = (char*)sp->nodes;
				for(c=0; c < arp->nelem; c++)
				{
					i = (char*)sp->nptrs[c]-(char*)&sp->nodes[0];
					if(i/nodesize !=c)
					{
						args[c] = ((struct Node*)(cp+i))->vp;
						bits[c] = ((struct Node*)(cp+i))->bits;
					}
				}
				free(sp);
				nv_close(np);
				np = 0;
			}
			else
				strsort(shp->st.dolv+1,shp->st.dolc,sortfn);
		}
		if(np)
		{
			if(unsetnp)
				nv_unset(np);
			nv_setvec(np,0,argc,argv);
			nv_close(np);
		}
		else if(argc>0 || ((sp=argv[-1]) && strcmp(sp,"--")==0))
			sh_argset(ap,argv-1);
	}
	else if(is_option(&newflags,SH_CFLAG))
	{
		if(!(shp->comdiv = *argv++))
		{
			errormsg(SH_DICT,2,e_cneedsarg);
			errormsg(SH_DICT,ERROR_usage(2),optusage(NIL(char*)));
		}
		argc--;
	}