STATIC void minus_o(char *name, int val) { size_t i; if (name == NULL) { if (val) { out1str("Current option settings\n"); for (i = 0; i < NOPTS; i++) { out1fmt("%-16s%s\n", optlist[i].name, optlist[i].val ? "on" : "off"); } } else { out1str("set"); for (i = 0; i < NOPTS; i++) { out1fmt(" %co %s", "+-"[optlist[i].val], optlist[i].name); } out1str("\n"); } } else { for (i = 0; i < NOPTS; i++) if (equal(name, optlist[i].name)) { set_opt_val(i, val); return; } error("Illegal option -o %s", name); } }
/* * The trap builtin. */ int trapcmd(int argc __unused, char **argv) { char *action; int signo; int errors = 0; int i; while ((i = nextopt("l")) != '\0') { switch (i) { case 'l': printsignals(); return (0); } } argv = argptr; if (*argv == NULL) { for (signo = 0 ; signo < sys_nsig ; signo++) { if (signo < NSIG && trap[signo] != NULL) { out1str("trap -- "); out1qstr(trap[signo]); if (signo == 0) { out1str(" EXIT\n"); } else if (sys_signame[signo]) { out1fmt(" %s\n", sys_signame[signo]); } else { out1fmt(" %d\n", signo); } } } return 0; } action = NULL; if (*argv && sigstring_to_signum(*argv) == -1) { if (strcmp(*argv, "-") == 0) argv++; else { action = *argv; argv++; } } for (; *argv; argv++) { if ((signo = sigstring_to_signum(*argv)) == -1) { warning("bad signal %s", *argv); errors = 1; continue; } INTOFF; if (action) action = savestr(action); if (trap[signo]) ckfree(trap[signo]); trap[signo] = action; if (signo != 0) setsignal(signo); INTON; } return errors; }
static void printjobcmd(struct job *jp) { struct procstat *ps; int i; for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) { out1str(ps->cmd); if (i > 0) out1str(" | "); } out1c('\n'); }
/* * Print a list of valid signal names */ static void printsignals(void) { int n; out1str("EXIT "); for (n = 1; n < NSIG; n++) { out1fmt("%s", sys_signame[n]); if ((n == NSIG/2) || n == (NSIG - 1)) out1str("\n"); else out1c(' '); } }
static void minus_o(char *name, int val) { int i; const unsigned char *on; size_t len; if (name == NULL) { if (val) { /* "Pretty" output. */ out1str("Current option settings\n"); for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) out1fmt("%-16.*s%s\n", *on, on + 1, optval[i] ? "on" : "off"); } else { /* Output suitable for re-input to shell. */ for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) out1fmt("%s %co %.*s%s", i % 6 == 0 ? "set" : "", optval[i] ? '-' : '+', *on, on + 1, i % 6 == 5 || i == NOPTS - 1 ? "\n" : ""); } } else { len = strlen(name); for (i = 0, on = optname; i < NOPTS; i++, on += *on + 1) if (*on == len && memcmp(on + 1, name, len) == 0) { setoptionbyindex(i, val); return; } error("Illegal option -o %s", name); } }
static void minus_o(char *name, int val) { int i; if (name == NULL) { if (val) { /* "Pretty" output. */ out1str("Current option settings\n"); for (i = 0; i < NOPTS; i++) out1fmt("%-16s%s\n", optlist[i].name, optlist[i].val ? "on" : "off"); } else { /* Output suitable for re-input to shell. */ for (i = 0; i < NOPTS; i++) out1fmt("%s %co %s%s", i % 6 == 0 ? "set" : "", optlist[i].val ? '-' : '+', optlist[i].name, i % 6 == 5 || i == NOPTS - 1 ? "\n" : ""); } } else { for (i = 0; i < NOPTS; i++) if (equal(name, optlist[i].name)) { setoption(optlist[i].letter, val); return; } error("Illegal option -o %s", name); } }
STATIC void minus_o(char *name, int val) { int i; if (name == NULL) { if (val) { out1str("Current option settings\n"); for (i = 0; i < NOPTS; i++) out1fmt("%-16s%s\n", optnames[i], optlist[i] ? "on" : "off"); } else { for (i = 0; i < NOPTS; i++) out1fmt("set %s %s\n", optlist[i] ? "-o" : "+o", optnames[i]); } } else { for (i = 0; i < NOPTS; i++) if (equal(name, optnames[i])) { optlist[i] = val; return; } sh_error("Illegal option -o %s", name); } }
static void put_prompt(void) { out1str(cmdedit_prompt); cmdedit_x = cmdedit_prmt_len; /* count real x terminal position */ cursor = 0; cmdedit_y = 0; /* new quasireal y */ }
static void put_prompt(void) { out1str(cmdedit_prompt); cmdedit_x = cmdedit_prmt_len; cursor = 0; // Huh? what if cmdedit_prmt_len >= width? cmdedit_y = 0; /* new quasireal y */ }
/* * Print a list of valid signal names */ static void printsignals(void) { int n; out1str("EXIT "); #ifndef HAVE_SYS_SIGNAME init_sys_signame(); #endif for (n = 1; n < NSIG; n++) { out1fmt("%s", sys_signame[n]); if ((n == NSIG/2) || n == (NSIG - 1)) out1str("\n"); else out1c(' '); } }
int bgcmd(int argc, char **argv) { char s[64]; struct job *jp; do { jp = getjob(*++argv); if (jp->jobctl == 0) error("job not created under job control"); if (jp->state == JOBDONE) continue; restartjob(jp); jp->foreground = 0; fmtstr(s, 64, "[%td] ", jp - jobtab + 1); out1str(s); out1str(jp->ps[0].cmd); out1c('\n'); } while (--argc > 1); return 0; }
STATIC void minus_o(char *name, int val) { int doneset, i; if (name == NULL) { if (val) { /* "Pretty" output. */ out1str("Current option settings\n"); for (i = 0; i < NOPTS; i++) out1fmt("%-16s%s\n", optlist[i].name, optlist[i].val ? "on" : "off"); } else { /* Output suitable for re-input to shell. */ for (doneset = i = 0; i < NOPTS; i++) if (optlist[i].val) { if (!doneset) { out1str("set"); doneset = 1; } out1fmt(" -o %s", optlist[i].name); } if (doneset) out1c('\n'); } } else { for (i = 0; i < NOPTS; i++) if (equal(name, optlist[i].name)) { if (!val && privileged && equal(name, "privileged")) { (void) setuid(getuid()); (void) setgid(getgid()); } setoption(optlist[i].letter, val); return; } error("Illegal option -o %s", name); } }
int wordexpcmd(int argc, char **argv) { size_t len; int i; out1fmt("%08x", argc - 1); for (i = 1, len = 0; i < argc; i++) len += strlen(argv[i]); out1fmt("%08x", (int)len); for (i = 1; i < argc; i++) { out1str(argv[i]); out1c('\0'); } return (0); }
int wordexpcmd(shinstance *psh, int argc, char **argv) { size_t len; int i; out1fmt(psh, "%d", argc - 1); out1c(psh, '\0'); for (i = 1, len = 0; i < argc; i++) len += strlen(argv[i]); out1fmt(psh, "%zd", len); out1c(psh, '\0'); for (i = 1; i < argc; i++) { out1str(psh, argv[i]); out1c(psh, '\0'); } return (0); }
int fgcmd(int argc __unused, char **argv) { struct job *jp; pid_t pgrp; int status; jp = getjob(argv[1]); if (jp->jobctl == 0) error("job not created under job control"); out1str(jp->ps[0].cmd); out1c('\n'); flushout(&output); pgrp = jp->ps[0].pid; tcsetpgrp(ttyfd, pgrp); restartjob(jp); jp->foreground = 1; INTOFF; status = waitforjob(jp, (int *)NULL); INTON; return status; }
/* * Print a list of valid signal names. */ static void printsignals(void) { int n, outlen; outlen = 0; for (n = 1; n < sys_nsig; n++) { if (sys_signame[n]) { out1fmt("%s", sys_signame[n]); outlen += strlen(sys_signame[n]); } else { out1fmt("%d", n); outlen += 3; /* good enough */ } ++outlen; if (outlen > 71 || n == sys_nsig - 1) { out1str("\n"); outlen = 0; } else { out1c(' '); } } }
/* * Print a list of valid signal names. */ static void printsignals(void) { int n, outlen; outlen = 0; for (n = 1; n < _NSIG; n++) { if (strsigname(n)) { out1fmt("%s", strsigname(n)); outlen += strlen(strsigname(n)); } else { out1fmt("%d", n); outlen += 3; /* good enough */ } ++outlen; if (outlen > 70 || n == _NSIG - 1) { out1str("\n"); outlen = 0; } else { out1c(' '); } } }
STATIC void showjob(struct job *jp, pid_t pid, int sformat, int lformat) { char s[64]; struct procstat *ps; struct job *j; int col, curr, i, jobno, prev, procno; char c; procno = jp->nprocs; jobno = jp - jobtab + 1; curr = prev = 0; #if JOBS if ((j = getcurjob(NULL)) != NULL) { curr = j - jobtab + 1; if ((j = getcurjob(j)) != NULL) prev = j - jobtab + 1; } #endif for (ps = jp->ps ; ; ps++) { /* for each process */ if (sformat) { out1fmt("%d\n", (int)ps->pid); goto skip; } if (!lformat && ps != jp->ps && pid == 0) goto skip; if (pid != 0 && pid != ps->pid) goto skip; if (jobno == curr && ps == jp->ps) c = '+'; else if (jobno == prev && ps == jp->ps) c = '-'; else c = ' '; if (ps == jp->ps) fmtstr(s, 64, "[%d] %c ", jobno, c); else fmtstr(s, 64, " %c ", c); out1str(s); col = strlen(s); if (lformat) { fmtstr(s, 64, "%d ", (int)ps->pid); out1str(s); col += strlen(s); } s[0] = '\0'; if (ps != jp->ps) { *s = '\0'; } else if (ps->status == -1) { strcpy(s, "Running"); } else if (WIFEXITED(ps->status)) { if (WEXITSTATUS(ps->status) == 0) strcpy(s, "Done"); else fmtstr(s, 64, "Done (%d)", WEXITSTATUS(ps->status)); } else { #if JOBS if (WIFSTOPPED(ps->status)) i = WSTOPSIG(ps->status); else #endif i = WTERMSIG(ps->status); if ((i & 0x7F) < _NSIG && strsiglist(i & 0x7F)) scopy(strsiglist(i & 0x7F), s); else fmtstr(s, 64, "Signal %d", i & 0x7F); if (WCOREDUMP(ps->status)) strcat(s, " (core dumped)"); } out1str(s); col += strlen(s); do { out1c(' '); col++; } while (col < 30); out1str(ps->cmd); out1c('\n'); skip: if (--procno <= 0) break; } }
/* * 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; }
static void showjob(struct job *jp, int mode) { char s[64]; char statestr[64]; struct procstat *ps; struct job *j; int col, curr, i, jobno, prev, procno; char c; procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs; jobno = jp - jobtab + 1; curr = prev = 0; #if JOBS if ((j = getcurjob(NULL)) != NULL) { curr = j - jobtab + 1; if ((j = getcurjob(j)) != NULL) prev = j - jobtab + 1; } #endif ps = jp->ps + jp->nprocs - 1; if (jp->state == 0) { strcpy(statestr, "Running"); #if JOBS } else if (jp->state == JOBSTOPPED) { while (!WIFSTOPPED(ps->status) && ps > jp->ps) ps--; if (WIFSTOPPED(ps->status)) i = WSTOPSIG(ps->status); else i = -1; if (i > 0 && i < sys_nsig && sys_siglist[i]) strcpy(statestr, sys_siglist[i]); else strcpy(statestr, "Suspended"); #endif } else if (WIFEXITED(ps->status)) { if (WEXITSTATUS(ps->status) == 0) strcpy(statestr, "Done"); else fmtstr(statestr, 64, "Done(%d)", WEXITSTATUS(ps->status)); } else { i = WTERMSIG(ps->status); if (i > 0 && i < sys_nsig && sys_siglist[i]) strcpy(statestr, sys_siglist[i]); else fmtstr(statestr, 64, "Signal %d", i); if (WCOREDUMP(ps->status)) strcat(statestr, " (core dumped)"); } for (ps = jp->ps ; ; ps++) { /* for each process */ if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) { out1fmt("%d\n", (int)ps->pid); goto skip; } if (mode != SHOWJOBS_VERBOSE && ps != jp->ps) goto skip; if (jobno == curr && ps == jp->ps) c = '+'; else if (jobno == prev && ps == jp->ps) c = '-'; else c = ' '; if (ps == jp->ps) fmtstr(s, 64, "[%d] %c ", jobno, c); else fmtstr(s, 64, " %c ", c); out1str(s); col = strlen(s); if (mode == SHOWJOBS_VERBOSE) { fmtstr(s, 64, "%d ", (int)ps->pid); out1str(s); col += strlen(s); } if (ps == jp->ps) { out1str(statestr); col += strlen(statestr); } do { out1c(' '); col++; } while (col < 30); if (mode == SHOWJOBS_VERBOSE) { out1str(ps->cmd); out1c('\n'); } else printjobcmd(jp); skip: if (--procno <= 0) break; } }
int trapcmd(int argc, char **argv) { char *action; char **ap; int signo; int errs = 0; int printonly = 0; ap = argv + 1; if (argc == 2 && strcmp(*ap, "-l") == 0) { printsignals(); return 0; } if (argc == 2 && strcmp(*ap, "-") == 0) { for (signo = 0; signo < NSIG; signo++) { if (trap[signo] == NULL) continue; INTOFF; ckfree(trap[signo]); trap[signo] = NULL; if (signo != 0) setsignal(signo, 0); INTON; } return 0; } if (argc >= 2 && strcmp(*ap, "-p") == 0) { printonly = 1; ap++; argc--; } if (argc > 1 && strcmp(*ap, "--") == 0) { argc--; ap++; } if (argc <= 1) { int count; if (printonly) { for (count = 0, signo = 0 ; signo < NSIG ; signo++) if (trap[signo] == NULL) { if (count == 0) out1str("trap -- -"); out1fmt(" %s", trap_signame(signo)); /* oh! unlucky 13 */ if (++count >= 13) { out1str("\n"); count = 0; } } if (count) out1str("\n"); } for (count = 0, signo = 0 ; signo < NSIG ; signo++) if (trap[signo] != NULL && trap[signo][0] == '\0') { if (count == 0) out1str("trap -- ''"); out1fmt(" %s", trap_signame(signo)); /* * the prefix is 10 bytes, with 4 byte * signal names (common) we have room in * the 70 bytes left on a normal line for * 70/(4+1) signals, that's 14, but to * allow for the occasional longer sig name * we output one less... */ if (++count >= 13) { out1str("\n"); count = 0; } } if (count) out1str("\n"); for (signo = 0 ; signo < NSIG ; signo++) if (trap[signo] != NULL && trap[signo][0] != '\0') { out1str("trap -- "); print_quoted(trap[signo]); out1fmt(" %s\n", trap_signame(signo)); } return 0; } action = NULL; if (!printonly && !is_number(*ap)) { if ((*ap)[0] == '-' && (*ap)[1] == '\0') ap++; /* reset to default */ else action = *ap++; /* can be '' for "ignore" */ argc--; } if (argc < 2) { /* there must be at least 1 condition */ out2str("Usage: trap [-l]\n" " trap -p [condition ...]\n" " trap action condition ...\n" " trap N condition ...\n"); return 2; } while (*ap) { signo = signame_to_signum(*ap); if (signo < 0 || signo >= NSIG) { /* This is not a fatal error, so sayeth posix */ outfmt(out2, "trap: '%s' bad condition\n", *ap); errs = 1; ap++; continue; } ap++; if (printonly) { out1str("trap -- "); if (trap[signo] == NULL) out1str("-"); else print_quoted(trap[signo]); out1fmt(" %s\n", trap_signame(signo)); continue; } INTOFF; if (action) action = savestr(action); if (trap[signo]) ckfree(trap[signo]); trap[signo] = action; if (signo != 0) setsignal(signo, 0); INTON; } return errs; }