int evalcmd(shinstance *psh, int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(psh, concat); ap = argv + 2; for (;;) { while (*p) STPUTC(psh, *p++, concat); if ((p = *ap++) == NULL) break; STPUTC(psh, ' ', concat); } STPUTC(psh, '\0', concat); p = grabstackstr(psh, concat); } evalstring(psh, p, EV_TESTED); } return psh->exitstatus; }
int evalcmd(int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(concat); ap = argv + 2; for (;;) { while (*p) STPUTC(*p++, concat); if ((p = *ap++) == NULL) break; STPUTC(' ', concat); } STPUTC('\0', concat); p = grabstackstr(concat); } evalstring(p); } return exitstatus; }
/* * Called to execute a trap. Perhaps we should avoid entering new trap * handlers while we are executing a trap handler. */ void dotrap(void) { int i; int savestatus; in_dotrap++; for (;;) { for (i = 1; i < _NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; if (trap[i]) { /* * Ignore SIGCHLD to avoid infinite * recursion if the trap action does * a fork. */ if (i == SIGCHLD) ignore_sigchld++; savestatus = exitstatus; evalstring(trap[i]); exitstatus = savestatus; if (i == SIGCHLD) ignore_sigchld--; } break; } } if (i >= _NSIG) break; } in_dotrap--; pendingsigs = 0; }
int evalcmd(int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(concat); ap = argv + 2; for (;;) { concat = stputs(p, concat); if ((p = *ap++) == NULL) break; STPUTC(' ', concat); } STPUTC('\0', concat); p = grabstackstr(concat); } return evalstring(p, ~SKIPEVAL); } return 0; }
void exitshell(void) { struct jmploc loc; char *p; volatile int status; #ifdef HETIO hetio_reset_term(); #endif status = exitstatus; TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); if (setjmp(loc.loc)) { if (exception == EXEXIT) status = exitstatus; goto out; } handler = &loc; if ((p = trap[0])) { trap[0] = NULL; evalskip = 0; evalstring(p, 0); } out: /* * Disable job control so that whoever had the foreground before we * started can get it back. */ if (likely(!setjmp(loc.loc))) setjobctl(0); flushall(); _exit(status); /* NOTREACHED */ }
void exitshell(int status) { struct jmploc loc1, loc2; char *p; TRACE(("pid %d, exitshell(%d)\n", getpid(), status)); if (setjmp(loc1.loc)) { goto l1; } if (setjmp(loc2.loc)) { goto l2; } handler = &loc1; if ((p = trap[0]) != NULL && *p != '\0') { trap[0] = NULL; evalstring(p, 0); } l1: handler = &loc2; /* probably unnecessary */ flushall(); #if JOBS setjobctl(0); #endif l2: _exit(status); /* NOTREACHED */ }
void dotrap(void) { char *p; char *q; int i; int savestatus; savestatus = exitstatus; pendingsigs = 0; barrier(); for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) { if (!*q) continue; *q = 0; p = trap[i + 1]; if (!p) continue; evalstring(p, 0); exitstatus = savestatus; if (evalskip) break; } }
SH_NORETURN_1 void exitshell(shinstance *psh, int status) { struct jmploc loc1, loc2; char *p; TRACE((psh, "pid %d, exitshell(%d)\n", sh_getpid(psh), status)); if (setjmp(loc1.loc)) { goto l1; } if (setjmp(loc2.loc)) { goto l2; } psh->handler = &loc1; if ((p = psh->trap[0]) != NULL && *p != '\0') { psh->trap[0] = NULL; evalstring(psh, p, 0); } l1: psh->handler = &loc2; /* probably unnecessary */ output_flushall(psh); #if JOBS setjobctl(psh, 0); #endif l2: sh__exit(psh, status); /* NOTREACHED */ }
int evalcmd(int argc, char **argv) { char *p; char *concat; char **ap; if (argc > 1) { p = argv[1]; if (argc > 2) { STARTSTACKSTR(concat); ap = argv + 2; for (;;) { STPUTS(p, concat); if ((p = *ap++) == NULL) break; STPUTC(' ', concat); } STPUTC('\0', concat); p = grabstackstr(concat); } evalstring(p, builtin_flags); } else exitstatus = 0; return exitstatus; }
void dotrap(void) { int i; int savestatus; char *tr; for (;;) { for (i = 1 ; ; i++) { if (i >= NSIG) { pendingsigs = 0; return; } if (gotsig[i]) break; } gotsig[i] = 0; savestatus=exitstatus; CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: \"%s\"\n", i, trap[i] ? trap[i] : "-NULL-")); tr = savestr(trap[i]); /* trap code may free trap[i] */ evalstring(tr, 0); ckfree(tr); exitstatus=savestatus; } }
void exitshell(void) { struct jmploc loc; char *p; savestatus = exitstatus; TRACE(("pid %d, exitshell(%d)\n", getpid(), savestatus)); if (setjmp(loc.loc)) goto out; handler = &loc; if ((p = trap[0])) { trap[0] = NULL; evalskip = 0; evalstring(p, 0); } out: /* * Disable job control so that whoever had the foreground before we * started can get it back. */ if (likely(!setjmp(loc.loc))) setjobctl(0); flushall(); _exit(savestatus); /* NOTREACHED */ }
void dotrap(void) { int i; char *tr; int savestatus; struct skipsave saveskip; in_dotrap++; CTRACE(DBG_TRAP, ("dotrap[%d]: %d pending, traps %sinvalid\n", in_dotrap, pendingsigs, traps_invalid ? "" : "not ")); for (;;) { pendingsigs = 0; for (i = 1 ; ; i++) { if (i >= NSIG) return; if (gotsig[i]) break; } gotsig[i] = 0; if (traps_invalid) continue; tr = trap[i]; CTRACE(DBG_TRAP|DBG_SIG, ("dotrap %d: %s%s%s\n", i, tr ? "\"" : "", tr ? tr : "NULL", tr ? "\"" : "")); if (tr != NULL) { last_trapsig = i; save_skipstate(&saveskip); savestatus = exitstatus; tr = savestr(tr); /* trap code may free trap[i] */ evalstring(tr, 0); ckfree(tr); if (current_skipstate() == SKIPNONE || saveskip.state != SKIPNONE) { restore_skipstate(&saveskip); exitstatus = savestatus; } } } in_dotrap--; }
void exitshell_savedstatus(void) { struct jmploc loc1, loc2; char *p; int sig = 0; sigset_t sigs; if (!exiting) { if (in_dotrap && last_trapsig) { sig = last_trapsig; exiting_exitstatus = sig + 128; } else exiting_exitstatus = oexitstatus; } exitstatus = oexitstatus = exiting_exitstatus; if (setjmp(loc1.loc)) { goto l1; } if (setjmp(loc2.loc)) { goto l2; } handler = &loc1; if ((p = trap[0]) != NULL && *p != '\0') { /* * Reset evalskip, or the trap on EXIT could be * interrupted if the last command was a "return". */ evalskip = 0; trap[0] = NULL; evalstring(p, 0); } l1: handler = &loc2; /* probably unnecessary */ flushall(); #if JOBS setjobctl(0); #endif l2: if (sig != 0 && sig != SIGSTOP && sig != SIGTSTP && sig != SIGTTIN && sig != SIGTTOU) { signal(sig, SIG_DFL); sigemptyset(&sigs); sigaddset(&sigs, sig); sigprocmask(SIG_UNBLOCK, &sigs, NULL); kill(getpid(), sig); /* If the default action is to ignore, fall back to _exit(). */ } _exit(exiting_exitstatus); }
void dotrap(shinstance *psh) { int i; int savestatus; for (;;) { for (i = 1 ; ; i++) { if (psh->gotsig[i - 1]) break; if (i >= NSIG) goto done; } psh->gotsig[i - 1] = 0; savestatus=psh->exitstatus; evalstring(psh, psh->trap[i], 0); psh->exitstatus=savestatus; } done: psh->pendingsigs = 0; }
void dotrap(void) { int i; int savestatus; for (;;) { for (i = 1 ; ; i++) { if (gotsig[i - 1]) break; if (i >= NSIG) goto done; } gotsig[i - 1] = 0; savestatus=exitstatus; evalstring(trap[i], 0); exitstatus=savestatus; } done: pendingsigs = 0; }
void dotrap(void) { char *p; char *q; int i; int status, last_status; if (!pendingsigs) return; status = savestatus; last_status = status; if (likely(status < 0)) { status = exitstatus; savestatus = status; } pendingsigs = 0; barrier(); for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) { if (!*q) continue; if (evalskip) { pendingsigs = i + 1; break; } *q = 0; p = trap[i + 1]; if (!p) continue; evalstring(p, 0); if (evalskip != SKIPFUNC) exitstatus = status; } savestatus = last_status; }
int main(int argc, char **argv) { struct jmploc jmploc; struct stackmark smark; volatile int state; char *shinit; setlocale(LC_ALL, ""); /* Just a --version for show. */ if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '-') { if (!strcmp(&argv[1][2], "version")) { printf("kmk_ash - kBuild version %d.%d.%d\n", KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); return 0; } if (!strcmp(&argv[1][2], "help")) { printf("usage: kmk_ash [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] [command_file [argument ...]]\n" " or: kmk_ash -c [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] command_string [command_name [argument ...]]\n" " or: kmk_ash -s [-aCefnuvxIimqVEb] [+aCefnuvxIimqVEb] [-o option_name]\n" " [+o option_name] [argument ...]\n" " or: kmk_ash --help\n" " or: kmk_ash --version\n", argv[0], argv[0], argv[0], argv[0], argv[0]); return 0; } } #if PROFILE monitor(4, etext, profile_buf, sizeof profile_buf, 50); #endif state = 0; if (setjmp(jmploc.loc)) { /* * When a shell procedure is executed, we raise the * exception EXSHELLPROC to clean up before executing * the shell procedure. */ switch (exception) { case EXSHELLPROC: rootpid = getpid(); rootshell = 1; minusc = NULL; state = 3; break; case EXEXEC: exitstatus = exerrno; break; case EXERROR: exitstatus = 2; break; default: break; } if (exception != EXSHELLPROC) { if (state == 0 || iflag == 0 || ! rootshell) exitshell(exitstatus); } reset(); if (exception == EXINT #if ATTY && (! attyset() || equal(termval(), "emacs")) #endif ) { out2c('\n'); flushout(&errout); } popstackmark(&smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } handler = &jmploc; #ifdef DEBUG #if DEBUG == 2 debug = 1; #endif opentrace(); trputs("Shell args: "); trargs(argv); #endif rootpid = getpid(); rootshell = 1; #ifdef _MSC_VER { extern void init_syntax(void); init_syntax(); } #endif init(); setstackmark(&smark); procargs(argc, argv); if (argv[0] && argv[0][0] == '-') { state = 1; #ifndef KMK read_profile("/etc/profile"); #endif state1: state = 2; #ifndef KMK read_profile(".profile"); #endif } state2: state = 3; #ifndef KMK if (getuid() == geteuid() && getgid() == getegid()) { if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(shinit); } } #endif state3: state = 4; if (sflag == 0 || minusc) { static int sigs[] = { SIGINT, SIGQUIT, SIGHUP, #ifdef SIGTSTP SIGTSTP, #endif SIGPIPE }; #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) int i; for (i = 0; i < SIGSSIZE; i++) setsignal(sigs[i], 0); } if (minusc) evalstring(minusc, 0); if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(1); } #if PROFILE monitor(0); #endif exitshell(exitstatus); /* NOTREACHED */ }
int main(int argc, char *argv[]) { struct stackmark smark, smark2; volatile int state; char *shinit; #ifdef CBSD char *MY_APP = NULL; char *cbsdpath = NULL; char *workdir = NULL; char *cbsd_disable_history = NULL; //getenv chdir("/var/empty"); /* Only use history when stdin is a tty. */ if ( isatty(0) && isatty(1) ) { cbsd_enable_history = 1; } #endif (void) setlocale(LC_ALL, ""); initcharset(); state = 0; if (setjmp(main_handler.loc)) { switch (exception) { case EXEXEC: exitstatus = exerrno; break; case EXERROR: exitstatus = 2; break; default: break; } if (state == 0 || iflag == 0 || ! rootshell || exception == EXEXIT) exitshell(exitstatus); reset(); if (exception == EXINT) out2fmt_flush("\n"); popstackmark(&smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } handler = &main_handler; #ifdef DEBUG opentrace(); trputs("Shell args: "); trargs(argv); #endif rootpid = getpid(); rootshell = 1; INTOFF; initvar(); setstackmark(&smark); setstackmark(&smark2); #ifdef CBSD if (argc>1) { if (!strcmp(argv[1],"--help")) { system("/usr/local/bin/cbsd help"); exit(0); } else { if (!strcmp(argv[1],"version")) { printf("%s\n",VERSION); exit(0); } } } cbsd_disable_history=lookupvar("NO_CBSD_HISTORY"); if ( cbsd_disable_history != NULL ) cbsd_enable_history=0; workdir=lookupvar("workdir"); if ( workdir == NULL ) { read_profile("/etc/rc.conf"); setvarsafe("workdir", lookupvar("cbsd_workdir"), 0); } workdir=lookupvar("workdir"); if ( workdir == NULL ) { out2fmt_flush("cbsd: no workdir defined\n"); exitshell(1); } setvarsafe("PS1","cbsd@\\h> ",1); setvarsafe("workdir",workdir,1); workdir=lookupvar("workdir"); // ^^ after "setsave*" original is free cbsdpath = calloc(MAXPATHLEN, sizeof(char *)); if (argv[1]) { setvarsafe("CBSD_APP",basename(argv[1]),1); } if (cbsdpath == NULL) { out2fmt_flush("cbsd: out of memory for cbsdpath\n"); exitshell(1); } // %s/modules must be first for opportunity to have a module commands greater priority than the original CBSD command. // This makes it possible to write a 3rd party modules with altered functionality of the original code. sprintf(cbsdpath,"%s/modules:%s/bin:%s/sbin:%s/tools:%s/jailctl:%s/nodectl:%s/system:/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin",workdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir,cbsd_distdir); setvarsafe("PATH",cbsdpath,1); ckfree(cbsdpath); // read global params first (disable/enable colors, repos etc..) read_profile("${workdir}/etc/defaults/global.conf"); read_profile("${workdir}/etc/global.conf"); if (lookupvar("NOCOLOR") != NULL ) { putenv("NOCOLOR=1"); } // non-interactive global env if (lookupvar("NOINTER") != NULL ) { setvarsafe("inter","1",1); putenv("inter=0"); } read_profile("/usr/local/cbsd/cbsd.conf"); read_profile("${workdir}/etc/defaults/logger.conf"); read_profile("${workdir}/etc/logger.conf"); if (cbsd_enable_history==1) { cbsd_history_file=calloc(MAXPATHLEN, sizeof(char *)); sprintf(cbsd_history_file,"%s/%s",workdir,CBSD_HISTORYFILE); } #endif procargs(argc, argv); pwd_init(iflag); INTON; #ifndef CBSD if (iflag) chkmail(1); #endif if (argv[0] && argv[0][0] == '-') { state = 1; read_profile("/etc/profile"); state1: state = 2; if (privileged == 0) read_profile("${HOME-}/.profile"); else read_profile("/etc/suid_profile"); } state2: state = 3; if (!privileged && iflag) { if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(shinit); } } state3: state = 4; popstackmark(&smark2); if (minusc) { evalstring(minusc, sflag ? 0 : EV_EXIT); } state4: if (sflag || minusc == NULL) { cmdloop(1); } exitshell(exitstatus); /*NOTREACHED*/ return 0; }
/* * This command is provided since POSIX decided to standardize * the Korn shell fc command. Oh well... */ int histcmd(volatile int argc, char ** volatile argv) { int ch; const char * volatile editor = NULL; HistEvent he; volatile int lflg = 0, nflg = 0, rflg = 0, sflg = 0; int i, retval; const char *firststr, *laststr; int first, last, direction; char * volatile pat = NULL, * volatile repl; /* ksh "fc old=new" crap */ static int active = 0; struct jmploc jmploc; struct jmploc *volatile savehandler; char editfile[MAXPATHLEN + 1]; FILE * volatile efp; #ifdef __GNUC__ repl = NULL; /* XXX gcc4 */ efp = NULL; /* XXX gcc4 */ #endif if (hist == NULL) error("history not active"); if (argc == 1) error("missing history argument"); optreset = 1; optind = 1; /* initialize getopt */ while (not_fcnumber(argv[optind]) && (ch = getopt(argc, argv, ":e:lnrs")) != -1) switch ((char)ch) { case 'e': editor = optionarg; break; case 'l': lflg = 1; break; case 'n': nflg = 1; break; case 'r': rflg = 1; break; case 's': sflg = 1; break; case ':': error("option -%c expects argument", optopt); /* NOTREACHED */ case '?': default: error("unknown option: -%c", optopt); /* NOTREACHED */ } argc -= optind, argv += optind; /* * If executing... */ if (lflg == 0 || editor || sflg) { lflg = 0; /* ignore */ editfile[0] = '\0'; /* * Catch interrupts to reset active counter and * cleanup temp files. */ savehandler = handler; if (setjmp(jmploc.loc)) { active = 0; if (*editfile) unlink(editfile); handler = savehandler; longjmp(handler->loc, 1); } handler = &jmploc; if (++active > MAXHISTLOOPS) { active = 0; displayhist = 0; error("called recursively too many times"); } /* * Set editor. */ if (sflg == 0) { if (editor == NULL && (editor = bltinlookup("FCEDIT", 1)) == NULL && (editor = bltinlookup("EDITOR", 1)) == NULL) editor = DEFEDITOR; if (editor[0] == '-' && editor[1] == '\0') { sflg = 1; /* no edit */ editor = NULL; } } } /* * If executing, parse [old=new] now */ if (lflg == 0 && argc > 0 && ((repl = strchr(argv[0], '=')) != NULL)) { pat = argv[0]; *repl++ = '\0'; argc--, argv++; } /* * If -s is specified, accept only one operand */ if (sflg && argc >= 2) error("too many args"); /* * determine [first] and [last] */ switch (argc) { case 0: firststr = lflg ? "-16" : "-1"; laststr = "-1"; break; case 1: firststr = argv[0]; laststr = lflg ? "-1" : argv[0]; break; case 2: firststr = argv[0]; laststr = argv[1]; break; default: error("too many args"); /* NOTREACHED */ } /* * Turn into event numbers. */ first = str_to_event(firststr, 0); last = str_to_event(laststr, 1); if (rflg) { i = last; last = first; first = i; } /* * XXX - this should not depend on the event numbers * always increasing. Add sequence numbers or offset * to the history element in next (diskbased) release. */ direction = first < last ? H_PREV : H_NEXT; /* * If editing, grab a temp file. */ if (editor) { int fd; INTOFF; /* easier */ snprintf(editfile, sizeof(editfile), "%s_shXXXXXX", _PATH_TMP); if ((fd = mkstemp(editfile)) < 0) error("can't create temporary file %s", editfile); if ((efp = fdopen(fd, "w")) == NULL) { close(fd); error("can't allocate stdio buffer for temp"); } } /* * Loop through selected history events. If listing or executing, * do it now. Otherwise, put into temp file and call the editor * after. * * The history interface needs rethinking, as the following * convolutions will demonstrate. */ history(hist, &he, H_FIRST); retval = history(hist, &he, H_NEXT_EVENT, first); for (;retval != -1; retval = history(hist, &he, direction)) { if (lflg) { if (!nflg) out1fmt("%5d ", he.num); out1str(he.str); } else { const char *s = pat ? fc_replace(he.str, pat, repl) : he.str; if (sflg) { if (displayhist) { out2str(s); } evalstring(strcpy(stalloc(strlen(s) + 1), s), 0); if (displayhist && hist) { /* * XXX what about recursive and * relative histnums. */ history(hist, &he, H_ENTER, s); } break; } else fputs(s, efp); } /* * At end? (if we were to lose last, we'd sure be * messed up). */ if (he.num == last) break; } if (editor) { char *editcmd; size_t cmdlen; fclose(efp); cmdlen = strlen(editor) + strlen(editfile) + 2; editcmd = stalloc(cmdlen); snprintf(editcmd, cmdlen, "%s %s", editor, editfile); evalstring(editcmd, 0); /* XXX - should use no JC command */ INTON; readcmdfile(editfile); /* XXX - should read back - quick tst */ unlink(editfile); } if (lflg == 0 && active > 0) --active; if (displayhist) displayhist = 0; return 0; }
/* * Called to execute a trap. Perhaps we should avoid entering new trap * handlers while we are executing a trap handler. */ void dotrap(void) { int i; int savestatus, prev_evalskip, prev_skipcount; in_dotrap++; for (;;) { pendingsig = 0; for (i = 1; i < NSIG; i++) { if (gotsig[i]) { gotsig[i] = 0; if (trap[i]) { /* * Ignore SIGCHLD to avoid infinite * recursion if the trap action does * a fork. */ if (i == SIGCHLD) ignore_sigchld++; /* * Backup current evalskip * state and reset it before * executing a trap, so that the * trap is not disturbed by an * ongoing break/continue/return * statement. */ prev_evalskip = evalskip; prev_skipcount = skipcount; evalskip = 0; last_trapsig = i; savestatus = exitstatus; evalstring(trap[i], 0); /* * If such a command was not * already in progress, allow a * break/continue/return in the * trap action to have an effect * outside of it. */ if (evalskip == 0 || prev_evalskip != 0) { evalskip = prev_evalskip; skipcount = prev_skipcount; exitstatus = savestatus; } if (i == SIGCHLD) ignore_sigchld--; } break; } } if (i >= NSIG) break; } in_dotrap--; }
int main(int argc, char *argv[]) { struct stackmark smark, smark2; volatile int state; char *shinit; (void) setlocale(LC_ALL, ""); initcharset(); state = 0; if (setjmp(main_handler.loc)) { switch (exception) { case EXEXEC: exitstatus = exerrno; break; case EXERROR: exitstatus = 2; break; default: break; } if (state == 0 || iflag == 0 || ! rootshell || exception == EXEXIT) exitshell(exitstatus); reset(); if (exception == EXINT) out2fmt_flush("\n"); popstackmark(&smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } handler = &main_handler; #ifdef DEBUG opentrace(); trputs("Shell args: "); trargs(argv); #endif rootpid = getpid(); rootshell = 1; init(); setstackmark(&smark); setstackmark(&smark2); procargs(argc, argv); pwd_init(iflag); if (iflag) chkmail(1); if (argv[0] && argv[0][0] == '-') { state = 1; read_profile("/etc/profile"); state1: state = 2; if (privileged == 0) read_profile("${HOME-}/.profile"); else read_profile("/etc/suid_profile"); } state2: state = 3; if (!privileged && iflag) { if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(shinit); } } state3: state = 4; popstackmark(&smark2); if (minusc) { evalstring(minusc, sflag ? 0 : EV_EXIT); } if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(1); } exitshell(exitstatus); /*NOTREACHED*/ return 0; }
SH_NORETURN_1 void shell_main(shinstance *psh, int argc, char **argv) { struct jmploc jmploc; struct stackmark smark; volatile int state; char *shinit; state = 0; if (setjmp(jmploc.loc)) { /* * When a shell procedure is executed, we raise the * exception EXSHELLPROC to clean up before executing * the shell procedure. */ switch (psh->exception) { case EXSHELLPROC: psh->rootpid = /*getpid()*/ psh->pid; psh->rootshell = 1; psh->minusc = NULL; state = 3; break; case EXEXEC: psh->exitstatus = psh->exerrno; break; case EXERROR: psh->exitstatus = 2; break; default: break; } if (psh->exception != EXSHELLPROC) { if (state == 0 || iflag(psh) == 0 || ! psh->rootshell) exitshell(psh, psh->exitstatus); } reset(psh); if (psh->exception == EXINT #if ATTY && (! attyset(psh) || equal(termval(psh), "emacs")) #endif ) { out2c(psh, '\n'); flushout(&psh->errout); } popstackmark(psh, &smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } psh->handler = &jmploc; psh->rootpid = /*getpid()*/ psh->pid; psh->rootshell = 1; #ifdef DEBUG #if DEBUG == 2 debug(psh) = 1; #endif opentrace(psh); trputs(psh, "Shell args: "); trargs(psh, argv); #endif init(psh); setstackmark(psh, &smark); procargs(psh, argc, argv); if (argv[0] && argv[0][0] == '-') { state = 1; read_profile(psh, "/etc/profile"); state1: state = 2; read_profile(psh, ".profile"); } state2: state = 3; if (sh_getuid(psh) == sh_geteuid(psh) && sh_getgid(psh) == sh_getegid(psh)) { if ((shinit = lookupvar(psh, "ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(psh, shinit); } } state3: state = 4; if (sflag(psh) == 0 || psh->minusc) { static int sigs[] = { SIGINT, SIGQUIT, SIGHUP, #ifdef SIGTSTP SIGTSTP, #endif SIGPIPE }; #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) unsigned i; for (i = 0; i < SIGSSIZE; i++) setsignal(psh, sigs[i], 0); } if (psh->minusc) evalstring(psh, psh->minusc, 0); if (sflag(psh) || psh->minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(psh, 1); } exitshell(psh, psh->exitstatus); /* NOTREACHED */ }
int main(int argc, char **argv) { char *shinit; volatile int state; struct jmploc jmploc; struct stackmark smark; int login; int i; for (i = 1; i < argc; i++) { if (0 == strcmp(argv[i], "--help") || 0 == strcmp(argv[i], "-h")) { sxsh_print_usage(); return (0); } if (0 == strcmp(argv[i], "--version") || 0 == strcmp(argv[i], "-v")) { sxsh_print_version(); return (0); } } #ifdef __GLIBC__ dash_errno = __errno_location(); #endif #if PROFILE monitor(4, etext, profile_buf, sizeof profile_buf, 50); #endif state = 0; if (unlikely(setjmp(jmploc.loc))) { int e; int s; reset(); e = exception; s = state; if (e == EXEXIT || s == 0 || iflag == 0 || shlvl) exitshell(); if (e == EXINT #if ATTY && (! attyset() || equal(termval(), "emacs")) #endif ) { out2c('\n'); #ifdef FLUSHERR flushout(out2); #endif } popstackmark(&smark); FORCEINTON; /* enable interrupts */ if (s == 1) goto state1; else if (s == 2) goto state2; else if (s == 3) goto state3; else goto state4; } handler = &jmploc; #ifdef DEBUG opentrace(); trputs("Shell args: "); trargs(argv); #endif rootpid = getpid(); init(); setstackmark(&smark); login = procargs(argc, argv); if (login) { state = 1; read_profile("/etc/profile"); state1: state = 2; read_profile("$HOME/.profile"); } state2: state = 3; if ( #ifndef linux getuid() == geteuid() && getgid() == getegid() && #endif iflag ) { if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { read_profile(shinit); } } popstackmark(&smark); state3: state = 4; if (minusc) evalstring(minusc, sflag ? 0 : EV_EXIT); if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(1); } #if PROFILE monitor(0); #endif #if GPROF { extern void _mcleanup(void); _mcleanup(); } #endif exitshell(); /* NOTREACHED */ }
int main(int argc, char **argv) { struct stackmark smark; volatile int state; char *shinit; uid_t uid; gid_t gid; uid = getuid(); gid = getgid(); max_user_fd = fcntl(0, F_MAXFD); if (max_user_fd < 2) max_user_fd = 2; setlocale(LC_ALL, ""); posix = getenv("POSIXLY_CORRECT") != NULL; #if PROFILE monitor(4, etext, profile_buf, sizeof profile_buf, 50); #endif state = 0; if (setjmp(main_handler.loc)) { /* * When a shell procedure is executed, we raise the * exception EXSHELLPROC to clean up before executing * the shell procedure. */ switch (exception) { case EXSHELLPROC: rootpid = getpid(); rootshell = 1; minusc = NULL; state = 3; break; case EXEXEC: exitstatus = exerrno; break; case EXERROR: exitstatus = 2; break; default: break; } if (exception != EXSHELLPROC) { if (state == 0 || iflag == 0 || ! rootshell || exception == EXEXIT) exitshell(exitstatus); } reset(); if (exception == EXINT) { out2c('\n'); flushout(&errout); } popstackmark(&smark); FORCEINTON; /* enable interrupts */ if (state == 1) goto state1; else if (state == 2) goto state2; else if (state == 3) goto state3; else goto state4; } handler = &main_handler; #ifdef DEBUG #if DEBUG >= 2 debug = 1; /* this may be reset by procargs() later */ #endif opentrace(); trputs("Shell args: "); trargs(argv); #if DEBUG >= 3 set_debug(((DEBUG)==3 ? "_@" : "++"), 1); #endif #endif rootpid = getpid(); rootshell = 1; init(); initpwd(); setstackmark(&smark); procargs(argc, argv); /* * Limit bogus system(3) or popen(3) calls in setuid binaries, * by requiring the -p flag */ if (!pflag && (uid != geteuid() || gid != getegid())) { setuid(uid); setgid(gid); /* PS1 might need to be changed accordingly. */ choose_ps1(); } if (argv[0] && argv[0][0] == '-') { state = 1; read_profile("/etc/profile"); state1: state = 2; read_profile(".profile"); } state2: state = 3; if ((iflag || !posix) && getuid() == geteuid() && getgid() == getegid()) { struct stackmark env_smark; setstackmark(&env_smark); if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') { state = 3; read_profile(expandenv(shinit)); } popstackmark(&env_smark); } state3: state = 4; line_number = 1; /* undo anything from profile files */ if (sflag == 0 || minusc) { static int sigs[] = { SIGINT, SIGQUIT, SIGHUP, #ifdef SIGTSTP SIGTSTP, #endif SIGPIPE }; #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0])) size_t i; for (i = 0; i < SIGSSIZE; i++) setsignal(sigs[i], 0); } if (minusc) evalstring(minusc, sflag ? 0 : EV_EXIT); if (sflag || minusc == NULL) { state4: /* XXX ??? - why isn't this before the "if" statement */ cmdloop(1); if (iflag) { out2str("\n"); flushout(&errout); } } #if PROFILE monitor(0); #endif line_number = plinno; exitshell(exitstatus); /* NOTREACHED */ }
void exitshell_savedstatus(void) { struct jmploc loc; char *p; volatile int sig = 0; int s; sigset_t sigs; CTRACE(DBG_ERRS|DBG_PROCS|DBG_CMDS|DBG_TRAP, ("pid %d: exitshell_savedstatus()%s $?=%d xs=%d dt=%d ts=%d\n", getpid(), exiting ? " exiting" : "", exitstatus, exiting_status, in_dotrap, last_trapsig)); if (!exiting) { if (in_dotrap && last_trapsig) { sig = last_trapsig; exiting_status = sig + 128; } else exiting_status = exitstatus; } exitstatus = exiting_status; if (!setjmp(loc.loc)) { handler = &loc; if (!traps_invalid && (p = trap[0]) != NULL && *p != '\0') { reset_eval(); trap[0] = NULL; VTRACE(DBG_TRAP, ("exit trap: \"%s\"\n", p)); evalstring(p, 0); } } INTOFF; /* we're done, no more interrupts. */ if (!setjmp(loc.loc)) { handler = &loc; /* probably unnecessary */ flushall(); #if JOBS setjobctl(0); #endif } if ((s = sig) != 0 && s != SIGSTOP && s != SIGTSTP && s != SIGTTIN && s != SIGTTOU) { struct rlimit nocore; /* * if the signal is of the core dump variety, don't... */ nocore.rlim_cur = nocore.rlim_max = 0; (void) setrlimit(RLIMIT_CORE, &nocore); signal(s, SIG_DFL); sigemptyset(&sigs); sigaddset(&sigs, s); sigprocmask(SIG_UNBLOCK, &sigs, NULL); kill(getpid(), s); } _exit(exiting_status); /* NOTREACHED */ }