static Char * handleone(Char *str, Char **vl, int action) { size_t chars; Char **t, *p, *strp; switch (action) { case G_ERROR: setname(short2str(str)); blkfree(vl); stderror(ERR_NAME | ERR_AMBIG); break; case G_APPEND: chars = 0; for (t = vl; (p = *t++) != NULL; chars++) chars += Strlen(p); str = xmalloc(chars * sizeof(Char)); for (t = vl, strp = str; (p = *t++) != '\0'; chars++) { while (*p) *strp++ = *p++ & TRIM; *strp++ = ' '; } *--strp = '\0'; blkfree(vl); break; case G_IGNORE: str = Strsave(strip(*vl)); blkfree(vl); break; default: break; } return (str); }
void vffree(int sig) { register char **v; if (v = gargv) gargv = 0, blkfree(v); if (v = pargv) pargv = 0, blkfree(v); _exit(1); }
void setq(Char *name, Char **vec, struct varent *p) { struct varent *c; int f; f = 0; /* tree hangs off the header's left link */ while ((c = p->v_link[f]) != NULL) { if ((f = *name - *c->v_name) == 0 && (f = Strcmp(name, c->v_name)) == 0) { blkfree(c->vec); goto found; } p = c; f = f > 0; } p->v_link[f] = c = (struct varent *) xmalloc((size_t) sizeof(struct varent)); c->v_name = Strsave(name); c->v_bal = 0; c->v_left = c->v_right = 0; c->v_parent = p; balance(p, f, 0); found: trim(c->vec = vec); }
void setq(const Char *name, Char **vec, struct varent *p, int flags) { struct varent *c; int f; f = 0; /* tree hangs off the header's left link */ while ((c = p->v_link[f]) != 0) { if ((f = *name - *c->v_name) == 0 && (f = Strcmp(name, c->v_name)) == 0) { if (c->v_flags & VAR_READONLY) stderror(ERR_READONLY|ERR_NAME, c->v_name); blkfree(c->vec); c->v_flags = flags; trim(c->vec = vec); return; } p = c; f = f > 0; } p->v_link[f] = c = xmalloc(sizeof(struct varent)); c->v_name = Strsave(name); c->v_flags = flags; c->v_bal = 0; c->v_left = c->v_right = 0; c->v_parent = p; balance(p, f, 0); trim(c->vec = vec); }
void pintr1(int wantnl) { Char **v; sigset_t nsigset, osigset; sigemptyset(&nsigset); (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); if (setintr) { nsigset = osigset; (void)sigdelset(&nsigset, SIGINT); (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); if (pjobs) { pjobs = 0; (void)fprintf(cshout, "\n"); dojobs(jobargv, NULL); stderror(ERR_NAME | ERR_INTR); } } (void)sigdelset(&osigset, SIGCHLD); (void)sigprocmask(SIG_SETMASK, &osigset, NULL); (void)fpurge(cshout); (void)endpwent(); /* * If we have an active "onintr" then we search for the label. Note that if * one does "onintr -" then we shan't be interruptible so we needn't worry * about that here. */ if (gointr) { gotolab(gointr); timflg = 0; if ((v = pargv) != NULL) pargv = 0, blkfree(v); if ((v = gargv) != NULL) gargv = 0, blkfree(v); reset(); } else if (intty && wantnl) { (void)fputc('\r', cshout); (void)fputc('\n', cshout); } stderror(ERR_SILENT); /* NOTREACHED */ }
void blk_indirect_cleanup(void *xptr) { Char ***ptr; ptr = xptr; blkfree(*ptr); xfree(ptr); }
/* * $ substitute one word, for i/o redirection */ Char * Dfix1(Char *cp) { Char *Dv[2], **expanded; if (noexec) return (0); Dv[0] = cp; Dv[1] = NULL; expanded = Dfix2(Dv); if (expanded[0] == NULL || expanded[1] != NULL) { blkfree(expanded); setname(short2str(cp)); stderror(ERR_NAME | ERR_AMBIG); } cp = Strsave(expanded[0]); blkfree(expanded); return (cp); }
void set1(Char *var, Char **vec, struct varent *head) { Char **oldv = vec; gflag = 0; tglob(oldv); if (gflag) { vec = globall(oldv); if (vec == 0) { blkfree(oldv); stderror(ERR_NAME | ERR_NOMATCH); return; } blkfree(oldv); gargv = 0; } setq(var, vec, head); }
static void globzap(void) { if (globbed) { blkfree(globbed); free(globbed); } globbed = NULL; globcnt = 0; }
/* * $ substitute one word, for i/o redirection */ Char * Dfix1(Char *cp) { Char *Dv[2]; if (noexec) return (0); Dv[0] = cp; Dv[1] = NULL; Dfix2(Dv); if (gargc != 1) { setname(vis_str(cp)); stderror(ERR_NAME | ERR_AMBIG); } cp = Strsave(gargv[0]); blkfree(gargv), gargv = 0; return (cp); }
static void unsetv1(struct varent *p) { struct varent *c, *pp; int f; /* * Free associated memory first to avoid complications. */ blkfree(p->vec); xfree(p->v_name); /* * If p is missing one child, then we can move the other into where p is. * Otherwise, we find the predecessor of p, which is guaranteed to have no * right child, copy it into p, and move it's left child into it. */ if (p->v_right == 0) c = p->v_left; else if (p->v_left == 0) c = p->v_right; else { for (c = p->v_left; c->v_right; c = c->v_right) continue; p->v_name = c->v_name; p->v_flags = c->v_flags; p->vec = c->vec; p = c; c = p->v_left; } /* * Move c into where p is. */ pp = p->v_parent; f = pp->v_right == p; if ((pp->v_link[f] = c) != 0) c->v_parent = pp; /* * Free the deleted node, and rebalance. */ xfree(p); balance(pp, f, 1); }
/* * $ substitute one word, for i/o redirection */ tchar * Dfix1(tchar *cp) { tchar *Dv[2]; #ifdef TRACE tprintf("TRACE- Dfix1()\n"); #endif if (noexec) return (0); Dv[0] = cp; Dv[1] = NOSTR; Dfix2(Dv); if (gargc != 1) { setname(cp); bferr("Ambiguous"); } cp = savestr(gargv[0]); blkfree(gargv), gargv = 0; return (cp); }
/* * Fix up the $ expansions and quotations in the * argument list to command t. */ void Dfix(struct command *t) { Char **pp; Char *p; if (noexec) return; /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ for (pp = t->t_dcom; (p = *pp++) != NULL;) for (; *p; p++) { if (cmap(*p, _DOL | QUOTES)) { /* $, \, ', ", ` */ Dfix2(t->t_dcom); /* found one */ blkfree(t->t_dcom); t->t_dcom = gargv; gargv = 0; return; } } }
/* * Fix up the $ expansions and quotations in the * argument list to command t. */ void Dfix(struct command *t) { tchar **pp; tchar *p; #ifdef TRACE tprintf("TRACE- Dfix()\n"); #endif if (noexec) return; /* Note that t_dcom isn't trimmed thus !...:q's aren't lost */ for (pp = t->t_dcom; p = *pp++; ) while (*p) if (cmap(*p++, _DOL|QUOTES)) { /* $, \, ', ", ` */ Dfix2(t->t_dcom); /* found one */ blkfree(t->t_dcom); t->t_dcom = gargv; gargv = 0; return; } }
void set1(const Char *var, Char **vec, struct varent *head, int flags) { Char **oldv = vec; if ((flags & VAR_NOGLOB) == 0) { int gflag; gflag = tglob(oldv); if (gflag) { vec = globall(oldv, gflag); if (vec == 0) { blkfree(oldv); stderror(ERR_NAME | ERR_NOMATCH); } blkfree(oldv); } } /* * Uniqueness addition from: Michael Veksler <*****@*****.**> */ if ( flags & (VAR_FIRST | VAR_LAST) ) { /* * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. * Method: * Delete all duplicate words leaving "holes" in the word array (vec). * Then remove the "holes", keeping the order of the words unchanged. */ if (vec && vec[0] && vec[1]) { /* more than one word ? */ int i, j; int num_items; for (num_items = 0; vec[num_items]; num_items++) continue; if (flags & VAR_FIRST) { /* delete duplications, keeping first occurance */ for (i = 1; i < num_items; i++) for (j = 0; j < i; j++) /* If have earlier identical item, remove i'th item */ if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { xfree(vec[i]); vec[i] = NULL; break; } } else if (flags & VAR_LAST) { /* delete duplications, keeping last occurance */ for (i = 0; i < num_items - 1; i++) for (j = i + 1; j < num_items; j++) /* If have later identical item, remove i'th item */ if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { /* remove identical item (the first) */ xfree(vec[i]); vec[i] = NULL; } } /* Compress items - remove empty items */ for (j = i = 0; i < num_items; i++) if (vec[i]) vec[j++] = vec[i]; /* NULL-fy remaining items */ for (; j < num_items; j++) vec[j] = NULL; } /* don't let the attribute propagate */ flags &= ~(VAR_FIRST|VAR_LAST); } setq(var, vec, head, flags); }
/* * Print the error with the given id. * * Special ids: * ERR_SILENT: Print nothing. * ERR_OLD: Print the previously set error if one was there. * otherwise return. * ERR_NAME: If this bit is set, print the name of the function * in bname * * This routine always resets or exits. The flag haderr * is set so the routine who catches the unwind can propogate * it if they want. * * Note that any open files at the point of error will eventually * be closed in the routine process in sh.c which is the only * place error unwinds are ever caught. */ void stderror(int id, ...) { va_list va; Char **v; int flags; flags = id & ERR_FLAGS; id &= ~ERR_FLAGS; if ((flags & ERR_OLD) && seterr == NULL) abort(); if (id < 0 || id > (int)(sizeof(errorlist) / sizeof(errorlist[0]))) id = ERR_INVALID; (void)fflush(cshout); (void)fflush(csherr); haderr = 1; /* Now to diagnostic output */ timflg = 0; /* This isn't otherwise reset */ if (!(flags & ERR_SILENT)) { if (flags & ERR_NAME) (void)fprintf(csherr, "%s: ", bname); if ((flags & ERR_OLD)) /* Old error. */ (void)fprintf(csherr, "%s.\n", seterr); else { va_start(va, id); (void)vfprintf(csherr, errorlist[id], va); va_end(va); (void)fprintf(csherr, ".\n"); } } if (seterr) { xfree((ptr_t) seterr); seterr = NULL; } if ((v = pargv) != NULL) pargv = 0, blkfree(v); if ((v = gargv) != NULL) gargv = 0, blkfree(v); (void)fflush(cshout); (void)fflush(csherr); didfds = 0; /* Forget about 0,1,2 */ /* * Go away if -e or we are a child shell */ if (exiterr || child) xexit(1); /* * Reset the state of the input. This buffered seek to end of file will * also clear the while/foreach stack. */ btoeof(); set(STRstatus, Strsave(STR1)); if (tpgrp > 0) (void)tcsetpgrp(FSHTTY, tpgrp); reset(); /* Unwind */ }
void execute(struct command *t, int wtty, int *pipein, int *pipeout) { static sigset_t csigset, ocsigset; static int nosigchld = 0, onosigchld = 0; volatile int wanttty = wtty; struct biltins * volatile bifunc; int pv[2], pid; sigset_t nsigset; int forked; UNREGISTER(forked); UNREGISTER(bifunc); UNREGISTER(wanttty); forked = 0; pid = 0; if (t == 0) return; if (t->t_dflg & F_AMPERSAND) wanttty = 0; switch (t->t_dtyp) { case NODE_COMMAND: if ((t->t_dcom[0][0] & (QUOTE | TRIM)) == QUOTE) (void)Strcpy(t->t_dcom[0], t->t_dcom[0] + 1); if ((t->t_dflg & F_REPEAT) == 0) Dfix(t); /* $ " ' \ */ if (t->t_dcom[0] == 0) return; /* FALLTHROUGH */ case NODE_PAREN: if (t->t_dflg & F_PIPEOUT) mypipe(pipeout); /* * Must do << early so parent will know where input pointer should be. * If noexec then this is all we do. */ if (t->t_dflg & F_READ) { (void)close(0); heredoc(t->t_dlef); if (noexec) (void)close(0); } set(STRstatus, Strsave(STR0)); /* * This mess is the necessary kludge to handle the prefix builtins: * nice, nohup, time. These commands can also be used by themselves, * and this is not handled here. This will also work when loops are * parsed. */ while (t->t_dtyp == NODE_COMMAND) if (eq(t->t_dcom[0], STRnice)) { if (t->t_dcom[1]) { if (strchr("+-", t->t_dcom[1][0])) { if (t->t_dcom[2]) { setname("nice"); t->t_nice = getn(t->t_dcom[1]); lshift(t->t_dcom, 2); t->t_dflg |= F_NICE; } else break; } else { t->t_nice = 4; lshift(t->t_dcom, 1); t->t_dflg |= F_NICE; } } else break; } else if (eq(t->t_dcom[0], STRnohup)) { if (t->t_dcom[1]) { t->t_dflg |= F_NOHUP; lshift(t->t_dcom, 1); } else break; } else if (eq(t->t_dcom[0], STRtime)) { if (t->t_dcom[1]) { t->t_dflg |= F_TIME; lshift(t->t_dcom, 1); } else break; } else break; /* is it a command */ if (t->t_dtyp == NODE_COMMAND) { /* * Check if we have a builtin function and remember which one. */ bifunc = isbfunc(t); if (noexec && bifunc != NULL) { /* * Continue for builtins that are part of the scripting language */ if (bifunc->bfunct != dobreak && bifunc->bfunct != docontin && bifunc->bfunct != doelse && bifunc->bfunct != doend && bifunc->bfunct != doforeach && bifunc->bfunct != dogoto && bifunc->bfunct != doif && bifunc->bfunct != dorepeat && bifunc->bfunct != doswbrk && bifunc->bfunct != doswitch && bifunc->bfunct != dowhile && bifunc->bfunct != dozip) break; } } else { /* not a command */ bifunc = NULL; if (noexec) break; } /* * We fork only if we are timed, or are not the end of a parenthesized * list and not a simple builtin function. Simple meaning one that is * not pipedout, niced, nohupped, or &'d. It would be nice(?) to not * fork in some of these cases. */ /* * Prevent forking cd, pushd, popd, chdir cause this will cause the * shell not to change dir! */ if (bifunc && (bifunc->bfunct == dochngd || bifunc->bfunct == dopushd || bifunc->bfunct == dopopd)) t->t_dflg &= ~(F_NICE); if (((t->t_dflg & F_TIME) || ((t->t_dflg & F_NOFORK) == 0 && (!bifunc || t->t_dflg & (F_PIPEOUT | F_AMPERSAND | F_NICE | F_NOHUP)))) || /* * We have to fork for eval too. */ (bifunc && (t->t_dflg & (F_PIPEIN | F_PIPEOUT)) != 0 && bifunc->bfunct == doeval)) { if (t->t_dtyp == NODE_PAREN || t->t_dflg & (F_REPEAT | F_AMPERSAND) || bifunc) { forked++; /* * We need to block SIGCHLD here, so that if the process does * not die before we can set the process group */ if (wanttty >= 0 && !nosigchld) { sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGCHLD); (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset); nosigchld = 1; } pid = pfork(t, wanttty); if (pid == 0 && nosigchld) { (void)sigprocmask(SIG_SETMASK, &csigset, NULL); nosigchld = 0; } else if (pid != 0 && (t->t_dflg & F_AMPERSAND)) backpid = pid; } else { int ochild, osetintr, ohaderr, odidfds; int oSHIN, oSHOUT, oSHERR, oOLDSTD, otpgrp; sigset_t osigset; /* * Prepare for the vfork by saving everything that the child * corrupts before it exec's. Note that in some signal * implementations which keep the signal info in user space * (e.g. Sun's) it will also be necessary to save and restore * the current sigaction's for the signals the child touches * before it exec's. */ if (wanttty >= 0 && !nosigchld && !noexec) { sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGCHLD); (void)sigprocmask(SIG_BLOCK, &nsigset, &csigset); nosigchld = 1; } sigemptyset(&nsigset); (void)sigaddset(&nsigset, SIGCHLD); (void)sigaddset(&nsigset, SIGINT); (void)sigprocmask(SIG_BLOCK, &nsigset, &osigset); ochild = child; osetintr = setintr; ohaderr = haderr; odidfds = didfds; oSHIN = SHIN; oSHOUT = SHOUT; oSHERR = SHERR; oOLDSTD = OLDSTD; otpgrp = tpgrp; ocsigset = csigset; onosigchld = nosigchld; Vsav = Vdp = 0; Vexpath = 0; Vt = 0; pid = vfork(); if (pid < 0) { (void)sigprocmask(SIG_SETMASK, &osigset, NULL); stderror(ERR_NOPROC); } forked++; if (pid) { /* parent */ child = ochild; setintr = osetintr; haderr = ohaderr; didfds = odidfds; SHIN = oSHIN; SHOUT = oSHOUT; SHERR = oSHERR; OLDSTD = oOLDSTD; tpgrp = otpgrp; csigset = ocsigset; nosigchld = onosigchld; xfree((ptr_t) Vsav); Vsav = 0; xfree((ptr_t) Vdp); Vdp = 0; xfree((ptr_t) Vexpath); Vexpath = 0; blkfree((Char **) Vt); Vt = 0; /* this is from pfork() */ palloc(pid, t); (void)sigprocmask(SIG_SETMASK, &osigset, NULL); } else { /* child */ /* this is from pfork() */ int pgrp; int ignint = 0; if (nosigchld) { (void)sigprocmask(SIG_SETMASK, &csigset, NULL); nosigchld = 0; } if (setintr) ignint = (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) || (gointr && eq(gointr, STRminus)); pgrp = pcurrjob ? pcurrjob->p_jobid : getpid(); child++; if (setintr) { setintr = 0; if (ignint) { (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); } else { (void)signal(SIGINT, vffree); (void)signal(SIGQUIT, SIG_DFL); } if (wanttty >= 0) { (void)signal(SIGTSTP, SIG_DFL); (void)signal(SIGTTIN, SIG_DFL); (void)signal(SIGTTOU, SIG_DFL); } (void)signal(SIGTERM, parterm); } else if (tpgrp == -1 && (t->t_dflg & F_NOINTERRUPT)) { (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); } pgetty(wanttty, pgrp); if (t->t_dflg & F_NOHUP) (void)signal(SIGHUP, SIG_IGN); if (t->t_dflg & F_NICE) (void)setpriority(PRIO_PROCESS, 0, t->t_nice); } } } if (pid != 0) { /* * It would be better if we could wait for the whole job when we * knew the last process had been started. Pwait, in fact, does * wait for the whole job anyway, but this test doesn't really * express our intentions. */ if (didfds == 0 && t->t_dflg & F_PIPEIN) { (void)close(pipein[0]); (void)close(pipein[1]); } if ((t->t_dflg & F_PIPEOUT) == 0) { if (nosigchld) { (void)sigprocmask(SIG_SETMASK, &csigset, NULL); nosigchld = 0; } if ((t->t_dflg & F_AMPERSAND) == 0) pwait(); } break; } doio(t, pipein, pipeout); if (t->t_dflg & F_PIPEOUT) { (void)close(pipeout[0]); (void)close(pipeout[1]); } /* * Perform a builtin function. If we are not forked, arrange for * possible stopping */ if (bifunc) { func(t, bifunc); if (forked) exitstat(); break; } if (t->t_dtyp != NODE_PAREN) doexec(NULL, t); /* * For () commands must put new 0,1,2 in FSH* and recurse */ (void) ioctl(OLDSTD = dcopy(0, FOLDSTD), FIOCLEX, NULL); (void) ioctl(SHOUT = dcopy(1, FSHOUT), FIOCLEX, NULL); (void) ioctl(SHERR = dcopy(2, FSHERR), FIOCLEX, NULL); (void) close(SHIN); SHIN = -1; didfds = 0; wanttty = -1; t->t_dspr->t_dflg |= t->t_dflg & F_NOINTERRUPT; execute(t->t_dspr, wanttty, NULL, NULL); exitstat(); /* NOTREACHED */ case NODE_PIPE: t->t_dcar->t_dflg |= F_PIPEOUT | (t->t_dflg & (F_PIPEIN | F_AMPERSAND | F_STDERR | F_NOINTERRUPT)); execute(t->t_dcar, wanttty, pipein, pv); t->t_dcdr->t_dflg |= F_PIPEIN | (t->t_dflg & (F_PIPEOUT | F_AMPERSAND | F_NOFORK | F_NOINTERRUPT)); if (wanttty > 0) wanttty = 0; /* got tty already */ execute(t->t_dcdr, wanttty, pv, pipeout); break; case NODE_LIST: if (t->t_dcar) { t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; execute(t->t_dcar, wanttty, NULL, NULL); /* * In strange case of A&B make a new job after A */ if (t->t_dcar->t_dflg & F_AMPERSAND && t->t_dcdr && (t->t_dcdr->t_dflg & F_AMPERSAND) == 0) pendjob(); } if (t->t_dcdr) { t->t_dcdr->t_dflg |= t->t_dflg & (F_NOFORK | F_NOINTERRUPT); execute(t->t_dcdr, wanttty, NULL, NULL); } break; case NODE_OR: case NODE_AND: if (t->t_dcar) { t->t_dcar->t_dflg |= t->t_dflg & F_NOINTERRUPT; execute(t->t_dcar, wanttty, NULL, NULL); if ((getn(value(STRstatus)) == 0) != (t->t_dtyp == NODE_AND)) return; } if (t->t_dcdr) { t->t_dcdr->t_dflg |= t->t_dflg & (F_NOFORK | F_NOINTERRUPT); execute(t->t_dcdr, wanttty, NULL, NULL); } break; } /* * Fall through for all breaks from switch * * If there will be no more executions of this command, flush all file * descriptors. Places that turn on the F_REPEAT bit are responsible for * doing donefds after the last re-execution */ if (didfds && !(t->t_dflg & F_REPEAT)) donefds(); }
/* * Form a shell temporary file (in unit 0) from the words * of the shell input up to a line the same as "term". * Unit 0 should have been closed before this call. */ void heredoc(tchar *term) { int c; tchar *Dv[2]; tchar obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ]; int ocnt, lcnt, mcnt; tchar *lbp, *obp, *mbp; tchar **vp; bool quoted; tchar shtemp[] = {'/', 't', 'm', 'p', '/', 's', 'h', 'X', 'X', 'X', 'X', 'X', 'X', 0}; int fd1; #ifdef TRACE tprintf("TRACE- heredoc()\n"); #endif if ((fd1 = mkstemp_(shtemp)) < 0) Perror(shtemp); (void) unlink_(shtemp); /* 0 0 inode! */ unsetfd(fd1); Dv[0] = term; Dv[1] = NOSTR; gflag = 0; trim(Dv); rscan(Dv, Dtestq); quoted = gflag; ocnt = BUFSIZ; obp = obuf; for (;;) { /* * Read up a line */ lbp = lbuf; lcnt = BUFSIZ - 4; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c < 0) { setname(term); bferr("<< terminator not found"); } if (c == '\n') break; if (c &= TRIM) { *lbp++ = c; if (--lcnt < 0) { setname(S_LESLES /* "<<" */); error("Line overflow"); } } } *lbp = 0; /* * Compare to terminator -- before expansion */ if (eq(lbuf, term)) { (void) write_(0, obuf, BUFSIZ - ocnt); (void) lseek(0, (off_t)0, 0); return; } /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { *lbp++ = '\n'; *lbp = 0; for (lbp = lbuf; c = *lbp++; ) { *obp++ = c; if (--ocnt == 0) { (void) write_(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } continue; } /* * Term wasn't quoted so variable and then command * expand the input line */ Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4; for (;;) { c = DgetC(DODOL); if (c == DEOF) break; if ((c &= TRIM) == 0) continue; /* \ quotes \ $ ` here */ if (c == '\\') { c = DgetC(0); /* if (!any(c, "$\\`")) */ if ((c != '$') && (c != '\\') && (c != '`')) unDgetC(c | QUOTE), c = '\\'; else c |= QUOTE; } *mbp++ = c; if (--mcnt == 0) { setname(S_LESLES /* "<<" */); bferr("Line overflow"); } } *mbp++ = 0; /* * If any ` in line do command substitution */ mbp = mbuf; if (any('`', mbp)) { /* * 1 arg to dobackp causes substitution to be literal. * Words are broken only at newlines so that all blanks * and tabs are preserved. Blank lines (null words) * are not discarded. */ vp = dobackp(mbuf, 1); } else /* Setup trivial vector similar to return of dobackp */ Dv[0] = mbp, Dv[1] = NOSTR, vp = Dv; /* * Resurrect the words from the command substitution * each separated by a newline. Note that the last * newline of a command substitution will have been * discarded, but we put a newline after the last word * because this represents the newline after the last * input line! */ for (; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; if (--ocnt == 0) { (void) write_(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } *obp++ = '\n'; if (--ocnt == 0) { (void) write_(0, obuf, BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } if (pargv) blkfree(pargv), pargv = 0; } }
void dostart(Char ** vc, struct command *c) { char *cmdstr,*cmdend,*ptr; char argv0[256];/*FIXBUF*/ DWORD cmdsize; char *currdir=NULL; char *savepath; char **v = NULL; STARTUPINFO si; PROCESS_INFORMATION pi; DWORD dwCreationFlags=CREATE_NEW_CONSOLE; DWORD k,cmdlen,j,jj,ret; UNREFERENCED_PARAMETER(c); vc++; cmdsize = 512; cmdstr = heap_alloc(cmdsize); cmdend = cmdstr; cmdlen = 0; memset(&si,0,sizeof(si)); si.cb = sizeof(si); vc = glob_all_or_error(vc); v = short2blk(vc); if(v == NULL) { stderror(ERR_NOMEM); return; } blkfree(vc); for (k = 0; v[k] != NULL ; k++){ if ( v[k][0] == '-' ) { /* various options */ if( (v[k][1] == 'T') || (v[k][1] == 't')) si.lpTitle =&( v[k][2]); else if ( (v[k][1] == 'D') || (v[k][1] == 'd')) currdir =&( v[k][2]); else if (!_stricmp(&v[k][1],"MIN") ) si.wShowWindow = SW_SHOWMINIMIZED; else if (!_stricmp(&v[k][1],"MAX") ) si.wShowWindow = SW_SHOWMAXIMIZED; else if (!_stricmp(&v[k][1],"SEPARATE") ) dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; else if (!_stricmp(&v[k][1],"SHARED") ) dwCreationFlags |= CREATE_SHARED_WOW_VDM; else if (!_stricmp(&v[k][1],"LOW") ) dwCreationFlags |= IDLE_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"NORMAL") ) dwCreationFlags |= NORMAL_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"HIGH") ) dwCreationFlags |= HIGH_PRIORITY_CLASS; else if (!_stricmp(&v[k][1],"REALTIME") ) dwCreationFlags |= REALTIME_PRIORITY_CLASS; else{ blkfree((Char **)v); stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ } } else{ // non-option arg break; } } /* * Stop the insanity of requiring start "tcsh -l" * Option processing now stops at first non-option arg * -amol 5/30/96 */ for (jj=k;v[jj] != NULL; jj++) { j=(lstrlen(v[jj]) + 2); if (j + cmdlen > cmdsize) { ptr = cmdstr; cmdstr = heap_realloc(cmdstr, max(cmdsize << 1, j+cmdlen) ); if(!cmdstr) { heap_free(ptr); stderror(ERR_NOMEM,"start");/*FIXRESET*/ } cmdend = cmdstr + (cmdend - ptr); cmdsize <<= 1; } ptr = v[jj]; while (*ptr) { *cmdend++ = *ptr++; cmdlen++; } *cmdend++ = ' '; cmdlen++; } if (jj == k) { blkfree((Char **)v); stderror(ERR_SYSTEM,start_usage,"See CMD.EXE for more info");/*FIXRESET*/ return; } *cmdend = 0; StringCbCopy(argv0,sizeof(argv0),v[k]); /* * strictly speaking, it should do no harm to set the path * back to '\'-delimited even in the parent, but in the * interest of consistency, we save the old value and restore it * later */ savepath = fix_path_for_child(); if (! CreateProcess(NULL, cmdstr, NULL, NULL, FALSE, dwCreationFlags, NULL, currdir, &si, &pi) ) { restore_path(savepath); ret = GetLastError(); if (ret == ERROR_BAD_EXE_FORMAT || ret == ERROR_ACCESS_DENIED || (ret == ERROR_FILE_NOT_FOUND && (is_url(v[k]) || is_directory(v[k])) ) ) { char erbuf[MAX_PATH]; errno = ENOEXEC; try_shell_ex(&v[k],0,FALSE); heap_free(cmdstr); /* free !! */ if (errno) { strerror_s(erbuf,sizeof(erbuf),errno); stderror(ERR_ARCH,argv0,erbuf);/*FIXRESET*/ } } else if (ret == ERROR_INVALID_PARAMETER) { errno = ENAMETOOLONG; heap_free(cmdstr); /* free !! */ stderror(ERR_TOOLARGE,argv0);/*FIXRESET*/ } else { errno = ENOENT; if ( ( (v[k][0] == '\\') ||(v[k][0] == '/') ) && ( (v[k][1] == '\\') ||(v[k][1] == '/') ) && (!v[k+1]) ) try_shell_ex(&v[k],0,FALSE); heap_free(cmdstr); /* free !! */ if (errno) { stderror(ERR_NOTFOUND,argv0);/*FIXRESET*/ } } } else { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); heap_free(cmdstr); restore_path(savepath); } blkfree((Char **)v); return; }
The default action is to shutdown without a reboot.\n\"now\" must be \ specified to actually shutdown or reboot\n"}; void doshutdown(Char **vc, struct command *c) { unsigned int flags = 0; unsigned char reboot,shutdown,logoff,shutdown_ok; char **v; char *ptr; char errbuf[128]; int k; HANDLE hToken; TOKEN_PRIVILEGES tp,tpPrevious; LUID luid; DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); if (gdwPlatform != VER_PLATFORM_WIN32_NT) { stderror(ERR_SYSTEM,"shutdown","Sorry,not supported on win95"); } shutdown_ok = reboot = shutdown = logoff = 0; gflag = 0; tglob(vc); if (gflag) { vc = globall(vc); if (vc == 0) stderror(ERR_NAME | ERR_NOMATCH); } else vc = gargv = saveblk(vc); trim(vc); v = short2blk(vc); for (k = 0; v[k] != NULL ; k++){ if ( v[k][0] == '-' ) { ptr = v[k]; ptr++; while( ptr && *ptr) { if (*ptr == 'f') flags |= EWX_FORCE; if (*ptr == 'r') reboot =1; else if (*ptr == 'l') logoff =1; else { blkfree((Char **)v); stderror(ERR_SYSTEM,"Usage",shutdown_usage); } ptr++; } } else if (!lstrcmpi(v[k],"now")) { shutdown_ok = 1; } } if (k == 0) { blkfree((Char**)v); stderror(ERR_SYSTEM,"Usage",shutdown_usage); } if (!reboot && !logoff){ flags |= EWX_SHUTDOWN; shutdown = 1; } if (reboot && logoff ) { blkfree((Char **)v); stderror(ERR_SYSTEM,"Usage",shutdown_usage); } if (reboot) flags |= EWX_REBOOT; if (logoff) flags |= EWX_LOGOFF; if ((reboot || shutdown) && (!shutdown_ok) ) { blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown","Specify \"now\" to really shutdown"); } if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES| TOKEN_QUERY, &hToken) ){ make_err_str(GetLastError(),errbuf,128); blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown failed",errbuf); } if (!LookupPrivilegeValue(NULL,SE_SHUTDOWN_NAME,&luid)) { make_err_str(GetLastError(),errbuf,128); blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown failed",errbuf); } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; tp.Privileges[0].Attributes = 0; if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),&tpPrevious, &cbPrevious)){ make_err_str(GetLastError(),errbuf,128); blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown failed",errbuf); } tpPrevious.PrivilegeCount = 1; tpPrevious.Privileges[0].Luid = luid; tpPrevious.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken,FALSE,&tpPrevious,cbPrevious,NULL, NULL)){ make_err_str(GetLastError(),errbuf,128); blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown failed",errbuf); } if ( !ExitWindowsEx(flags,0) ) { make_err_str(GetLastError(),errbuf,128); blkfree((Char **)v); stderror(ERR_SYSTEM,"shutdown failed",errbuf); } }
/* * Form a shell temporary file (in unit 0) from the words * of the shell input up to EOF or a line the same as "term". * Unit 0 should have been closed before this call. */ void heredoc(Char *term) { eChar c; Char *Dv[2]; struct Strbuf lbuf = Strbuf_INIT, mbuf = Strbuf_INIT; Char obuf[BUFSIZE + 1]; #define OBUF_END (obuf + sizeof(obuf) / sizeof (*obuf) - 1) Char *lbp, *obp, *mbp; Char **vp; int quoted; #ifdef HAVE_MKSTEMP char *tmp = short2str(shtemp); char *dot = strrchr(tmp, '.'); if (!dot) stderror(ERR_NAME | ERR_NOMATCH); strcpy(dot, TMP_TEMPLATE); xclose(0); if (mkstemp(tmp) == -1) stderror(ERR_SYSTEM, tmp, strerror(errno)); #else /* !HAVE_MKSTEMP */ char *tmp; # ifndef WINNT_NATIVE again: # endif /* WINNT_NATIVE */ tmp = short2str(shtemp); # if O_CREAT == 0 if (xcreat(tmp, 0600) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); # endif xclose(0); if (xopen(tmp, O_RDWR|O_CREAT|O_EXCL|O_TEMPORARY|O_LARGEFILE, 0600) == -1) { int oerrno = errno; # ifndef WINNT_NATIVE if (errno == EEXIST) { if (unlink(tmp) == -1) { xfree(shtemp); mbp = randsuf(); shtemp = Strspl(STRtmpsh, mbp); xfree(mbp); } goto again; } # endif /* WINNT_NATIVE */ (void) unlink(tmp); errno = oerrno; stderror(ERR_SYSTEM, tmp, strerror(errno)); } #endif /* HAVE_MKSTEMP */ (void) unlink(tmp); /* 0 0 inode! */ Dv[0] = term; Dv[1] = NULL; gflag = 0; trim(Dv); rscan(Dv, Dtestq); quoted = gflag; obp = obuf; obuf[BUFSIZE] = 0; inheredoc = 1; cleanup_push(&inheredoc, inheredoc_cleanup); #ifdef WINNT_NATIVE __dup_stdin = 1; #endif /* WINNT_NATIVE */ cleanup_push(&lbuf, Strbuf_cleanup); cleanup_push(&mbuf, Strbuf_cleanup); for (;;) { Char **words; /* * Read up a line */ lbuf.len = 0; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c == CHAR_ERR || c == '\n') break; if ((c &= TRIM) != 0) Strbuf_append1(&lbuf, (Char) c); } Strbuf_terminate(&lbuf); /* Catch EOF in the middle of a line. */ if (c == CHAR_ERR && lbuf.len != 0) c = '\n'; /* * Check for EOF or compare to terminator -- before expansion */ if (c == CHAR_ERR || eq(lbuf.s, term)) break; /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { Strbuf_append1(&lbuf, '\n'); Strbuf_terminate(&lbuf); for (lbp = lbuf.s; (c = *lbp++) != 0;) { *obp++ = (Char) c; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } continue; } /* * Term wasn't quoted so variable and then command expand the input * line */ Dcp = lbuf.s; Dvp = Dv + 1; mbuf.len = 0; for (;;) { c = DgetC(DODOL); if (c == DEOF) break; if ((c &= TRIM) == 0) continue; /* \ quotes \ $ ` here */ if (c == '\\') { c = DgetC(0); if (!any("$\\`", c)) unDgetC(c | QUOTE), c = '\\'; else c |= QUOTE; } Strbuf_append1(&mbuf, (Char) c); } Strbuf_terminate(&mbuf); /* * If any ` in line do command substitution */ mbp = mbuf.s; if (Strchr(mbp, '`') != NULL) { /* * 1 arg to dobackp causes substitution to be literal. Words are * broken only at newlines so that all blanks and tabs are * preserved. Blank lines (null words) are not discarded. */ words = dobackp(mbp, 1); } else /* Setup trivial vector similar to return of dobackp */ Dv[0] = mbp, Dv[1] = NULL, words = Dv; /* * Resurrect the words from the command substitution each separated by * a newline. Note that the last newline of a command substitution * will have been discarded, but we put a newline after the last word * because this represents the newline after the last input line! */ for (vp= words; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } *obp++ = '\n'; if (obp == OBUF_END) { tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); obp = obuf; } } if (words != Dv) blkfree(words); } *obp = 0; tmp = short2str(obuf); (void) xwrite(0, tmp, strlen (tmp)); (void) lseek(0, (off_t) 0, L_SET); cleanup_until(&inheredoc); }
/* * Form a shell temporary file (in unit 0) from the words * of the shell input up to EOF or a line the same as "term". * Unit 0 should have been closed before this call. */ void /*ARGSUSED*/ heredoc(Char *term) { int c; Char *Dv[2]; Char obuf[BUFSIZ], lbuf[BUFSIZ], mbuf[BUFSIZ]; int ocnt, lcnt, mcnt; Char *lbp, *obp, *mbp; Char **vp; bool quoted; char tmp[] = "/tmp/sh.XXXXXXXX"; if (mkstemp(tmp) < 0) stderror(ERR_SYSTEM, tmp, strerror(errno)); (void) unlink(tmp); /* 0 0 inode! */ Dv[0] = term; Dv[1] = NULL; gflag = 0; trim(Dv); rscan(Dv, Dtestq); quoted = gflag; ocnt = BUFSIZ; obp = obuf; for (;;) { /* * Read up a line */ lbp = lbuf; lcnt = BUFSIZ - 4; for (;;) { c = readc(1); /* 1 -> Want EOF returns */ if (c < 0 || c == '\n') break; if ((c &= TRIM) != '\0') { *lbp++ = c; if (--lcnt < 0) { setname("<<"); stderror(ERR_NAME | ERR_OVERFLOW); } } } *lbp = 0; /* * Check for EOF or compare to terminator -- before expansion */ if (c < 0 || eq(lbuf, term)) { (void) write(STDIN_FILENO, short2str(obuf), (size_t) (BUFSIZ - ocnt)); (void) lseek(STDIN_FILENO, (off_t) 0, SEEK_SET); return; } /* * If term was quoted or -n just pass it on */ if (quoted || noexec) { *lbp++ = '\n'; *lbp = 0; for (lbp = lbuf; (c = *lbp++) != '\0';) { *obp++ = c; if (--ocnt == 0) { (void) write(STDIN_FILENO, short2str(obuf), BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } continue; } /* * Term wasn't quoted so variable and then command expand the input * line */ Dcp = lbuf; Dvp = Dv + 1; mbp = mbuf; mcnt = BUFSIZ - 4; for (;;) { c = DgetC(DODOL); if (c == DEOF) break; if ((c &= TRIM) == 0) continue; /* \ quotes \ $ ` here */ if (c == '\\') { c = DgetC(0); if (!any("$\\`", c)) unDgetC(c | QUOTE), c = '\\'; else c |= QUOTE; } *mbp++ = c; if (--mcnt == 0) { setname("<<"); stderror(ERR_NAME | ERR_OVERFLOW); } } *mbp++ = 0; /* * If any ` in line do command substitution */ mbp = mbuf; if (any(short2str(mbp), '`')) { /* * 1 arg to dobackp causes substitution to be literal. Words are * broken only at newlines so that all blanks and tabs are * preserved. Blank lines (null words) are not discarded. */ vp = dobackp(mbuf, 1); } else /* Setup trivial vector similar to return of dobackp */ Dv[0] = mbp, Dv[1] = NULL, vp = Dv; /* * Resurrect the words from the command substitution each separated by * a newline. Note that the last newline of a command substitution * will have been discarded, but we put a newline after the last word * because this represents the newline after the last input line! */ for (; *vp; vp++) { for (mbp = *vp; *mbp; mbp++) { *obp++ = *mbp & TRIM; if (--ocnt == 0) { (void) write(STDIN_FILENO, short2str(obuf), BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } *obp++ = '\n'; if (--ocnt == 0) { (void) write(STDIN_FILENO, short2str(obuf), BUFSIZ); obp = obuf; ocnt = BUFSIZ; } } if (pargv) blkfree(pargv), pargv = 0; } }
/*ARGSUSED*/ void dosched(Char **v, struct command *c) { struct sched_event *tp, **pp; time_t cur_time; int count, hours, minutes, dif_hour, dif_min; Char *cp; int relative; /* time specified as +hh:mm */ struct tm *ltp; USE(c); /* This is a major kludge because of a gcc linker */ /* Problem. It may or may not be needed for you */ #if defined(_MINIX) && !defined(_MINIX_VMD) char kludge[10]; extern char *sprintf(); sprintf(kludge, CGETS(24, 1, "kludge")); #endif /* _MINIX && !_MINIX_VMD */ v++; cp = *v++; if (cp == NULL) { const Char *fmt; if ((fmt = varval(STRsched)) == STRNULL) fmt = str2short("%h\t%T\t%R\n"); /* print list of scheduled events */ for (count = 1, tp = sched_ptr; tp; count++, tp = tp->t_next) { Char *buf, *str; buf = blkexpand(tp->t_lex); cleanup_push(buf, xfree); str = tprintf(FMT_SCHED, fmt, short2str(buf), tp->t_when, &count); cleanup_until(buf); cleanup_push(str, xfree); for (cp = str; *cp;) xputwchar(*cp++); cleanup_until(str); } return; } if (*cp == '-') { /* remove item from list */ if (!sched_ptr) stderror(ERR_NOSCHED); if (*v) stderror(ERR_SCHEDUSAGE); count = atoi(short2str(++cp)); if (count <= 0) stderror(ERR_SCHEDUSAGE); pp = &sched_ptr; tp = sched_ptr; while (--count) { if (tp->t_next == 0) break; else { pp = &tp->t_next; tp = tp->t_next; } } if (count) stderror(ERR_SCHEDEV); *pp = tp->t_next; blkfree(tp->t_lex); xfree(tp); return; } /* else, add an item to the list */ if (!*v) stderror(ERR_SCHEDCOM); relative = 0; if (!Isdigit(*cp)) { /* not abs. time */ if (*cp != '+') stderror(ERR_SCHEDUSAGE); cp++, relative++; } minutes = 0; hours = atoi(short2str(cp)); while (*cp && *cp != ':' && *cp != 'a' && *cp != 'p') cp++; if (*cp && *cp == ':') minutes = atoi(short2str(++cp)); if ((hours < 0) || (minutes < 0) || (hours > 23) || (minutes > 59)) stderror(ERR_SCHEDTIME); while (*cp && *cp != 'p' && *cp != 'a') cp++; if (*cp && relative) stderror(ERR_SCHEDREL); if (*cp == 'p') hours += 12; (void) time(&cur_time); ltp = localtime(&cur_time); if (relative) { dif_hour = hours; dif_min = minutes; } else { if ((dif_hour = hours - ltp->tm_hour) < 0) dif_hour += 24; if ((dif_min = minutes - ltp->tm_min) < 0) { dif_min += 60; if ((--dif_hour) < 0) dif_hour = 23; } } tp = xcalloc(1, sizeof *tp); #ifdef _SX tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600 + dif_min * 60; #else /* _SX */ tp->t_when = cur_time - ltp->tm_sec + dif_hour * 3600L + dif_min * 60L; #endif /* _SX */ /* use of tm_sec: get to beginning of minute. */ for (pp = &sched_ptr; *pp != NULL && tp->t_when >= (*pp)->t_when; pp = &(*pp)->t_next) ; tp->t_next = *pp; *pp = tp; tp->t_lex = saveblk(v); }
void /*ARGSUSED*/ doexec(Char **v, struct command *t) { struct varent *pathv; Char *blk[2], **av, *dp, **pv, *sav; int i, hashval, hashval1; sigset_t nsigset; int slash; hashval = 0; /* * Glob the command name. We will search $path even if this does something, * as in sh but not in csh. One special case: if there is no PATH, then we * execute only commands which start with '/'. */ blk[0] = t->t_dcom[0]; blk[1] = 0; gflag = 0, tglob(blk); if (gflag) { pv = globall(blk); if (pv == 0) { setname(vis_str(blk[0])); stderror(ERR_NAME | ERR_NOMATCH); } gargv = 0; } else pv = saveblk(blk); trim(pv); exerr = 0; expath = Strsave(pv[0]); Vexpath = expath; pathv = adrof(STRpath); if (pathv == 0 && expath[0] != '/') { blkfree(pv); pexerr(); } slash = any(short2str(expath), '/'); /* * Glob the argument list, if necessary. Otherwise trim off the quote bits. */ gflag = 0; av = &t->t_dcom[1]; tglob(av); if (gflag) { av = globall(av); if (av == 0) { blkfree(pv); setname(vis_str(expath)); stderror(ERR_NAME | ERR_NOMATCH); } gargv = 0; } else av = saveblk(av); blkfree(t->t_dcom); t->t_dcom = blkspl(pv, av); free(pv); free(av); av = t->t_dcom; trim(av); if (*av == NULL || **av == '\0') pexerr(); xechoit(av); /* Echo command if -x */ /* * Since all internal file descriptors are set to close on exec, we don't * need to close them explicitly here. Just reorient ourselves for error * messages. */ SHIN = 0; SHOUT = 1; SHERR = 2; OLDSTD = 0; /* * We must do this AFTER any possible forking (like `foo` in glob) so that * this shell can still do subprocesses. */ sigemptyset(&nsigset); (void)sigprocmask(SIG_SETMASK, &nsigset, NULL); /* * If no path, no words in path, or a / in the filename then restrict the * command search. */ if (pathv == 0 || pathv->vec[0] == 0 || slash) pv = justabs; else pv = pathv->vec; sav = Strspl(STRslash, *av); /* / command name for postpending */ Vsav = sav; if (havhash) hashval = hashname(*av); i = 0; hits++; do { /* * Try to save time by looking at the hash table for where this command * could be. If we are doing delayed hashing, then we put the names in * one at a time, as the user enters them. This is kinda like Korn * Shell's "tracked aliases". */ if (!slash && pv[0][0] == '/' && havhash) { hashval1 = hash(hashval, i); if (!bit(xhash, hashval1)) goto cont; } if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */ texec(*av, av); else { dp = Strspl(*pv, sav); Vdp = dp; texec(dp, av); Vdp = 0; free(dp); } misses++; cont: pv++; i++; } while (*pv); hits--; Vsav = 0; free(sav); pexerr(); /* NOTREACHED */ }
int nt_try_fast_exec(struct command *t) { register Char **pv, **av; register Char *dp,*sav; register char **tt; register char *f; register struct varent *v; register int hashval,i; register int slash; int rc = 0, gflag; Char *vp; Char *blk[2]; vp = varval(STRNTslowexec); if (vp != STRNULL) return 1; blk[0] = t->t_dcom[0]; blk[1] = 0; // don't do backtick if(Strchr(t->t_dcom[0],'`') ) return 1; gflag = tglob(blk); if (gflag) { pv = globall(blk, gflag); if (pv == 0) { return 1; } } else pv = saveblk(blk); trim(pv); epath = Strsave(pv[0]); v = adrof(STRpath); if (v == 0 && epath[0] != '/' && epath[0] != '.') { blkfree(pv); return 1; } slash = any(short2str(epath),'/'); /* * Glob the argument list, if necessary. Otherwise trim off the quote bits. */ av = &t->t_dcom[1]; gflag = tglob(av); if (gflag) { av = globall(av, gflag);/*FIXRESET*/ if (av == 0) { blkfree(pv); return 1; } } else av = saveblk(av); blkfree(t->t_dcom); t->t_dcom = blkspl(pv, av); xfree((ptr_t) pv); xfree((ptr_t) av); av = t->t_dcom; //trim(av); if (*av == NULL || **av == '\0') return 1; xechoit(av);/*FIXRESET*/ /* Echo command if -x */ if (v == 0 || v->vec[0] == 0 || slash) pv = abspath; else pv = v->vec; sav = Strspl(STRslash,*av); hashval = hashval_extern(*av); i = 0; do { #pragma warning(disable:4310) if (!slash && ABSOLUTEP(pv[0]) && havhash) { #pragma warning(default:4310) if (!bit_extern(hashval,i)){ pv++;i++; continue; } } if (pv[0][0] == 0 || eq(pv[0],STRdot)) { tt = short2blk(av); f = short2str(*av); rc = nt_texec(f, tt); blkfree((Char**)tt); if (!rc) break; } else { dp = Strspl(*pv,sav); tt = short2blk(av); f = short2str(dp); rc = nt_texec(f, tt); blkfree((Char**)tt); xfree((ptr_t)dp); if (!rc) break; } pv++; i++; }while(*pv); return rc; }
FILE * ftpd_popen(char *program, char *type, int closestderr) { register char *cp; FILE *iop; int argc, gargc, pdes[2], pid; char **pop, *argv[100], *gargv[1000], *vv[2]; extern char **ftpglob(register char *v), **copyblk(register char **v), *strspl(register char *cp, register char *dp); if (*type != 'r' && *type != 'w' || type[1]) return (NULL); if (!pids) { #ifndef HAVE_GETDTABLESIZE struct rlimit rlp; rlp.rlim_cur = rlp.rlim_max = RLIM_INFINITY; if (getrlimit( RLIMIT_NOFILE, &rlp ) ) return(NULL); fds = rlp.rlim_cur; #else if ((fds = getdtablesize()) <= 0) return (NULL); #endif if ((pids = (int *) malloc((u_int) (fds * sizeof(int)))) == NULL) return (NULL); #ifdef USG (void) memset((char *)pids, fds * sizeof(int), 0); #else bzero((char *) pids, fds * sizeof(int)); #endif } if (pipe(pdes) < 0) return (NULL); /* break up string into pieces */ for (argc = 0, cp = program;; cp = NULL) if (!(argv[argc++] = strtok(cp, " \t\n"))) break; /* glob each piece */ gargv[0] = argv[0]; for (gargc = argc = 1; argv[argc]; argc++) { if (!(pop = ftpglob(argv[argc]))) { /* globbing failed */ vv[0] = strspl(argv[argc], ""); vv[1] = NULL; pop = copyblk(vv); } argv[argc] = (char *) pop; /* save to free later */ while (*pop && gargc < 1000) gargv[gargc++] = *pop++; } gargv[gargc] = NULL; iop = NULL; switch (pid = vfork()) { case -1: /* error */ (void) close(pdes[0]); (void) close(pdes[1]); goto pfree; /* NOTREACHED */ case 0: /* child */ if (*type == 'r') { if (pdes[1] != 1) { dup2(pdes[1], 1); if (closestderr) (void) close(2); else dup2(pdes[1], 2); /* stderr, too! */ (void) close(pdes[1]); } (void) close(pdes[0]); } else { if (pdes[0] != 0) { dup2(pdes[0], 0); (void) close(pdes[0]); } (void) close(pdes[1]); } execv(gargv[0], gargv); _exit(1); } /* parent; assume fdopen can't fail... */ if (*type == 'r') { iop = fdopen(pdes[0], type); (void) close(pdes[1]); } else { iop = fdopen(pdes[1], type); (void) close(pdes[0]); } pids[fileno(iop)] = pid; pfree:for (argc = 1; argv[argc] != NULL; argc++) { blkfree((char **) argv[argc]); free((char *) argv[argc]); } return (iop); }
void blk_cleanup(void *ptr) { blkfree(ptr); }
int f_put (char **vec) { int append; #ifdef BRIDGE int result; char *dst; #else int sglobbed; char *bp, *dst, **gp, **src; char *freedst = NULL, buffer[BUFSIZ]; #endif append = strcmp (*vec, "append") == 0; if (*++vec == NULL) { #ifdef BRIDGE return NOTOK; #else if (getftamline ("source: ", buffer) == NOTOK || str2vec (buffer, vec) < 1) return OK; dst = NULL; #endif } else { #ifdef BRIDGE dst = *vec; #else char **ap; for (ap = vec; *ap; ap++) continue; if (--ap != vec) dst = *ap, *ap = NULL; else dst = NULL; #endif } #ifndef BRIDGE if (!(src = xglob (vec, 0))) return OK; sglobbed = xglobbed; if (dst == NULL) { if (getftamline ("destination: ", buffer) == NOTOK) { blkfree (src); return OK; } switch (str2vec (buffer, vec)) { case 0: break; case 1: dst = *vec; break; default: advise (NULLCP, "too many destinations"); goto out; } } if (dst && !(dst = freedst = xglob1val (dst, 0))) goto out; if (src[1] == NULL) { if (interrupted) goto out; if (dst == NULL) { switch (realstore) { case RFS_UNIX: if (dst = rindex (*src, '/')) dst++; if (dst == NULL || *dst == NULL) dst = *src; break; default: dst = *src; break; } dst = str2file (dst); ask_it: ; if (query) switch (ask ("%s %s %s", append ? "append" : "put", *src, dst)) { case NOTOK: goto out; case OK: default: break; case DONE: goto out; } } else switch (realstore) { case RFS_UNIX: if (isdir (dst, NULLCP, 1) == NOTOK) break; #ifdef apollo if (*dst == '/') sprintf (bp = buffer, "%s", dst); else #endif sprintf (bp = buffer, "%s/", dst); bp += strlen (bp); if (dst = rindex (*src, '/')) dst++; if (dst == NULL || *dst == NULL) dst = *src; strcpy (bp, dst); dst = buffer; goto ask_it; default: break; } dst = str2file (dst); put (*src, dst, append); goto out; } switch (realstore) { case RFS_UNKNOWN: advise (NULLCP, "%s", rs_unknown); goto out; case RFS_UNIX: if (dst) #ifdef apollo if (*(bp = str2file (dst)) == '/') { strcpy (buffer, bp); bp = buffer; } else #endif sprintf (bp = buffer, "%s/", str2file (dst)); else if (rcwd) sprintf (bp = buffer, "%s", str2file ("")); else strcpy (bp = buffer, "./"); bp += strlen (bp); break; default: advise (NULLCP, "%s", rs_support); goto out; } if (isdir (str2file (buffer), NULLCP, 0) == NOTOK) goto out; for (gp = src; *gp && !interrupted; gp++) { switch (realstore) { case RFS_UNIX: if (dst = rindex (*gp, '/')) dst++; if (dst == NULL || *dst == NULL) dst = *gp; break; default: dst = *gp; break; } strcpy (bp, dst); dst = str2file (buffer); if (sglobbed) { if (query) switch (ask ("%s %s %s", append ? "append" : "put", *gp, dst)) { case NOTOK: continue; case OK: default: break; case DONE: goto out; } else advise (NULLCP, "%s %s %s", append ? "append" : "put", *gp, dst); } put (*gp, dst, append); if (ftamfd == NOTOK) break; } out: ; blkfree (src); if (freedst) free (freedst); return OK; #else result = put (dst, append); return result; #endif }
/* * Execute command f, arg list t. * Record error message if not found. * Also do shell scripts here. */ static void texec(Char *sf, Char **st) { struct varent *v; Char *lastsh[2], **vp, *st0, **ost; char *f, **t; int fd; unsigned char c = '\0'; /* The order for the conversions is significant */ t = short2blk(st); f = short2str(sf); Vt = t; errno = 0; /* don't use a previous error */ (void)execve(f, t, environ); Vt = 0; blkfree((Char **)t); switch (errno) { case ENOEXEC: /* * From: [email protected] (Casper H.S. Dik) If we could not execute * it, don't feed it to the shell if it looks like a binary! */ if ((fd = open(f, O_RDONLY)) != -1) { if (read(fd, (char *)&c, 1) == 1) { if (!Isprint(c) && (c != '\n' && c != '\t')) { (void)close(fd); /* * We *know* what ENOEXEC means. */ stderror(ERR_ARCH, f, strerror(errno)); } } #ifdef _PATH_BSHELL else c = '#'; #endif (void)close(fd); } /* * If there is an alias for shell, then put the words of the alias in * front of the argument list replacing the command name. Note no * interpretation of the words at this point. */ v = adrof1(STRshell, &aliases); if (v == 0) { vp = lastsh; vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH; vp[1] = NULL; #ifdef _PATH_BSHELL if (fd != -1 && c != '#') vp[0] = STR_BSHELL; #endif } else vp = v->vec; st0 = st[0]; st[0] = sf; ost = st; st = blkspl(vp, st); /* Splice up the new arglst */ ost[0] = st0; sf = *st; /* The order for the conversions is significant */ t = short2blk(st); f = short2str(sf); free(st); Vt = t; (void)execve(f, t, environ); Vt = 0; blkfree((Char **)t); /* FALLTHROUGH */ case ENOMEM: stderror(ERR_SYSTEM, f, strerror(errno)); /* NOTREACHED */ case ENOENT: break; default: if (exerr == 0) { exerr = strerror(errno); if (expath) free(expath); expath = Strsave(sf); Vexpath = expath; } } }
/* * Execute scheduled events */ void sched_run(void) { time_t cur_time; struct sched_event *tp; struct wordent cmd, *nextword, *lastword; struct command *t; Char **v, *cp; pintr_disabled++; cleanup_push(&pintr_disabled, disabled_cleanup); (void) time(&cur_time); /* bugfix by: Justin Bur at Universite de Montreal */ /* * this test wouldn't be necessary if this routine were not called before * each prompt (in sh.c). But it is, to catch missed alarms. Someone * ought to fix it all up. -jbb */ if (!(sched_ptr && sched_ptr->t_when < cur_time)) { cleanup_until(&pintr_disabled); return; } if (GettingInput) (void) Cookedmode(); while ((tp = sched_ptr) != NULL && tp->t_when < cur_time) { if (seterr) { xfree(seterr); seterr = NULL; } cmd.word = STRNULL; lastword = &cmd; v = tp->t_lex; for (cp = *v; cp; cp = *++v) { nextword = xcalloc(1, sizeof cmd); nextword->word = Strsave(cp); lastword->next = nextword; nextword->prev = lastword; lastword = nextword; } lastword->next = &cmd; cmd.prev = lastword; sched_ptr = tp->t_next; /* looping termination cond: */ blkfree(tp->t_lex); /* straighten out in case of */ xfree(tp); /* command blow-up. */ cleanup_push(&cmd, lex_cleanup); /* expand aliases like process() does. */ alias(&cmd); /* build a syntax tree for the command. */ t = syntax(cmd.next, &cmd, 0); cleanup_push(t, syntax_cleanup); if (seterr) stderror(ERR_OLD); /* execute the parse tree. */ execute(t, -1, NULL, NULL, TRUE); /* done. free the lex list and parse tree. */ cleanup_until(&cmd); } if (GettingInput && !just_signaled) { /* PWP */ (void) Rawmode(); ClearLines(); /* do a real refresh since something may */ ClearDisp(); /* have printed to the screen */ Refresh(); } just_signaled = 0; cleanup_until(&pintr_disabled); }