void sh_applyopts(Shell_t *shp, Shopt_t newflags) { // Cannot set -n for interactive shells since there is no way out. if (sh_isoption(shp, SH_INTERACTIVE)) off_option(&newflags, SH_NOEXEC); if (is_option(&newflags, SH_PRIVILEGED)) on_option(&newflags, SH_NOUSRPROFILE); int is_privileged = is_option(&newflags, SH_PRIVILEGED) != sh_isoption(shp, SH_PRIVILEGED); int is_privileged_off = is_option(&(shp->arg_context)->sh->offoptions, SH_PRIVILEGED); if ((!sh_isstate(shp, SH_INIT) && is_privileged) || (sh_isstate(shp, SH_INIT) && is_privileged_off && shp->gd->userid != shp->gd->euserid)) { if (!is_option(&newflags, SH_PRIVILEGED)) { if (setuid(shp->gd->userid) < 0) { error(ERROR_system(0), "setuid(%d) failed", shp->gd->userid); return; } if (setgid(shp->gd->groupid) < 0) { error(ERROR_system(0), "setgid(%d) failed", shp->gd->groupid); return; } if (shp->gd->euserid == 0) { shp->gd->euserid = shp->gd->userid; shp->gd->egroupid = shp->gd->groupid; } } else if ((shp->gd->userid != shp->gd->euserid && setuid(shp->gd->euserid) < 0) || (shp->gd->groupid != shp->gd->egroupid && setgid(shp->gd->egroupid) < 0) || (shp->gd->userid == shp->gd->euserid && shp->gd->groupid == shp->gd->egroupid)) { off_option(&newflags, SH_PRIVILEGED); } } #if SHOPT_BASH on_option(&newflags, SH_CMDHIST); on_option(&newflags, SH_CHECKHASH); on_option(&newflags, SH_EXECFAIL); on_option(&newflags, SH_EXPAND_ALIASES); on_option(&newflags, SH_HISTAPPEND); on_option(&newflags, SH_INTERACTIVE_COMM); on_option(&newflags, SH_LITHIST); on_option(&newflags, SH_NOEMPTYCMDCOMPL); if (!is_option(&newflags, SH_XPG_ECHO) && sh_isoption(shp, SH_XPG_ECHO)) { astconf("UNIVERSE", 0, "ucb"); } if (is_option(&newflags, SH_XPG_ECHO) && !sh_isoption(shp, SH_XPG_ECHO)) { astconf("UNIVERSE", 0, "att"); } if (is_option(&newflags, SH_HISTORY2) && !sh_isoption(shp, SH_HISTORY2)) { sh_onstate(shp, SH_HISTORY); sh_onoption(shp, SH_HISTORY); } if (!is_option(&newflags, SH_HISTORY2) && sh_isoption(shp, SH_HISTORY2)) { sh_offstate(shp, SH_HISTORY); sh_offoption(shp, SH_HISTORY); } #endif shp->options = newflags; }
int init_jobs(lflag) { register int pid; register int dev; struct stat statbuf; jobstat.mypid = pid = getpid(); savepgrp = getpgrp(pid); if(ioctl(2,SXTIOCSTAT,&status2) < 0) return(-1); if(ioctl(2,TCGETA,&my_stty) < 0) return(-1); if(fstat(2,&statbuf) < 0) return(-1); dev = statbuf.st_rdev&0xff; /* must be channel 0 */ if(dev&07) return(-1); dev >>= 3; sxt[10] = '0' + (dev%10); sxt[9] = '0' + dev/10; my_stty.c_cc[VSWTCH] = CSWTCH; if(ioctl(2,TCSETAF,&my_stty) < 0) return(-1); setpgrp(pid,pid); jobstat.maxjob = MAXPCHAN; on_option(MONITOR); return(0); }
Gobby::ClosableFrame::ClosableFrame(const Glib::ustring& title, const Glib::ustring& icon_name, Preferences::Option<bool>& option): m_option(option), m_allow_visible(true) { CloseButton* button = Gtk::manage(new CloseButton); button->set_hexpand(true); button->set_halign(Gtk::ALIGN_END); button->signal_clicked().connect( sigc::mem_fun(*this, &ClosableFrame::on_clicked)); m_option.signal_changed().connect( sigc::mem_fun(*this, &ClosableFrame::on_option)); button->show(); Gtk::Image* image = Gtk::manage( new Gtk::Image); image->set_from_icon_name(icon_name, Gtk::ICON_SIZE_MENU); image->show(); Gtk::Label* label_title = Gtk::manage( new Gtk::Label(title, Gtk::ALIGN_START)); label_title->show(); m_grid.set_border_width(6); m_grid.set_column_spacing(6); m_grid.set_row_spacing(6); m_grid.attach(*image, 0, 0, 1, 1); m_grid.attach(*label_title, 1, 0, 1, 1); m_grid.attach(*button, 2, 0, 1, 1); m_grid.show(); add(m_grid); on_option(); }
int init_jobs(lflag) { int ldisc; register int ntry = 0; register int pid; jobstat.mypid = pid = getpid(); savepgrp = getpgrp(pid); # ifdef version8 if((ldisc = ioctl (2, FIOLOOKLD, 0)) <0) # else if(ioctl(2,TIOCGETD,&ldisc) !=0) # endif /* version8 */ return(-1); if(ldisc!=NTTYDISC && ldisc!=OTTYDISC) { /* no job control when running with MPX */ # ifdef VSH on_option(VIRAW); # endif /* VSH */ return(-1); } retry: signal(SIGTTOU,SIG_IGN); if(ioctl(2,TIOCGPGRP,&savetgrp) !=0) { fputs(j_not_tty,output); return(-1); } /* This shell must be in foreground to change state */ if(savetgrp != savepgrp) { signal(SIGTTOU,SIG_DFL); kill(pid,SIGTTOU); /* wait for continue and try again */ if(ntry++ > 100) { fputs(j_no_start,output); return(-1); } goto retry; } if(ldisc == OTTYDISC) { ldisc = NTTYDISC; # ifdef version8 ioctl(2,TIOCGETP,&my_stty); if (ioctl(2, FIOPOPLD, 0) < 0) return(-1); if (ioctl(2, FIOPUSHLD, &ldisc, 0) < 0) { ldisc = OTTYDISC; ioctl(2, FIOPUSHLD, &ldisc, 0); return(-1); } ioctl(2,TIOCSETN,&my_stty); # else if(ioctl(2,TIOCSETD,&ldisc) !=0) return(-1); # endif /* version8 */ if(lflag==0) { fputs(j_newtty,output); old_driver++; } } on_option(MONITOR); signal(SIGCHLD,fault); signal(SIGTSTP,SIG_IGN); signal(SIGTTIN,SIG_IGN); setpgrp(pid,pid); set_ttygrp(pid); return(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, 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; }
/* * 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--; }
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); }
/* * 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--; }