/* * dnewcwd - make a new directory in the loop the current one */ static void dnewcwd(struct directory *dp, int dflag) { int print; if (adrof(STRdunique)) { struct directory *dn; for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev) if (dn != dp && Strcmp(dn->di_name, dp->di_name) == 0) { dn->di_next->di_prev = dn->di_prev; dn->di_prev->di_next = dn->di_next; dfree(dn); break; } } dcwd = dp; dset(dcwd->di_name); dgetstack(); print = printd; /* if printd is set, print dirstack... */ if (adrof(STRpushdsilent)) /* but pushdsilent overrides printd... */ print = 0; if (dflag & DIR_PRINT) /* but DIR_PRINT overrides pushdsilent... */ print = 1; if (bequiet) /* and bequiet overrides everything */ print = 0; if (print) printdirs(dflag); cwd_cmd(); /* PWP: run the defined cwd command */ }
/* * Fill up caching arrays for path and cdpath */ void dohash(char cachearray[]) { struct stat stb; DIR *dirp; struct dirent *dp; int cnt; int i = 0; struct varent *v; tchar **pv; int hashval; tchar curdir_[MAXNAMLEN+1]; #ifdef TRACE tprintf("TRACE- dohash()\n"); #endif /* Caching $path */ if (cachearray == xhash) { havhash = 1; v = adrof(S_path /* "path" */); } else { /* Caching $cdpath */ havhash2 = 1; v = adrof(S_cdpath /* "cdpath" */); } for (cnt = 0; cnt < (HSHSIZ / 8); cnt++) cachearray[cnt] = 0; if (v == 0) { return; } for (pv = v->vec; *pv; pv++, i++) { if (pv[0][0] != '/') continue; dirp = opendir_(*pv); if (dirp == NULL) continue; if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) { unsetfd(dirp->dd_fd); closedir_(dirp); continue; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || dp->d_name[1] == '.' && dp->d_name[2] == '\0')) continue; hashval = hash(hashname(strtots(curdir_, dp->d_name)), i); bis(cachearray, hashval); } unsetfd(dirp->dd_fd); closedir_(dirp); } }
void SoundBeep(void) { /* produce a sound */ beep_cmd (); if (adrof(STRnobeep)) return; if (adrof(STRvisiblebell)) NT_VisibleBell(); /* visible bell */ else MessageBeep(MB_ICONQUESTION); }
void /*ARGSUSED*/ unset(Char **v, struct command *t) { unset1(v, &shvhed); if (adrof(STRfilec) == 0) filec = 0; if (adrof(STRhistchars) == 0) { HIST = '!'; HISTSUB = '^'; } if (adrof(STRwordchars) == 0) word_chars = STR_WORD_CHARS; }
/* set_color_context(): */ void set_color_context() { struct varent *vp = adrof(STRcolor); if (!vp) { color_context_ls = FALSE; color_context_lsmF = FALSE; } else if (!vp->vec[0] || vp->vec[0][0] == '\0') { color_context_ls = TRUE; color_context_lsmF = TRUE; } else { size_t i; color_context_ls = FALSE; color_context_lsmF = FALSE; for (i = 0; vp->vec[i]; i++) if (Strcmp(vp->vec[i], STRls) == 0) color_context_ls = TRUE; else if (Strcmp(vp->vec[i], STRlsmF) == 0) color_context_lsmF = TRUE; } }
void dsetstack(void) { Char **cp; struct varent *vp; struct directory *dn, *dp; if ((vp = adrof(STRdirstack)) == NULL || vp->vec == NULL) return; /* Free the whole stack */ while ((dn = dhead.di_prev) != &dhead) { dn->di_next->di_prev = dn->di_prev; dn->di_prev->di_next = dn->di_next; if (dn != dcwd) dfree(dn); } /* thread the current working directory */ dhead.di_prev = dhead.di_next = dcwd; dcwd->di_next = dcwd->di_prev = &dhead; /* put back the stack */ for (cp = vp->vec; cp && *cp && **cp; cp++) { dp = xcalloc(sizeof(struct directory), 1); dp->di_name = Strsave(*cp); dp->di_count = 0; dp->di_prev = dcwd; dp->di_next = dcwd->di_next; dcwd->di_next = dp; dp->di_next->di_prev = dp; } dgetstack(); /* Make $dirstack reflect the current state */ }
static Char * globtilde(Char *s) { Char *name, *u, *home, *res; u = s; for (s++; *s && *s != '/' && *s != ':'; s++) continue; name = Strnsave(u + 1, s - (u + 1)); cleanup_push(name, xfree); home = gethdir(name); if (home == NULL) { if (adrof(STRnonomatch)) { cleanup_until(name); return u; } if (*name) stderror(ERR_UNKUSER, short2str(name)); else stderror(ERR_NOHOME); } cleanup_until(name); if (home[0] == '/' && home[1] == '\0' && s[0] == '/') res = Strsave(s); else res = Strspl(home, s); xfree(home); xfree(u); return res; }
/* * dnewcwd - make a new directory in the loop the current one */ static void dnewcwd(struct directory *dp) { dcwd = dp; dset(dcwd->di_name); if (printd && !(adrof(STRpushdsilent))) printdirs(); }
void goodbye(void) { rechist(); if (loginsh) { (void) signal(SIGQUIT, SIG_IGN); (void) signal(SIGINT, SIG_IGN); (void) signal(SIGTERM, SIG_IGN); setintr = 0; /* No interrupts after "logout" */ if (!(adrof(STRlogout))) set(STRlogout, STRnormal); (void) srcfile(_PATH_DOTLOGOUT, 0, 0); if (adrof(STRhome)) (void) srccat(value(STRhome), STRsldtlogout); } exitstat(); }
void xechoit(Char **t) { if (adrof(STRecho)) { (void) fflush(csherr); blkpr(csherr, t); (void) fputc('\n', csherr); } }
void rechist(void) { Char buf[BUFSIZ], hbuf[BUFSIZ], *hfile; int fd, ftmp, oldidfds; struct varent *shist; if (!fast) { /* * If $savehist is just set, we use the value of $history * else we use the value in $savehist */ if ((shist = adrof(STRsavehist)) != NULL) { if (shist->vec[0][0] != '\0') (void) Strlcpy(hbuf, shist->vec[0], sizeof hbuf/sizeof(Char)); else if ((shist = adrof(STRhistory)) && shist->vec[0][0] != '\0') (void) Strlcpy(hbuf, shist->vec[0], sizeof hbuf/sizeof(Char)); else return; } else return; if ((hfile = value(STRhistfile)) == STRNULL) { Strlcpy(buf, value(STRhome), sizeof buf/sizeof(Char)); hfile = buf; (void) Strlcat(buf, STRsldthist, sizeof buf/sizeof(Char)); } if ((fd = open(short2str(hfile), O_WRONLY | O_CREAT | O_TRUNC, 0600)) == -1) return; oldidfds = didfds; didfds = 0; ftmp = SHOUT; SHOUT = fd; dumphist[2] = hbuf; dohist(dumphist, NULL); SHOUT = ftmp; (void) close(fd); didfds = oldidfds; } }
/* * dfollow - change to arg directory; fall back on cdpath if not valid */ static Char * dfollow(Char *cp) { Char *dp; struct varent *c; char ebuf[PATH_MAX]; int serrno; cp = globone(cp, G_ERROR); /* * if we are ignoring symlinks, try to fix relatives now. */ dp = dnormalize(cp); if (chdir(short2str(dp)) >= 0) { free(cp); return dgoto(dp); } else { free(dp); if (chdir(short2str(cp)) >= 0) return dgoto(cp); serrno = errno; } if (cp[0] != '/' && !prefix(STRdotsl, cp) && !prefix(STRdotdotsl, cp) && (c = adrof(STRcdpath))) { Char **cdp; Char *p; Char buf[PATH_MAX]; for (cdp = c->vec; *cdp; cdp++) { for (dp = buf, p = *cdp; (*dp++ = *p++) != '\0';) continue; dp[-1] = '/'; for (p = cp; (*dp++ = *p++) != '\0';) continue; if (chdir(short2str(buf)) >= 0) { printd = 1; free(cp); cp = Strsave(buf); return dgoto(cp); } } } dp = value(cp); if ((dp[0] == '/' || dp[0] == '.') && chdir(short2str(dp)) >= 0) { free(cp); cp = Strsave(dp); printd = 1; return dgoto(cp); } (void) strlcpy(ebuf, short2str(cp), sizeof ebuf); free(cp); stderror(ERR_SYSTEM, ebuf, strerror(serrno)); return (NULL); }
void autoset_kanji(void) { char *codeset = nl_langinfo(CODESET); if (*codeset == '\0') { if (adrof(STRnokanji) == NULL) setNS(STRnokanji); return; } if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) { if (adrof(STRnokanji) == NULL) setNS(STRnokanji); return; } if (adrof(STRnokanji) != NULL) unsetv(STRnokanji); }
static struct varent * getvx(Char *vp, int subscr) { struct varent *v = adrof(vp); if (v == 0) udvar(vp); if (subscr < 1 || subscr > blklen(v->vec)) stderror(ERR_NAME | ERR_RANGE); return (v); }
Char * globone(Char *str, int action) { Char *v[2], **vl, **vo; int gflg, noglob; noglob = adrof(STRnoglob) != 0; v[0] = str; v[1] = 0; gflg = tglob(v); if (gflg == G_NONE) return (strip(Strsave(str))); if (gflg & G_CSH) { /* * Expand back-quote, tilde and brace */ vo = globexpand(v, noglob); if (noglob || (gflg & G_GLOB) == 0) { vl = vo; goto result; } cleanup_push(vo, blk_cleanup); } else if (noglob || (gflg & G_GLOB) == 0) return (strip(Strsave(str))); else vo = v; vl = libglob(vo); if (gflg & G_CSH) { if (vl != vo) cleanup_until(vo); else cleanup_ignore(vo); } if (vl == NULL) { setname(short2str(str)); stderror(ERR_NAME | ERR_NOMATCH); } result: if (vl && vl[0] == NULL) { xfree(vl); return (Strsave(STRNULL)); } if (vl && vl[1]) return (handleone(str, vl, action)); else { str = strip(*vl); xfree(vl); return (str); } }
void setalarm(int lck) { struct varent *vp; Char *cp; unsigned alrm_time = 0, logout_time, lock_time; time_t cl, nl, sched_dif; if ((vp = adrof(STRautologout)) != NULL && vp->vec != NULL) { if ((cp = vp->vec[0]) != 0) { if ((logout_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { #ifdef SOLARIS2 /* * Solaris alarm(2) uses a timer based in clock ticks * internally so it multiplies our value with CLK_TCK... * Of course that can overflow leading to unexpected * results, so we clip it here. Grr. Where is that * documented folks? */ if (logout_time >= 0x7fffffff / CLK_TCK) logout_time = 0x7fffffff / CLK_TCK; #endif /* SOLARIS2 */ alrm_time = logout_time; alm_fun = auto_logout; } } if ((cp = vp->vec[1]) != 0) { if ((lock_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { if (lck) { if (alrm_time == 0 || lock_time < alrm_time) { alrm_time = lock_time; alm_fun = auto_lock; } } else /* lock_time always < alrm_time */ if (alrm_time) alrm_time -= lock_time; } } } if ((nl = sched_next()) != -1) { (void) time(&cl); sched_dif = nl > cl ? nl - cl : 0; if ((alrm_time == 0) || ((unsigned) sched_dif < alrm_time)) { alrm_time = ((unsigned) sched_dif) + 1; alm_fun = sched_run; } } alrmcatch_disabled = 0; (void) alarm(alrm_time); /* Autologout ON */ }
struct varent * getvx(tchar *vp, int subscr) { struct varent *v = adrof(vp); #ifdef TRACE tprintf("TRACE- getvx()\n"); #endif if (v == 0) udvar(vp); if (subscr < 1 || subscr > blklen(v->vec)) bferr("Subscript out of range"); return (v); }
void xechoit(Char **t) { if (adrof(STRecho)) { int odidfds = didfds; (void)fflush(csherr); odidfds = didfds; didfds = 0; blkpr(csherr, t); (void)fputc('\n', csherr); (void)fflush(csherr); didfds = odidfds; } }
void xechoit(tchar **t) { #ifdef TRACE tprintf("TRACE- xechoit()\n"); #endif if (adrof(S_echo /* "echo" */)) { flush(); haderr = 1; blkpr(t), Putchar('\n'); haderr = 0; } }
void prusage(FILE *fp, struct rusage *r0, struct rusage *r1, struct timespec *e, struct timespec *b) { struct varent *vp; const char *cp; vp = adrof(STRtime); if (vp && vp->vec[0] && vp->vec[1]) cp = short2str(vp->vec[1]); else cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; prusage1(fp, cp, r0, r1, e, b); }
static int iscommand(Char *name) { struct varent *v; Char **pv, *sav; int hashval, hashval1, i; int slash; hashval = 0; slash = any(short2str(name), '/'); v = adrof(STRpath); if (v == 0 || v->vec[0] == 0 || slash) pv = justabs; else pv = v->vec; sav = Strspl(STRslash, name); /* / command name for postpending */ if (havhash) hashval = hashname(name); i = 0; do { 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 */ if (executable(NULL, name, 0)) { free(sav); return i + 1; } } else { if (executable(*pv, sav, 0)) { free(sav); return i + 1; } } cont: pv++; i++; } while (*pv); free(sav); return 0; }
void /*ARGSUSED*/ shift(Char **v, struct command *t) { struct varent *argv; Char *name; v++; name = *v; if (name == 0) name = STRargv; else (void) strip(name); argv = adrof(name); if (argv == 0) udvar(name); if (argv->vec[0] == 0) stderror(ERR_NAME | ERR_NOMORE); lshift(argv->vec, 1); }
static void dgetstack(void) { int i = 0; Char **dblk, **dbp; struct directory *dn; if (adrof(STRdirstack) == NULL) return; for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, i++) continue; dbp = dblk = xmalloc((i + 1) * sizeof(Char *)); for (dn = dhead.di_prev; dn != &dhead; dn = dn->di_prev, dbp++) *dbp = Strsave(dn->di_name); *dbp = NULL; cleanup_push(dblk, blk_cleanup); setq(STRdirstack, dblk, &shvhed, VAR_READWRITE); cleanup_ignore(dblk); cleanup_until(dblk); }
/*ARGSUSED*/ void shift(Char **v, struct command *c) { struct varent *argv; Char *name; USE(c); v++; name = *v; if (name == 0) name = STRargv; else (void) strip(name); argv = adrof(name); if (argv == NULL || argv->vec == NULL) udvar(name); if (argv->vec[0] == 0) stderror(ERR_NAME | ERR_NOMORE); lshift(argv->vec, 1); update_vars(name); }
/* * Expand and glob the words after an i/o redirection. * If more than one word is generated, then update the command vector. * * This is done differently in all the shells: * 1. in the bourne shell and ksh globbing is not performed * 2. Bash/csh say ambiguous * 3. zsh does i/o to/from all the files * 4. itcsh concatenates the words. * * I don't know what is best to do. I think that Ambiguous is better * than restructuring the command vector, because the user can get * unexpected results. In any case, the command vector restructuring * code is present and the user can choose it by setting noambiguous */ static Char * splicepipe(struct command *t, Char *cp) { Char *blk[2]; if (adrof(STRnoambiguous)) { Char **pv; int gflag; blk[0] = Dfix1(cp); /* expand $ */ blk[1] = NULL; gflag = tglob(blk); if (gflag) { pv = globall(blk, gflag); if (pv == NULL) { setname(short2str(blk[0])); xfree(blk[0]); stderror(ERR_NAME | ERR_NOMATCH); } if (pv[1] != NULL) { /* we need to fix the command vector */ Char **av = blkspl(t->t_dcom, &pv[1]); xfree(t->t_dcom); t->t_dcom = av; } xfree(blk[0]); blk[0] = pv[0]; xfree(pv); } } else { Char *buf; buf = Dfix1(cp); cleanup_push(buf, xfree); blk[0] = globone(buf, G_ERROR); cleanup_until(buf); } return(blk[0]); }
void /*ARGSUSED*/ dohash(Char **v, struct command *t) { struct dirent *dp; struct varent *pathv; DIR *dirp; Char **pv; size_t cnt; int hashval, i; i = 0; havhash = 1; pathv = adrof(STRpath); for (cnt = 0; cnt < sizeof xhash; cnt++) xhash[cnt] = 0; if (pathv == 0) return; for (pv = pathv->vec; *pv; pv++, i++) { if (pv[0][0] != '/') continue; dirp = opendir(short2str(*pv)); if (dirp == NULL) continue; while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) continue; hashval = hash(hashname(str2short(dp->d_name)), i); bis(xhash, hashval); /* tw_add_comm_name (dp->d_name); */ } (void) closedir(dirp); } }
/* * Expand and glob the words after an i/o redirection. * If more than one word is generated, then update the command vector. * * This is done differently in all the shells: * 1. in the bourne shell and ksh globbing is not performed * 2. Bash/csh say ambiguous * 3. zsh does i/o to/from all the files * 4. itcsh concatenates the words. * * I don't know what is best to do. I think that Ambiguous is better * than restructuring the command vector, because the user can get * unexpected results. In any case, the command vector restructuring * code is present and the user can choose it by setting noambiguous */ static Char * splicepipe(struct command *t, Char *cp /* word after < or > */) { Char *blk[2]; if (adrof(STRnoambiguous)) { Char **pv; blk[0] = Dfix1(cp); /* expand $ */ blk[1] = NULL; gflag = 0, tglob(blk); if (gflag) { pv = globall(blk); if (pv == NULL) { setname(vis_str(blk[0])); xfree((ptr_t) blk[0]); stderror(ERR_NAME | ERR_NOMATCH); /* NOTREACHED */ } gargv = NULL; if (pv[1] != NULL) { /* we need to fix the command vector */ Char **av = blkspl(t->t_dcom, &pv[1]); xfree((ptr_t) t->t_dcom); t->t_dcom = av; } xfree((ptr_t) blk[0]); blk[0] = pv[0]; xfree((ptr_t) pv); } } else { blk[0] = globone(blk[1] = Dfix1(cp), G_ERROR); xfree((ptr_t) blk[1]); } return(blk[0]); }
static int tellmewhat(struct wordent *lexp, Char *str) { struct biltins *bptr; struct wordent *sp; Char *cmd, *s0, *s1, *s2; int i; int aliased, found; Char qc; aliased = 0; sp = lexp->next; if (adrof1(sp->word, &aliases)) { alias(lexp); sp = lexp->next; aliased = 1; } s0 = sp->word; /* to get the memory freeing right... */ /* handle quoted alias hack */ if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE) (sp->word)++; /* do quoting, if it hasn't been done */ s1 = s2 = sp->word; while (*s2) switch (*s2) { case '\'': case '"': qc = *s2++; while (*s2 && *s2 != qc) *s1++ = (Char)(*s2++ | QUOTE); if (*s2) s2++; break; case '\\': if (*++s2) *s1++ = (Char)(*s2++ | QUOTE); break; default: *s1++ = *s2++; } *s1 = '\0'; for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) { if (eq(sp->word, str2short(bptr->bname))) { if (str == NULL) { if (aliased) prlex(cshout, lexp); (void)fprintf(cshout, "%s: shell built-in command.\n", vis_str(sp->word)); } else (void)Strcpy(str, sp->word); sp->word = s0; /* we save and then restore this */ return 1; } } sp->word = cmd = globone(sp->word, G_IGNORE); if ((i = iscommand(sp->word)) != 0) { Char **pv; struct varent *v; int slash = any(short2str(sp->word), '/'); v = adrof(STRpath); if (v == 0 || v->vec[0] == 0 || slash) pv = justabs; else pv = v->vec; while (--i) pv++; if (pv[0][0] == 0 || eq(pv[0], STRdot)) { if (!slash) { sp->word = Strspl(STRdotsl, sp->word); prlex(cshout, lexp); free(sp->word); } else prlex(cshout, lexp); } else { s1 = Strspl(*pv, STRslash); sp->word = Strspl(s1, sp->word); free(s1); if (str == NULL) prlex(cshout, lexp); else (void)Strcpy(str, sp->word); free(sp->word); } found = 1; } else { if (str == NULL) { if (aliased) prlex(cshout, lexp); (void)fprintf(csherr, "%s: Command not found.\n", vis_str(sp->word)); } else (void)Strcpy(str, sp->word); found = 0; } sp->word = s0; /* we save and then restore this */ free(cmd); return found; }
/* * 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; } } }
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 */ }