diff options
-rw-r--r-- | shell/ash.c | 402 |
1 files changed, 195 insertions, 207 deletions
diff --git a/shell/ash.c b/shell/ash.c index c96517c3a..5c9060cad 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -74,7 +74,6 @@ #define signed_char2int(sc) ((int)((signed char)sc)) - /* ============ Shell options */ static const char *const optletters_optnames[] = { @@ -139,6 +138,8 @@ static const char homestr[] = "HOME"; static const char snlfmt[] = "%s\n"; static const char illnum[] = "Illegal number: %s"; +static char *minusc; /* argument to -c option */ + static int isloginsh; /* pid of main shell */ static int rootpid; @@ -2464,14 +2465,6 @@ pwdcmd(int argc, char **argv) #define PEOA_OR_PEOF PEOF #endif -/* - * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise - * (assuming ascii char codes, as the original implementation did) - */ -#define is_special(c) \ - ((((unsigned int)c) - 33 < 32) \ - && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1)) - /* number syntax index */ #define BASESYNTAX 0 /* not in quotes */ #define DQSYNTAX 1 /* in double quotes */ @@ -2878,15 +2871,8 @@ static const char syntax_index_table[258] = { #endif /* USE_SIT_FUNCTION */ -/* main.h */ - -static void readcmdfile(char *); - - /* options.h */ -static char *minusc; /* argument to -c option */ - static void optschanged(void); static void setparam(char **); static void freeparam(volatile struct shparam *); @@ -3120,7 +3106,6 @@ unaliascmd(int argc, char **argv) #define SHOW_PID 0x04 /* include process pid */ #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */ - /* * A job structure contains information about a job. A job is either a * single process or a set of processes contained in a pipeline. In the @@ -7823,190 +7808,6 @@ find_builtin(const char *name) } /* - * Resolve a command name. If you change this routine, you may have to - * change the shellexec routine as well. - */ -static void -find_command(char *name, struct cmdentry *entry, int act, const char *path) -{ - struct tblentry *cmdp; - int idx; - int prev; - char *fullname; - struct stat statb; - int e; - int updatetbl; - struct builtincmd *bcmd; - - /* If name contains a slash, don't use PATH or hash table */ - if (strchr(name, '/') != NULL) { - entry->u.index = -1; - if (act & DO_ABS) { - while (stat(name, &statb) < 0) { -#ifdef SYSV - if (errno == EINTR) - continue; -#endif - entry->cmdtype = CMDUNKNOWN; - return; - } - } - entry->cmdtype = CMDNORMAL; - return; - } - -#if ENABLE_FEATURE_SH_STANDALONE_SHELL - if (find_applet_by_name(name)) { - entry->cmdtype = CMDNORMAL; - entry->u.index = -1; - return; - } -#endif - - if (is_safe_applet(name)) { - entry->cmdtype = CMDNORMAL; - entry->u.index = -1; - return; - } - - updatetbl = (path == pathval()); - if (!updatetbl) { - act |= DO_ALTPATH; - if (strstr(path, "%builtin") != NULL) - act |= DO_ALTBLTIN; - } - - /* If name is in the table, check answer will be ok */ - cmdp = cmdlookup(name, 0); - if (cmdp != NULL) { - int bit; - - switch (cmdp->cmdtype) { - default: -#if DEBUG - abort(); -#endif - case CMDNORMAL: - bit = DO_ALTPATH; - break; - case CMDFUNCTION: - bit = DO_NOFUNC; - break; - case CMDBUILTIN: - bit = DO_ALTBLTIN; - break; - } - if (act & bit) { - updatetbl = 0; - cmdp = NULL; - } else if (cmdp->rehash == 0) - /* if not invalidated by cd, we're done */ - goto success; - } - - /* If %builtin not in path, check for builtin next */ - bcmd = find_builtin(name); - if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || ( - act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0 - ))) - goto builtin_success; - - /* We have to search path. */ - prev = -1; /* where to start */ - if (cmdp && cmdp->rehash) { /* doing a rehash */ - if (cmdp->cmdtype == CMDBUILTIN) - prev = builtinloc; - else - prev = cmdp->param.index; - } - - e = ENOENT; - idx = -1; - loop: - while ((fullname = padvance(&path, name)) != NULL) { - stunalloc(fullname); - idx++; - if (pathopt) { - if (prefix(pathopt, "builtin")) { - if (bcmd) - goto builtin_success; - continue; - } else if (!(act & DO_NOFUNC) && - prefix(pathopt, "func")) { - /* handled below */ - } else { - /* ignore unimplemented options */ - continue; - } - } - /* if rehash, don't redo absolute path names */ - if (fullname[0] == '/' && idx <= prev) { - if (idx < prev) - continue; - 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 (!S_ISREG(statb.st_mode)) - continue; - if (pathopt) { /* this is a %func directory */ - stalloc(strlen(fullname) + 1); - readcmdfile(fullname); - cmdp = cmdlookup(name, 0); - if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION) - ash_msg_and_raise_error("%s not defined in %s", name, fullname); - stunalloc(fullname); - goto success; - } - TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); - if (!updatetbl) { - entry->cmdtype = CMDNORMAL; - entry->u.index = idx; - return; - } - INT_OFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDNORMAL; - cmdp->param.index = idx; - INT_ON; - goto success; - } - - /* We failed. If there was an entry for this command, delete it */ - if (cmdp && updatetbl) - delete_cmd_entry(); - if (act & DO_ERR) - ash_msg("%s: %s", name, errmsg(e, "not found")); - entry->cmdtype = CMDUNKNOWN; - return; - - builtin_success: - if (!updatetbl) { - entry->cmdtype = CMDBUILTIN; - entry->u.cmd = bcmd; - return; - } - INT_OFF; - cmdp = cmdlookup(name, 1); - cmdp->cmdtype = CMDBUILTIN; - cmdp->param.cmd = bcmd; - INT_ON; - success: - cmdp->rehash = 0; - entry->cmdtype = cmdp->cmdtype; - entry->u = cmdp->param; -} - -/* * Execute a simple command. */ static int back_exitstatus; /* exit status of backquoted command */ @@ -8410,7 +8211,6 @@ static int checkkwd; #define CHKKWD 0x2 #define CHKNL 0x4 - static void popstring(void) { @@ -10096,7 +9896,6 @@ readtoken1(int firstc, int syntax, char *eofmark, int striptabs) return lasttoken; /* end of readtoken routine */ - /* * Check to see whether we are at the end of the here document. When this * is called, c is set to the first character of the next input line. If @@ -10133,7 +9932,6 @@ checkend: { goto checkend_return; } - /* * Parse a redirection operator. The variable "out" points to a string * specifying the fd to be redirected. The variable "c" contains the @@ -10198,11 +9996,16 @@ parseredir: { goto parseredir_return; } - /* * Parse a substitution. At this point, we have read the dollar sign * and nothing else. */ + +/* is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise + * (assuming ascii char codes, as the original implementation did) */ +#define is_special(c) \ + ((((unsigned int)c) - 33 < 32) \ + && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1)) parsesub: { int subtype; int typeloc; @@ -10304,7 +10107,6 @@ parsesub: { goto parsesub_return; } - /* * Called to parse command substitutions. Newstyle is set if the command * is enclosed inside $(...); nlpp is a pointer to the head of the linked @@ -10993,6 +10795,193 @@ readcmdfile(char *name) } +/* ============ find_command inplementation */ + +/* + * Resolve a command name. If you change this routine, you may have to + * change the shellexec routine as well. + */ +static void +find_command(char *name, struct cmdentry *entry, int act, const char *path) +{ + struct tblentry *cmdp; + int idx; + int prev; + char *fullname; + struct stat statb; + int e; + int updatetbl; + struct builtincmd *bcmd; + + /* If name contains a slash, don't use PATH or hash table */ + if (strchr(name, '/') != NULL) { + entry->u.index = -1; + if (act & DO_ABS) { + while (stat(name, &statb) < 0) { +#ifdef SYSV + if (errno == EINTR) + continue; +#endif + entry->cmdtype = CMDUNKNOWN; + return; + } + } + entry->cmdtype = CMDNORMAL; + return; + } + +#if ENABLE_FEATURE_SH_STANDALONE_SHELL + if (find_applet_by_name(name)) { + entry->cmdtype = CMDNORMAL; + entry->u.index = -1; + return; + } +#endif + + if (is_safe_applet(name)) { + entry->cmdtype = CMDNORMAL; + entry->u.index = -1; + return; + } + + updatetbl = (path == pathval()); + if (!updatetbl) { + act |= DO_ALTPATH; + if (strstr(path, "%builtin") != NULL) + act |= DO_ALTBLTIN; + } + + /* If name is in the table, check answer will be ok */ + cmdp = cmdlookup(name, 0); + if (cmdp != NULL) { + int bit; + + switch (cmdp->cmdtype) { + default: +#if DEBUG + abort(); +#endif + case CMDNORMAL: + bit = DO_ALTPATH; + break; + case CMDFUNCTION: + bit = DO_NOFUNC; + break; + case CMDBUILTIN: + bit = DO_ALTBLTIN; + break; + } + if (act & bit) { + updatetbl = 0; + cmdp = NULL; + } else if (cmdp->rehash == 0) + /* if not invalidated by cd, we're done */ + goto success; + } + + /* If %builtin not in path, check for builtin next */ + bcmd = find_builtin(name); + if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || ( + act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0 + ))) + goto builtin_success; + + /* We have to search path. */ + prev = -1; /* where to start */ + if (cmdp && cmdp->rehash) { /* doing a rehash */ + if (cmdp->cmdtype == CMDBUILTIN) + prev = builtinloc; + else + prev = cmdp->param.index; + } + + e = ENOENT; + idx = -1; + loop: + while ((fullname = padvance(&path, name)) != NULL) { + stunalloc(fullname); + idx++; + if (pathopt) { + if (prefix(pathopt, "builtin")) { + if (bcmd) + goto builtin_success; + continue; + } else if (!(act & DO_NOFUNC) && + prefix(pathopt, "func")) { + /* handled below */ + } else { + /* ignore unimplemented options */ + continue; + } + } + /* if rehash, don't redo absolute path names */ + if (fullname[0] == '/' && idx <= prev) { + if (idx < prev) + continue; + 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 (!S_ISREG(statb.st_mode)) + continue; + if (pathopt) { /* this is a %func directory */ + stalloc(strlen(fullname) + 1); + readcmdfile(fullname); + cmdp = cmdlookup(name, 0); + if (cmdp == NULL || cmdp->cmdtype != CMDFUNCTION) + ash_msg_and_raise_error("%s not defined in %s", name, fullname); + stunalloc(fullname); + goto success; + } + TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); + if (!updatetbl) { + entry->cmdtype = CMDNORMAL; + entry->u.index = idx; + return; + } + INT_OFF; + cmdp = cmdlookup(name, 1); + cmdp->cmdtype = CMDNORMAL; + cmdp->param.index = idx; + INT_ON; + goto success; + } + + /* We failed. If there was an entry for this command, delete it */ + if (cmdp && updatetbl) + delete_cmd_entry(); + if (act & DO_ERR) + ash_msg("%s: %s", name, errmsg(e, "not found")); + entry->cmdtype = CMDUNKNOWN; + return; + + builtin_success: + if (!updatetbl) { + entry->cmdtype = CMDBUILTIN; + entry->u.cmd = bcmd; + return; + } + INT_OFF; + cmdp = cmdlookup(name, 1); + cmdp->cmdtype = CMDBUILTIN; + cmdp->param.cmd = bcmd; + INT_ON; + success: + cmdp->rehash = 0; + entry->cmdtype = cmdp->cmdtype; + entry->u = cmdp->param; +} + + /* ============ redir.c * * Code for dealing with input/output redirection. @@ -11184,7 +11173,6 @@ dupredirect(union node *redir, int f) } } - /* * Process a list of redirection commands. If the REDIR_PUSH flag is set, * old file descriptors are stashed away so that the redirection can be |