From 95ad413d4a493285a5560182fb10217819d7c357 Mon Sep 17 00:00:00 2001 From: jilles Date: Fri, 4 Feb 2011 22:47:55 +0000 Subject: sh: Remove special code for shell scripts without magic number. These are called "shell procedures" in the source. If execve() failed with [ENOEXEC], the shell would reinitialize itself and execute the program as a script. This requires a fair amount of code which is not frequently used (most scripts have a #! magic number). Therefore just execute a new instance of sh (_PATH_BSHELL) to run the script. --- bin/sh/TOUR | 19 +------------------ bin/sh/alias.c | 10 +--------- bin/sh/alias.h | 1 - bin/sh/error.h | 3 +-- bin/sh/eval.c | 28 ++++++++++------------------ bin/sh/exec.c | 49 ++++++------------------------------------------- bin/sh/exec.h | 1 - bin/sh/init.h | 1 - bin/sh/input.c | 7 +------ bin/sh/jobs.c | 16 ---------------- bin/sh/main.c | 18 ++---------------- bin/sh/mkinit.c | 6 ------ bin/sh/options.c | 15 --------------- bin/sh/redir.c | 4 ---- bin/sh/sh.1 | 14 ++++---------- bin/sh/trap.c | 16 ---------------- bin/sh/var.c | 43 +------------------------------------------ 17 files changed, 27 insertions(+), 224 deletions(-) (limited to 'bin/sh') diff --git a/bin/sh/TOUR b/bin/sh/TOUR index af2773a..8448966 100644 --- a/bin/sh/TOUR +++ b/bin/sh/TOUR @@ -44,10 +44,6 @@ C source files for entries looking like: back to the main command loop */ } - SHELLPROC { - x = 3; /* executed when the shell runs a shell procedure */ - } - It pulls this code out into routines which are when particular events occur. The intent is to improve modularity by isolating the information about which modules need to be explicitly @@ -80,12 +76,7 @@ EXCEPTIONS: Code for dealing with exceptions appears in exceptions.c. The C language doesn't include exception handling, so I implement it using setjmp and longjmp. The global variable exception contains the type of exception. EXERROR is raised by -calling error. EXINT is an interrupt. EXSHELLPROC is an excep- -tion which is raised when a shell procedure is invoked. The pur- -pose of EXSHELLPROC is to perform the cleanup actions associated -with other exceptions. After these cleanup actions, the shell -can interpret a shell procedure itself without exec'ing a new -copy of the shell. +calling error. EXINT is an interrupt. INTERRUPTS: In an interactive shell, an interrupt will cause an EXINT exception to return to the main command loop. (Exception: @@ -270,14 +261,6 @@ When a program is run, the code in eval.c sticks any environment variables which precede the command (as in "PATH=xxx command") in the variable table as the simplest way to strip duplicates, and then calls "environment" to get the value of the environment. -There are two consequences of this. First, if an assignment to -PATH precedes the command, the value of PATH before the assign- -ment must be remembered and passed to shellexec. Second, if the -program turns out to be a shell procedure, the strings from the -environment variables which preceded the command must be pulled -out of the table and replaced with strings obtained from malloc, -since the former will automatically be freed when the stack (see -the entry on memalloc.c) is emptied. BUILTIN COMMANDS: The procedures for handling these are scat- tered throughout the code, depending on which location appears diff --git a/bin/sh/alias.c b/bin/sh/alias.c index 0b7e31a..4662519 100644 --- a/bin/sh/alias.c +++ b/bin/sh/alias.c @@ -145,15 +145,7 @@ unalias(const char *name) return (1); } -#ifdef mkinit -MKINIT void rmaliases(void); - -SHELLPROC { - rmaliases(); -} -#endif - -void +static void rmaliases(void) { struct alias *ap, *tmp; diff --git a/bin/sh/alias.h b/bin/sh/alias.h index d8f0308..7983663 100644 --- a/bin/sh/alias.h +++ b/bin/sh/alias.h @@ -45,4 +45,3 @@ struct alias { struct alias *lookupalias(const char *, int); int aliascmd(int, char **); int unaliascmd(int, char **); -void rmaliases(void); diff --git a/bin/sh/error.h b/bin/sh/error.h index bf11c67..a1d2b4f 100644 --- a/bin/sh/error.h +++ b/bin/sh/error.h @@ -56,8 +56,7 @@ extern volatile sig_atomic_t exception; /* exceptions */ #define EXINT 0 /* SIGINT received */ #define EXERROR 1 /* a generic error */ -#define EXSHELLPROC 2 /* execute a shell procedure */ -#define EXEXEC 3 /* command execution failed */ +#define EXEXEC 2 /* command execution failed */ /* diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 0bb5322..2d3f631 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -111,10 +111,6 @@ RESET { loopnest = 0; funcnest = 0; } - -SHELLPROC { - exitstatus = 0; -} #endif @@ -732,7 +728,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; - argv = stalloc(sizeof (char *) * (argc + 1)); + /* Add one slot at the beginning for tryexec(). */ + argv = stalloc(sizeof (char *) * (argc + 2)); + argv++; for (sp = arglist.list ; sp ; sp = sp->next) { TRACE(("evalcommand arg: %s\n", sp->text)); @@ -927,14 +925,10 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) reffunc(cmdentry.u.func); savehandler = handler; if (setjmp(jmploc.loc)) { - if (exception == EXSHELLPROC) - freeparam(&saveparam); - else { - freeparam(&shellparam); - shellparam = saveparam; - if (exception == EXERROR || exception == EXEXEC) - popredir(); - } + freeparam(&shellparam); + shellparam = saveparam; + if (exception == EXERROR || exception == EXEXEC) + popredir(); unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; @@ -1016,11 +1010,9 @@ cmddone: out2 = &errout; freestdout(); handler = savehandler; - if (e != EXSHELLPROC) { - commandname = savecmdname; - if (jp) - exitshell(exitstatus); - } + commandname = savecmdname; + if (jp) + exitshell(exitstatus); if (flags == EV_BACKCMD) { backcmd->buf = memout.buf; backcmd->nleft = memout.nextc - memout.buf; diff --git a/bin/sh/exec.c b/bin/sh/exec.c index 2d781ab..07fa8bb 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include /* @@ -105,6 +106,8 @@ static void delete_cmd_entry(void); /* * Exec a program. Never returns. If you change this routine, you may * have to change the find_command routine as well. + * + * The argv array may be changed and element argv[-1] should be writable. */ void @@ -147,12 +150,9 @@ tryexec(char *cmd, char **argv, char **envp) execve(cmd, argv, envp); e = errno; if (e == ENOEXEC) { - initshellproc(); - setinputfile(cmd, 0); - commandname = arg0 = savestr(argv[0]); - setparam(argv + 1); - exraise(EXSHELLPROC); - /*NOTREACHED*/ + *argv = cmd; + *--argv = _PATH_BSHELL; + execve(_PATH_BSHELL, argv, envp); } errno = e; } @@ -537,43 +537,6 @@ clearcmdentry(int firstchange) /* - * Delete all functions. - */ - -#ifdef mkinit -MKINIT void deletefuncs(void); - -SHELLPROC { - deletefuncs(); -} -#endif - -void -deletefuncs(void) -{ - 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; - unreffunc(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 diff --git a/bin/sh/exec.h b/bin/sh/exec.h index 45330a1..45a647e 100644 --- a/bin/sh/exec.h +++ b/bin/sh/exec.h @@ -71,7 +71,6 @@ void find_command(const char *, struct cmdentry *, int, const char *); int find_builtin(const char *, int *); void hashcd(void); void changepath(const char *); -void deletefuncs(void); void addcmdentry(const char *, struct cmdentry *); void defun(const char *, union node *); int unsetfunc(const char *); diff --git a/bin/sh/init.h b/bin/sh/init.h index 1ec8343..dd0c4a8 100644 --- a/bin/sh/init.h +++ b/bin/sh/init.h @@ -35,4 +35,3 @@ void init(void); void reset(void); -void initshellproc(void); diff --git a/bin/sh/input.c b/bin/sh/input.c index 21a9134..e7baed3 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -119,12 +119,7 @@ INIT { RESET { popallfiles(); - if (exception != EXSHELLPROC) - parselleft = parsenleft = 0; /* clear input buffer */ -} - -SHELLPROC { - popallfiles(); + parselleft = parsenleft = 0; /* clear input buffer */ } #endif diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 7ffdc2a..f4f1dac 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -177,22 +177,6 @@ out: out2fmt_flush("sh: can't access tty; job control turned off\n"); #endif -#ifdef mkinit -INCLUDE -INCLUDE - -SHELLPROC { - backgndpid = -1; - bgjob = NULL; -#if JOBS - jobctl = 0; -#endif -} - -#endif - - - #if JOBS int fgcmd(int argc __unused, char **argv) diff --git a/bin/sh/main.c b/bin/sh/main.c index 88483b0..c5de899 100644 --- a/bin/sh/main.c +++ b/bin/sh/main.c @@ -98,19 +98,7 @@ main(int argc, char *argv[]) (void) setlocale(LC_ALL, ""); state = 0; if (setjmp(main_handler.loc)) { - /* - * When a shell procedure is executed, we raise the - * exception EXSHELLPROC to clean up before executing - * the shell procedure. - */ switch (exception) { - case EXSHELLPROC: - rootpid = getpid(); - rootshell = 1; - minusc = NULL; - state = 3; - break; - case EXEXEC: exitstatus = exerrno; break; @@ -123,10 +111,8 @@ main(int argc, char *argv[]) break; } - if (exception != EXSHELLPROC) { - if (state == 0 || iflag == 0 || ! rootshell) - exitshell(exitstatus); - } + if (state == 0 || iflag == 0 || ! rootshell) + exitshell(exitstatus); reset(); if (exception == EXINT) out2fmt_flush("\n"); diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c index 89385ff..82f2a55 100644 --- a/bin/sh/mkinit.c +++ b/bin/sh/mkinit.c @@ -126,16 +126,10 @@ char reset[] = "\ * interactive shell and control is returned to the main command loop.\n\ */\n"; -char shellproc[] = "\ -/*\n\ - * This routine is called to initialize the shell to run a shell procedure.\n\ - */\n"; - struct event event[] = { { "INIT", "init", init, { NULL, 0, NULL, NULL } }, { "RESET", "reset", reset, { NULL, 0, NULL, NULL } }, - { "SHELLPROC", "initshellproc", shellproc, { NULL, 0, NULL, NULL } }, { NULL, NULL, NULL, { NULL, 0, NULL, NULL } } }; diff --git a/bin/sh/options.c b/bin/sh/options.c index 389e555..de1f3ff 100644 --- a/bin/sh/options.c +++ b/bin/sh/options.c @@ -304,21 +304,6 @@ setoption(int flag, int val) } - -#ifdef mkinit -INCLUDE "options.h" - -SHELLPROC { - int i; - - for (i = 0; i < NOPTS; i++) - optlist[i].val = 0; - optschanged(); - -} -#endif - - /* * Set the shell parameters. */ diff --git a/bin/sh/redir.c b/bin/sh/redir.c index 6e6f7a5..915b2fc 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -324,10 +324,6 @@ RESET { popredir(); } -SHELLPROC { - clearredir(); -} - #endif /* Return true if fd 0 has already been redirected at least once. */ diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 32b76c8..2ecdcf0 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -32,7 +32,7 @@ .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" $FreeBSD$ .\" -.Dd January 16, 2011 +.Dd February 4, 2011 .Dt SH 1 .Os .Sh NAME @@ -647,15 +647,9 @@ resulting in an .Er ENOEXEC return value from .Xr execve 2 ) -the shell will interpret the program in a subshell. -The child shell will reinitialize itself in this case, -so that the effect will be -as if a new shell had been invoked to handle the ad-hoc shell script, -except that the location of hashed commands located in -the parent shell will be remembered by the child -(see the description of the -.Ic hash -built-in command below). +the shell will run a new instance of +.Nm +to interpret it. .Pp Note that previous versions of this document and the source code itself misleadingly and sporadically diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 3ddd5a9..aaa4753 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -367,22 +367,6 @@ ignoresig(int signo) } -#ifdef mkinit -INCLUDE -INCLUDE "trap.h" - -SHELLPROC { - char *sm; - - clear_traps(); - for (sm = sigmode ; sm < sigmode + NSIG ; sm++) { - if (*sm == S_IGN) - *sm = S_HARD_IGN; - } -} -#endif - - /* * Signal handler. */ diff --git a/bin/sh/var.c b/bin/sh/var.c index 44d2028..e14027f 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -161,7 +161,7 @@ INIT { /* * This routine initializes the builtin variables. It is called when the - * shell is initialized and again when a shell procedure is spawned. + * shell is initialized. */ void @@ -542,47 +542,6 @@ environment(void) } -/* - * Called when a shell procedure is invoked to clear out nonexported - * variables. It is also necessary to reallocate variables of with - * VSTACK set since these are currently allocated on the stack. - */ - -MKINIT void shprocvar(void); - -#ifdef mkinit -SHELLPROC { - shprocvar(); -} -#endif - -void -shprocvar(void) -{ - struct var **vpp; - struct var *vp, **prev; - - for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) { - for (prev = vpp ; (vp = *prev) != NULL ; ) { - if ((vp->flags & VEXPORT) == 0) { - *prev = vp->next; - if ((vp->flags & VTEXTFIXED) == 0) - ckfree(vp->text); - if ((vp->flags & VSTRFIXED) == 0) - ckfree(vp); - } else { - if (vp->flags & VSTACK) { - vp->text = savestr(vp->text); - vp->flags &=~ VSTACK; - } - prev = &vp->next; - } - } - } - initvar(); -} - - static int var_compare(const void *a, const void *b) { -- cgit v1.1