📄 exec.c
字号:
/* If name is in the table, and not invalidated by cd, we're done */ if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) goto success; /* If %builtin not in path, check for builtin next */ if (builtinloc < 0 && (i = find_builtin(name)) >= 0) { INTOFF; cmdp = cmdlookup(name, 1); cmdp->cmdtype = CMDBUILTIN; cmdp->param.index = i; INTON; goto success; } /* We have to search path. */ prev = -1; /* where to start */ if (cmdp) { /* doing a rehash */ if (cmdp->cmdtype == CMDBUILTIN) prev = builtinloc; else prev = cmdp->param.index; } path = pathval(); e = ENOENT; index = -1;loop: while ((fullname = padvance(&path, name)) != NULL) { stunalloc(fullname); index++; if (pathopt) { if (prefix("builtin", pathopt)) { if ((i = find_builtin(name)) < 0) goto loop; INTOFF; cmdp = cmdlookup(name, 1); cmdp->cmdtype = CMDBUILTIN; cmdp->param.index = i; INTON; goto success; } else if (prefix("func", pathopt)) { /* handled below */ } else { goto loop; /* ignore unimplemented options */ } } /* if rehash, don't redo absolute path names */ if (fullname[0] == '/' && index <= prev) { if (index < prev) goto loop; TRACE(("searchexec \"%s\": no change\n", name)); goto success; } while (stat(fullname, &statb) < 0) {#ifdef SYSV if (errno == EINTR) continue;#endif if (errno != ENOENT && errno != ENOTDIR) e = errno; goto loop; } e = EACCES; /* if we fail, this will be the error */ if ((statb.st_mode & S_IFMT) != S_IFREG) goto loop; if (pathopt) { /* this is a %func directory */ stalloc(strlen(fullname) + 1); readcmdfile(fullname); if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) error("%s not defined in %s", name, fullname); stunalloc(fullname); goto success; } if (statb.st_uid == geteuid()) { if ((statb.st_mode & 0100) == 0) goto loop; } else if (statb.st_gid == getegid()) { if ((statb.st_mode & 010) == 0) goto loop; } else {#if __minix_vmd || defined(BSD) gid_t group_list[NGROUPS_MAX]; int ngroups, i; ngroups = getgroups(NGROUPS_MAX, group_list); for (i = 0; i < ngroups; i++) { if (statb.st_gid == group_list[i]) break; } if (i < ngroups) { if ((statb.st_mode & 010) == 0) goto loop; } else#endif if ((statb.st_mode & 01) == 0) goto loop; } TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); INTOFF; cmdp = cmdlookup(name, 1); cmdp->cmdtype = CMDNORMAL; cmdp->param.index = index; INTON; goto success; } /* We failed. If there was an entry for this command, delete it */ if (cmdp) delete_cmd_entry(); if (printerr) outfmt(out2, "%s: %s\n", name, errmsg(e, E_EXEC)); entry->cmdtype = CMDUNKNOWN; return;success: cmdp->rehash = 0; entry->cmdtype = cmdp->cmdtype; entry->u = cmdp->param;}/* * Search the table of builtin commands. */intfind_builtin(name) char *name; { const register struct builtincmd *bp; for (bp = builtincmd ; bp->name ; bp++) { if (*bp->name == *name && equal(bp->name, name)) return bp->code; } return -1;}/* * Called when a cd is done. Marks all commands so the next time they * are executed they will be rehashed. */voidhashcd() { struct tblentry **pp; struct tblentry *cmdp; for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) { for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (cmdp->cmdtype == CMDNORMAL || cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0) cmdp->rehash = 1; } }}/* * Called before PATH is changed. The argument is the new value of PATH; * pathval() still returns the old value at this point. Called with * interrupts off. */voidchangepath(newval) char *newval; { char *old, *new; int index; int firstchange; int bltin; old = pathval(); new = newval; firstchange = 9999; /* assume no change */ index = 0; bltin = -1; for (;;) { if (*old != *new) { firstchange = index; if (*old == '\0' && *new == ':' || *old == ':' && *new == '\0') firstchange++; old = new; /* ignore subsequent differences */ } if (*new == '\0') break; if (*new == '%' && bltin < 0 && prefix("builtin", new + 1)) bltin = index; if (*new == ':') { index++; } new++, old++; } if (builtinloc < 0 && bltin >= 0) builtinloc = bltin; /* zap builtins */ if (builtinloc >= 0 && bltin < 0) firstchange = 0; clearcmdentry(firstchange); builtinloc = bltin;}/* * Clear out command entries. The argument specifies the first entry in * PATH which has changed. */STATIC voidclearcmdentry(firstchange) { struct tblentry **tblp; struct tblentry **pp; struct tblentry *cmdp; INTOFF; for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { pp = tblp; while ((cmdp = *pp) != NULL) { if (cmdp->cmdtype == CMDNORMAL && cmdp->param.index >= firstchange || cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange) { *pp = cmdp->next; ckfree(cmdp); } else { pp = &cmdp->next; } } } INTON;}/* * Delete all functions. */#ifdef mkinitMKINIT void deletefuncs();SHELLPROC { deletefuncs();}#endifvoiddeletefuncs() { struct tblentry **tblp; struct tblentry **pp; struct tblentry *cmdp; INTOFF; for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) { pp = tblp; while ((cmdp = *pp) != NULL) { if (cmdp->cmdtype == CMDFUNCTION) { *pp = cmdp->next; freefunc(cmdp->param.func); ckfree(cmdp); } else { pp = &cmdp->next; } } } INTON;}/* * Locate a command in the command hash table. If "add" is nonzero, * add the command to the table if it is not already present. The * variable "lastcmdentry" is set to point to the address of the link * pointing to the entry, so that delete_cmd_entry can delete the * entry. */struct tblentry **lastcmdentry;STATIC struct tblentry *cmdlookup(name, add) char *name; { int hashval; register char *p; struct tblentry *cmdp; struct tblentry **pp; p = name; hashval = *p << 4; while (*p) hashval += *p++; hashval &= 0x7FFF; pp = &cmdtable[hashval % CMDTABLESIZE]; for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) { if (equal(cmdp->cmdname, name)) break; pp = &cmdp->next; } if (add && cmdp == NULL) { INTOFF; cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB + strlen(name) + 1); cmdp->next = NULL; cmdp->cmdtype = CMDUNKNOWN; cmdp->rehash = 0; strcpy(cmdp->cmdname, name); INTON; } lastcmdentry = pp; return cmdp;}/* * Delete the command entry returned on the last lookup. */STATIC voiddelete_cmd_entry() { struct tblentry *cmdp; INTOFF; cmdp = *lastcmdentry; *lastcmdentry = cmdp->next; ckfree(cmdp); INTON;}#ifdef notdefvoidgetcmdentry(name, entry) char *name; struct cmdentry *entry; { struct tblentry *cmdp = cmdlookup(name, 0); if (cmdp) { entry->u = cmdp->param; entry->cmdtype = cmdp->cmdtype; } else { entry->cmdtype = CMDUNKNOWN; entry->u.index = 0; }}#endif/* * Add a new command entry, replacing any existing command entry for * the same name. */voidaddcmdentry(name, entry) char *name; struct cmdentry *entry; { struct tblentry *cmdp; INTOFF; cmdp = cmdlookup(name, 1); if (cmdp->cmdtype == CMDFUNCTION) { freefunc(cmdp->param.func); } cmdp->cmdtype = entry->cmdtype; cmdp->param = entry->u; INTON;}/* * Define a shell function. */voiddefun(name, func) char *name; union node *func; { struct cmdentry entry; INTOFF; entry.cmdtype = CMDFUNCTION; entry.u.func = copyfunc(func); addcmdentry(name, &entry); INTON;}/* * Delete a function if it exists. */voidunsetfunc(name) char *name; { struct tblentry *cmdp; if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { freefunc(cmdp->param.func); delete_cmd_entry(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -