diff options
| author | Tim J. Robbins <tjr@FreeBSD.org> | 2002-08-27 01:36:28 +0000 |
|---|---|---|
| committer | Tim J. Robbins <tjr@FreeBSD.org> | 2002-08-27 01:36:28 +0000 |
| commit | 2d11746790dad46da5776c17f1b05ee7e3336b4a (patch) | |
| tree | 4a58bd180bc718df2761fb6af915b905204e75b5 /bin/sh | |
| parent | 400e4f66e2ebefc35f98022a5039148615071b82 (diff) | |
Notes
Diffstat (limited to 'bin/sh')
| -rw-r--r-- | bin/sh/builtins.def | 4 | ||||
| -rw-r--r-- | bin/sh/cd.c | 72 | ||||
| -rw-r--r-- | bin/sh/error.c | 7 | ||||
| -rw-r--r-- | bin/sh/error.h | 2 | ||||
| -rw-r--r-- | bin/sh/eval.c | 57 | ||||
| -rw-r--r-- | bin/sh/eval.h | 1 | ||||
| -rw-r--r-- | bin/sh/exec.c | 105 | ||||
| -rw-r--r-- | bin/sh/histedit.c | 20 | ||||
| -rw-r--r-- | bin/sh/input.c | 7 | ||||
| -rw-r--r-- | bin/sh/jobs.c | 122 | ||||
| -rw-r--r-- | bin/sh/jobs.h | 4 | ||||
| -rw-r--r-- | bin/sh/myhistedit.h | 1 | ||||
| -rw-r--r-- | bin/sh/options.h | 4 | ||||
| -rw-r--r-- | bin/sh/redir.c | 2 | ||||
| -rw-r--r-- | bin/sh/sh.1 | 68 | ||||
| -rw-r--r-- | bin/sh/shell.h | 6 | ||||
| -rw-r--r-- | bin/sh/trap.c | 21 | ||||
| -rw-r--r-- | bin/sh/trap.h | 1 | ||||
| -rw-r--r-- | bin/sh/var.c | 1 |
19 files changed, 190 insertions, 315 deletions
diff --git a/bin/sh/builtins.def b/bin/sh/builtins.def index bd4c1dfb0630..2c744315108b 100644 --- a/bin/sh/builtins.def +++ b/bin/sh/builtins.def @@ -49,7 +49,8 @@ # # NOTE: bltincmd must come first! -bltincmd command +bltincmd builtin +commandcmd command #alloccmd alloc bgcmd -j bg breakcmd break continue @@ -91,3 +92,4 @@ waitcmd wait aliascmd alias ulimitcmd ulimit testcmd test [ +bindcmd bind diff --git a/bin/sh/cd.c b/bin/sh/cd.c index 9121dc4215ca..aa1fd5ab5a1b 100644 --- a/bin/sh/cd.c +++ b/bin/sh/cd.c @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <string.h> #include <unistd.h> #include <errno.h> +#include <limits.h> /* * The cd and pwd commands. @@ -86,8 +87,8 @@ cdcmd(int argc, char **argv) struct stat statb; int ch, phys, print = 0; - optreset = 1; optind = 1; /* initialize getopt */ - phys = 0; + optreset = 1; optind = 1; opterr = 0; /* initialize getopt */ + phys = Pflag; while ((ch = getopt(argc, argv, "LP")) != -1) { switch (ch) { case 'L': @@ -316,16 +317,14 @@ updatepwd(char *dir) return (0); } -#define MAXPWD 256 - int -pwdcmd(int argc __unused, char **argv __unused) +pwdcmd(int argc, char **argv) { - char buf[MAXPWD]; + char buf[PATH_MAX]; int ch, phys; - optreset = 1; optind = 1; /* initialize getopt */ - phys = 0; + optreset = 1; optind = 1; opterr = 0; /* initialize getopt */ + phys = Pflag; while ((ch = getopt(argc, argv, "LP")) != -1) { switch (ch) { case 'L': @@ -365,24 +364,10 @@ pwdcmd(int argc __unused, char **argv __unused) char * getpwd(void) { - char buf[MAXPWD]; + char buf[PATH_MAX]; if (curdir) return curdir; - /* - * Things are a bit complicated here; we could have just used - * getcwd, but traditionally getcwd is implemented using popen - * to /bin/pwd. This creates a problem for us, since we cannot - * keep track of the job if it is being ran behind our backs. - * So we re-implement getcwd(), and we suppress interrupts - * throughout the process. This is not completely safe, since - * the user can still break out of it by killing the pwd program. - * We still try to use getcwd for systems that we know have a - * c implementation of getcwd, that does not open a pipe to - * /bin/pwd. - */ -#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__SVR4) - if (getcwd(buf, sizeof(buf)) == NULL) { char *pwd = getenv("PWD"); struct stat stdot, stpwd; @@ -397,47 +382,6 @@ getpwd(void) return NULL; } curdir = savestr(buf); -#else - { - char *p; - int i; - int status; - struct job *jp; - int pip[2]; - INTOFF; - if (pipe(pip) < 0) - error("Pipe call failed: %s", strerror(errno)); - jp = makejob((union node *)NULL, 1); - if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) { - (void) close(pip[0]); - if (pip[1] != 1) { - close(1); - copyfd(pip[1], 1); - close(pip[1]); - } - (void) execl("/bin/pwd", "pwd", (char *)0); - error("Cannot exec /bin/pwd"); - } - (void) close(pip[1]); - pip[1] = -1; - p = buf; - while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0 - || (i == -1 && errno == EINTR)) { - if (i > 0) - p += i; - } - (void) close(pip[0]); - pip[0] = -1; - status = waitforjob(jp); - if (status != 0) - error((char *)0); - if (i < 0 || p == buf || p[-1] != '\n') - error("pwd command failed"); - p[-1] = '\0'; - } - curdir = savestr(buf); - INTON; -#endif return curdir; } diff --git a/bin/sh/error.c b/bin/sh/error.c index 77ade563b0c0..8c2c964a897e 100644 --- a/bin/sh/error.c +++ b/bin/sh/error.c @@ -211,7 +211,7 @@ STATIC const struct errname errormsg[] = { { EMFILE, ALL, "too many open files" }, #endif { ENFILE, ALL, "file table overflow" }, - { ENOSPC, ALL, "filesystem full" }, + { ENOSPC, ALL, "file system full" }, #ifdef EDQUOT { EDQUOT, ALL, "disk quota exceeded" }, #endif @@ -219,11 +219,8 @@ STATIC const struct errname errormsg[] = { { ENOSR, ALL, "no streams resources" }, #endif { ENXIO, ALL, "no such device or address" }, - { EROFS, ALL, "read-only filesystem" }, + { EROFS, ALL, "read-only file system" }, { ETXTBSY, ALL, "text busy" }, -#ifdef SYSV - { EAGAIN, E_EXEC, "not enough memory" }, -#endif { ENOMEM, ALL, "not enough memory" }, #ifdef ENOLINK { ENOLINK, ALL, "remote access failed" }, diff --git a/bin/sh/error.h b/bin/sh/error.h index d4ff7bcb7796..92ca8f8cce30 100644 --- a/bin/sh/error.h +++ b/bin/sh/error.h @@ -101,7 +101,5 @@ char *errmsg(int, int); * so we use _setjmp instead. */ -#ifdef BSD #define setjmp(jmploc) _setjmp(jmploc) #define longjmp(jmploc, val) _longjmp(jmploc, val) -#endif diff --git a/bin/sh/eval.c b/bin/sh/eval.c index 5d8f309f32bc..e147e43fc6a1 100644 --- a/bin/sh/eval.c +++ b/bin/sh/eval.c @@ -42,6 +42,7 @@ static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95"; #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <paths.h> #include <signal.h> #include <unistd.h> #include <sys/wait.h> /* For WIFSIGNALED(status) */ @@ -747,7 +748,9 @@ evalcommand(union node *cmd, int flags, struct backcmd *backcmd) && (cmdentry.cmdtype != CMDBUILTIN || cmdentry.u.index == CDCMD || cmdentry.u.index == DOTCMD - || cmdentry.u.index == EVALCMD))) { + || cmdentry.u.index == EVALCMD)) + || (cmdentry.cmdtype == CMDBUILTIN && + cmdentry.u.index == COMMANDCMD)) { jp = makejob(cmd, 1); mode = cmd->ncmd.backgnd; if (flags & EV_BACKCMD) { @@ -869,7 +872,8 @@ cmddone: #ifndef NO_HISTORY || cmdentry.u.index == HISTCMD #endif - || cmdentry.u.index == EXECCMD) + || cmdentry.u.index == EXECCMD + || cmdentry.u.index == COMMANDCMD) exraise(e); FORCEINTON; } @@ -986,6 +990,55 @@ breakcmd(int argc, char **argv) return 0; } +/* + * The `command' command. + */ +int +commandcmd(int argc, char **argv) +{ + static char stdpath[] = _PATH_STDPATH; + struct jmploc loc, *old; + struct strlist *sp; + char *path; + int ch; + + for (sp = cmdenviron; sp ; sp = sp->next) + setvareq(sp->text, VEXPORT|VSTACK); + path = pathval(); + + optind = optreset = 1; + opterr = 0; + while ((ch = getopt(argc, argv, "p")) != -1) { + switch (ch) { + case 'p': + path = stdpath; + break; + case '?': + default: + error("unknown option: -%c", optopt); + } + } + argc -= optind; + argv += optind; + + if (argc != 0) { + old = handler; + handler = &loc; + if (setjmp(handler->loc) == 0) + shellexec(argv, environment(), path, 0); + handler = old; + if (exception == EXEXEC) + exit(exerrno); + exraise(exception); + } + + /* + * Do nothing successfully if no command was specified; + * ksh also does this. + */ + exit(0); +} + /* * The return command. diff --git a/bin/sh/eval.h b/bin/sh/eval.h index 77dbbab77c1b..ff30c0c1695a 100644 --- a/bin/sh/eval.h +++ b/bin/sh/eval.h @@ -60,6 +60,7 @@ int returncmd(int, char **); int falsecmd(int, char **); int truecmd(int, char **); int execcmd(int, char **); +int commandcmd(int, char **); /* in_function returns nonzero if we are currently evaluating a function */ #define in_function() funcnest diff --git a/bin/sh/exec.c b/bin/sh/exec.c index cd6c7005b0cb..819089a9aeb0 100644 --- a/bin/sh/exec.c +++ b/bin/sh/exec.c @@ -100,9 +100,6 @@ int exerrno = 0; /* Last exec error */ STATIC void tryexec(char *, char **, char **); -#ifndef BSD -STATIC void execinterp(char **, char **); -#endif STATIC void printentry(struct tblentry *, int); STATIC struct tblentry *cmdlookup(char *, int); STATIC void delete_cmd_entry(void); @@ -155,30 +152,13 @@ STATIC void tryexec(char *cmd, char **argv, char **envp) { int e; -#ifndef BSD - char *p; -#endif -#ifdef SYSV - do { - execve(cmd, argv, envp); - } while (errno == EINTR); -#else execve(cmd, argv, envp); -#endif e = errno; if (e == ENOEXEC) { initshellproc(); setinputfile(cmd, 0); commandname = arg0 = savestr(argv[0]); -#ifndef BSD - pgetc(); pungetc(); /* fill up input buffer */ - p = parsenextc; - if (parsenleft > 2 && p[0] == '#' && p[1] == '!') { - argv[0] = cmd; - execinterp(argv, envp); - } -#endif setparam(argv + 1); exraise(EXSHELLPROC); /*NOTREACHED*/ @@ -186,85 +166,6 @@ tryexec(char *cmd, char **argv, char **envp) errno = e; } - -#ifndef BSD -/* - * Execute an interpreter introduced by "#!", for systems where this - * feature has not been built into the kernel. If the interpreter is - * the shell, return (effectively ignoring the "#!"). If the execution - * of the interpreter fails, exit. - * - * This code peeks inside the input buffer in order to avoid actually - * reading any input. It would benefit from a rewrite. - */ - -#define NEWARGS 5 - -STATIC void -execinterp(char **argv, char **envp) -{ - int n; - char *inp; - char *outp; - char c; - char *p; - char **ap; - char *newargs[NEWARGS]; - int i; - char **ap2; - char **new; - - n = parsenleft - 2; - inp = parsenextc + 2; - ap = newargs; - for (;;) { - while (--n >= 0 && (*inp == ' ' || *inp == '\t')) - inp++; - if (n < 0) - goto bad; - if ((c = *inp++) == '\n') - break; - if (ap == &newargs[NEWARGS]) -bad: error("Bad #! line"); - STARTSTACKSTR(outp); - do { - STPUTC(c, outp); - } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n'); - STPUTC('\0', outp); - n++, inp--; - *ap++ = grabstackstr(outp); - } - if (ap == newargs + 1) { /* if no args, maybe no exec is needed */ - p = newargs[0]; - for (;;) { - if (equal(p, "sh") || equal(p, "ash")) { - return; - } - while (*p != '/') { - if (*p == '\0') - goto break2; - p++; - } - p++; - } -break2:; - } - i = (char *)ap - (char *)newargs; /* size in bytes */ - if (i == 0) - error("Bad #! line"); - for (ap2 = argv ; *ap2++ != NULL ; ); - new = ckmalloc(i + ((char *)ap2 - (char *)argv)); - ap = newargs, ap2 = new; - while ((i -= sizeof (char **)) >= 0) - *ap2++ = *ap++; - ap = argv; - while (*ap2++ = *ap++); - shellexec(new, envp, pathval(), 0); -} -#endif - - - /* * Do a path search. The variable path (passed by reference) should be * set to the start of the path before the first call; padvance will update @@ -478,11 +379,7 @@ loop: TRACE(("searchexec \"%s\": no change\n", name)); goto success; } - while (stat(fullname, &statb) < 0) { -#ifdef SYSV - if (errno == EINTR) - continue; -#endif + if (stat(fullname, &statb) < 0) { if (errno != ENOENT && errno != ENOTDIR) e = errno; goto loop; diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c index 5c673fd4928a..463925d5208d 100644 --- a/bin/sh/histedit.c +++ b/bin/sh/histedit.c @@ -130,6 +130,7 @@ bad: el_set(el, EL_EDITOR, "vi"); else if (Eflag) el_set(el, EL_EDITOR, "emacs"); + el_source(el, NULL); } } else { INTOFF; @@ -204,6 +205,7 @@ histcmd(int argc, char **argv) error("missing history argument"); optreset = 1; optind = 1; /* initialize getopt */ + opterr = 0; while (not_fcnumber(argv[optind]) && (ch = getopt(argc, argv, ":e:lnrs")) != -1) switch ((char)ch) { @@ -469,6 +471,16 @@ str_to_event(char *str, int last) } return (he->num); } + +int +bindcmd(int argc, char **argv) +{ + + if (el == NULL) + error("line editing is disabled"); + return (el_parse(el, argc, argv)); +} + #else #include "error.h" @@ -480,4 +492,12 @@ histcmd(int argc, char **argv) /*NOTREACHED*/ return (0); } + +int +bindcmd(int argc, char **argv) +{ + + error("not compiled with line editing support"); + return (0); +} #endif diff --git a/bin/sh/input.c b/bin/sh/input.c index aa367da7ef3f..cb299207a6e2 100644 --- a/bin/sh/input.c +++ b/bin/sh/input.c @@ -64,6 +64,7 @@ __FBSDID("$FreeBSD$"); #include "alias.h" #include "parser.h" #include "myhistedit.h" +#include "trap.h" #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ @@ -178,6 +179,12 @@ preadfd(void) int nr; parsenextc = parsefile->buf; +#ifndef NO_HISTORY + if (el != NULL && gotwinch) { + gotwinch = 0; + el_resize(el); + } +#endif retry: #ifndef NO_HISTORY if (parsefile->fd == 0 && el) { diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c index 0a76e9bde426..a4a8bdf57cf7 100644 --- a/bin/sh/jobs.c +++ b/bin/sh/jobs.c @@ -49,12 +49,10 @@ __FBSDID("$FreeBSD$"); #include <unistd.h> #include <stdlib.h> #include <sys/param.h> -#ifdef BSD #include <sys/wait.h> #include <sys/time.h> #include <sys/resource.h> #include <paths.h> -#endif #include <sys/ioctl.h> #include "shell.h" @@ -83,7 +81,7 @@ int njobs; /* size of array */ MKINIT pid_t backgndpid = -1; /* pid of last background process */ #if JOBS struct job *jobmru; /* most recently used job list */ -int initialpgrp; /* pgrp of shell on invocation */ +pid_t initialpgrp; /* pgrp of shell on invocation */ #endif int in_waitcmd = 0; /* are we in waitcmd()? */ int in_dowait = 0; /* are we in dowait()? */ @@ -95,11 +93,8 @@ STATIC void restartjob(struct job *); #endif STATIC void freejob(struct job *); STATIC struct job *getjob(char *); -STATIC int dowait(int, struct job *); -#if SYSV -STATIC int onsigchild(void); -#endif -STATIC int waitproc(int, int *); +STATIC pid_t dowait(int, struct job *); +STATIC pid_t waitproc(int, int *); STATIC void cmdtxt(union node *); STATIC void cmdputs(char *); #if JOBS @@ -112,10 +107,6 @@ STATIC void showjob(struct job *, pid_t, int, int); /* * Turn job control on and off. - * - * Note: This code assumes that the third arg to ioctl is a character - * pointer, which is true on Berkeley systems but not System V. Since - * System V doesn't have job control yet, this isn't a problem now. */ MKINIT int jobctl; @@ -196,7 +187,7 @@ int fgcmd(int argc __unused, char **argv) { struct job *jp; - int pgrp; + pid_t pgrp; int status; jp = getjob(argv[1]); @@ -268,6 +259,7 @@ jobscmd(int argc, char *argv[]) int ch, sformat, lformat; optind = optreset = 1; + opterr = 0; sformat = lformat = 0; while ((ch = getopt(argc, argv, "ls")) != -1) { switch (ch) { @@ -315,7 +307,7 @@ showjob(struct job *jp, pid_t pid, int sformat, int lformat) #endif for (ps = jp->ps ; ; ps++) { /* for each process */ if (sformat) { - out1fmt("%d\n", ps->pid); + out1fmt("%d\n", (int)ps->pid); goto skip; } if (!lformat && ps != jp->ps && pid == 0) @@ -335,7 +327,7 @@ showjob(struct job *jp, pid_t pid, int sformat, int lformat) out1str(s); col = strlen(s); if (lformat) { - fmtstr(s, 64, "%d ", ps->pid); + fmtstr(s, 64, "%d ", (int)ps->pid); out1str(s); col += strlen(s); } @@ -500,7 +492,7 @@ jobidcmd(int argc __unused, char **argv) jp = getjob(argv[1]); for (i = 0 ; i < jp->nprocs ; ) { - out1fmt("%d", jp->ps[i].pid); + out1fmt("%d", (int)jp->ps[i].pid); out1c(++i < jp->nprocs? ' ' : '\n'); } return 0; @@ -517,7 +509,7 @@ getjob(char *name) { int jobno; struct job *found, *jp; - int pid; + pid_t pid; int i; if (name == NULL) { @@ -571,7 +563,7 @@ currentjob: if ((jp = getcurjob(NULL)) == NULL) return found; } } else if (is_number(name)) { - pid = number(name); + pid = (pid_t)number(name); for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { if (jp->used && jp->nprocs > 0 && jp->ps[jp->nprocs - 1].pid == pid) @@ -726,11 +718,11 @@ getcurjob(struct job *nj) * in a pipeline). */ -int +pid_t forkshell(struct job *jp, union node *n, int mode) { - int pid; - int pgrp; + pid_t pid; + pid_t pgrp; TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n, mode)); @@ -746,12 +738,9 @@ forkshell(struct job *jp, union node *n, int mode) int wasroot; int i; - TRACE(("Child shell %d\n", getpid())); + TRACE(("Child shell %d\n", (int)getpid())); wasroot = rootshell; rootshell = 0; - for (i = njobs, p = jobtab ; --i >= 0 ; p++) - if (p->used) - freejob(p); closescript(); INTON; clear_traps(); @@ -793,6 +782,11 @@ forkshell(struct job *jp, union node *n, int mode) } } #endif + INTOFF; + for (i = njobs, p = jobtab ; --i >= 0 ; p++) + if (p->used) + freejob(p); + INTON; if (wasroot && iflag) { setsignal(SIGINT); setsignal(SIGQUIT); @@ -822,7 +816,7 @@ forkshell(struct job *jp, union node *n, int mode) #endif } INTON; - TRACE(("In parent shell: child = %d\n", pid)); + TRACE(("In parent shell: child = %d\n", (int)pid)); return pid; } @@ -851,7 +845,7 @@ int waitforjob(struct job *jp, int *origstatus) { #if JOBS - int mypgrp = getpgrp(); + pid_t mypgrp = getpgrp(); #endif int status; int st; @@ -899,10 +893,10 @@ waitforjob(struct job *jp, int *origstatus) * Wait for a process to terminate. */ -STATIC int +STATIC pid_t dowait(int block, struct job *job) { - int pid; + pid_t pid; int status; struct procstat *sp; struct job *jp; @@ -916,7 +910,7 @@ dowait(int block, struct job *job) TRACE(("dowait(%d) called\n", block)); do { pid = waitproc(block, &status); - TRACE(("wait returns %d, status=%d\n", pid, status)); + TRACE(("wait returns %d, status=%d\n", (int)pid, status)); } while ((pid == -1 && errno == EINTR && breakwaitcmd == 0) || (WIFSTOPPED(status) && !iflag)); in_dowait--; @@ -937,7 +931,8 @@ dowait(int block, struct job *job) continue; if (sp->pid == pid) { TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", - pid, sp->status, status)); + (int)pid, sp->status, + status)); sp->status = status; thisjob = jp; } @@ -973,13 +968,8 @@ dowait(int block, struct job *job) sig = WTERMSIG(status); } if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { - if (jp->foreground) { -#if JOBS - if (WIFSTOPPED(status)) - i = WSTOPSIG(status); - else -#endif - i = WTERMSIG(status); + if (thisjob->foreground && !WIFSTOPPED(status)) { + i = WTERMSIG(status); if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) out1str(sys_siglist[i & 0x7F]); else @@ -988,7 +978,7 @@ dowait(int block, struct job *job) out1str(" (core dumped)"); out1c('\n'); } else - showjob(thisjob, pid, 0, 1); + showjob(thisjob, pid, 0, 0); } } else { TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job)); @@ -1004,44 +994,10 @@ dowait(int block, struct job *job) * Do a wait system call. If job control is compiled in, we accept * stopped processes. If block is zero, we return a value of zero * rather than blocking. - * - * System V doesn't have a non-blocking wait system call. It does - * have a SIGCLD signal that is sent to a process when one of it's - * children dies. The obvious way to use SIGCLD would be to install - * a handler for SIGCLD which simply bumped a counter when a SIGCLD - * was received, and have waitproc bump another counter when it got - * the status of a process. Waitproc would then know that a wait - * system call would not block if the two counters were different. - * This approach doesn't work because if a process has children that - * have not been waited for, System V will send it a SIGCLD when it - * installs a signal handler for SIGCLD. What this means is that when - * a child exits, the shell will be sent SIGCLD signals continuously - * until is runs out of stack space, unless it does a wait call before - * restoring the signal handler. The code below takes advantage of - * this (mis)feature by installing a signal handler for SIGCLD and - * then checking to see whether it was called. If there are any - * children to be waited for, it will be. - * - * If neither SYSV nor BSD is defined, we don't implement nonblocking - * waits at all. In this case, the user will not be informed when - * a background process until the next time she runs a real program - * (as opposed to running a builtin command or just typing return), - * and the jobs command may give out of date information. */ - -#ifdef SYSV -STATIC sig_atomic_t gotsigchild; - -STATIC int onsigchild() { - gotsigchild = 1; -} -#endif - - -STATIC int +STATIC pid_t waitproc(int block, int *status) { -#ifdef BSD int flags; #if JOBS @@ -1052,24 +1008,6 @@ waitproc(int block, int *status) if (block == 0) flags |= WNOHANG; return wait3(status, flags, (struct rusage *)NULL); -#else -#ifdef SYSV - int (*save)(); - - if (block == 0) { - gotsigchild = 0; - save = signal(SIGCLD, onsigchild); - signal(SIGCLD, save); - if (gotsigchild == 0) - return 0; - } - return wait(status); -#else - if (block == 0) - return 0; - return wait(status); -#endif -#endif } /* diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h index 5bc32ebc436f..53c0ba05ae0e 100644 --- a/bin/sh/jobs.h +++ b/bin/sh/jobs.h @@ -67,7 +67,7 @@ struct job { struct procstat ps0; /* status of process */ struct procstat *ps; /* status or processes when more than one */ short nprocs; /* number of processes */ - short pgrp; /* process group of this job */ + pid_t pgrp; /* process group of this job */ char state; /* true if job is finished */ char used; /* true if this entry is in used */ char changed; /* true if status has changed */ @@ -92,7 +92,7 @@ void showjobs(int, int, int); int waitcmd(int, char **); int jobidcmd(int, char **); struct job *makejob(union node *, int); -int forkshell(struct job *, union node *, int); +pid_t forkshell(struct job *, union node *, int); int waitforjob(struct job *, int *); int stoppedjobs(void); char *commandtext(union node *); diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h index 77817c70c00a..644b2c025302 100644 --- a/bin/sh/myhistedit.h +++ b/bin/sh/myhistedit.h @@ -45,4 +45,5 @@ void sethistsize(const char *); int histcmd(int, char **); int not_fcnumber(char *); int str_to_event(char *, int); +int bindcmd(int, char **); diff --git a/bin/sh/options.h b/bin/sh/options.h index 016a9369c716..5aec64e245d9 100644 --- a/bin/sh/options.h +++ b/bin/sh/options.h @@ -65,8 +65,9 @@ struct shparam { #define uflag optlist[14].val #define privileged optlist[15].val #define Tflag optlist[16].val +#define Pflag optlist[17].val -#define NOPTS 17 +#define NOPTS 18 struct optent { const char *name; @@ -93,6 +94,7 @@ struct optent optlist[NOPTS] = { { "nounset", 'u', 0 }, { "privileged", 'p', 0 }, { "trapsasync", 'T', 0 }, + { "physical", 'P', 0 }, }; #else extern struct optent optlist[NOPTS]; diff --git a/bin/sh/redir.c b/bin/sh/redir.c index d1d46eb00ac2..ed48f9fe260c 100644 --- a/bin/sh/redir.c +++ b/bin/sh/redir.c @@ -73,7 +73,7 @@ __FBSDID("$FreeBSD$"); MKINIT struct redirtab { struct redirtab *next; - short renamed[10]; + int renamed[10]; }; diff --git a/bin/sh/sh.1 b/bin/sh/sh.1 index 311c7de308b5..49ef656b0253 100644 --- a/bin/sh/sh.1 +++ b/bin/sh/sh.1 @@ -43,7 +43,7 @@ .Nd command interpreter (shell) .Sh SYNOPSIS .Nm -.Op Fl /+abCEefIimnpsTuVvx +.Op Fl /+abCEefIimnPpsTuVvx .Op Fl /+o Ar longname .Op Fl c Ar string .Op Ar arg ... @@ -225,6 +225,17 @@ Turn on job control (set automatically when interactive). If not interactive, read commands but do not execute them. This is useful for checking the syntax of shell scripts. +.It Fl P Li physical +Change the default for the +.Ic cd +and +.Ic pwd +commands from +.Fl L +(logical directory layout) +to +.Fl P +(physical directory layout). .It Fl p Li privileged Turn on privileged mode. This mode is enabled on startup if either the effective user or group id is not equal to the @@ -1271,16 +1282,20 @@ built-in command prints the names and values of all defined aliases (see .Ic unalias ) . Alias values are written with appropriate quoting so that they are -suitable for reinput to the shell. +suitable for re-input to the shell. .It Ic bg Op Ar job ... Continue the specified jobs (or the current job if no jobs are given) in the background. -.It Ic command Ar cmd Op Ar arg ... +.It Ic builtin Ar cmd Op Ar arg ... Execute the specified built-in command, .Ar cmd . This is useful when the user wishes to override a shell function with the same name as a built-in command. +.It Ic bind Oo Fl aeklrsv Oc Oo Ar key Oo Ar command Oc Oc +List or alter key bindings for the line editor. +This command is documented in +.Xr editrc 5 . .It Ic cd Oo Fl LP Oc Op Ar directory Switch to the specified .Ar directory , @@ -1292,7 +1307,7 @@ is specified. If .Ar directory does not begin with -.Pa / , . , +.Pa / , \&. , or .Pa .. , then the directories listed in the @@ -1334,11 +1349,20 @@ This is the default. A synonym for the .Ic cd built-in command. -.It Xo -.Ic echo -.Op Fl e | Fl n -.Op Ar string -.Xc +.It Ic command Oo Fl p Oc Op Ar utility Op Ar argument ... +Execute the specified +.Ar utility +as a simple command (see the +.Sx Simple Commands +section). +.Pp +If the +.Fl p +option is specified, the command search is performed using a +default value of +.Ev PATH +that is guaranteed to find all of the standard utilities. +.It Ic echo Oo Fl e | n Oc Op Ar string Print .Ar string to the standard output with a newline appended. @@ -1420,11 +1444,7 @@ If is given it is used as the exit status of the shell; otherwise the exit status of the preceding command is used. -.It Xo -.Ic export -.Op Fl p -.Op Ar name ... -.Xc +.It Ic export Oo Fl p Oc Op Ar name ... The specified names are exported so that they will appear in the environment of subsequent commands. The only way to un-export a variable is to @@ -1595,11 +1615,7 @@ Print the process id's of the processes in the specified If the .Ar job argument is omitted, use the current job. -.It Xo -.Ic jobs -.Op Fl ls -.Op Ar job ... -.Xc +.It Ic jobs Oo Fl ls Oc Op Ar job ... Print information about the specified jobs, or all jobs if no .Ar job argument is given. @@ -1610,7 +1626,7 @@ If the option is specified, the PID of each job is also printed. If the .Fl s -option is specified, only the PID's of the jobs are printed, one per line. +option is specified, only the PIDs of the jobs are printed, one per line. .It Ic pwd Op Fl LP Print the path of the current directory. The built-in command may differ from the program of the same name because the @@ -1685,11 +1701,7 @@ is assumed. The .Fl e option exists only for backward compatibility with older scripts. -.It Xo -.Ic readonly -.Op Fl p -.Op Ar name ... -.Xc +.It Ic readonly Oo Fl p Oc Op Ar name ... Each specified .Ar name is marked as read only, @@ -1876,11 +1888,7 @@ is specified, the shell removes that alias. If .Fl a is specified, all aliases are removed. -.It Xo -.Ic unset -.Op Fl fv -.Ar name ... -.Xc +.It Ic unset Oo Fl fv Oc Ar name ... The specified variables or functions are unset and unexported. If the .Fl v diff --git a/bin/sh/shell.h b/bin/sh/shell.h index 07c0ec512f67..1de36f337ecb 100644 --- a/bin/sh/shell.h +++ b/bin/sh/shell.h @@ -40,9 +40,6 @@ /* * The follow should be set to reflect the type of system you have: * JOBS -> 1 if you have Berkeley job control, 0 otherwise. - * SHORTNAMES -> 1 if your linker cannot handle long names. - * define BSD if you are running 4.2 BSD or later. - * define SYSV if you are running under System V. * define DEBUG=1 to compile in debugging (set global "debug" to turn on) * define DEBUG=2 to compile in and turn on debugging. * @@ -52,9 +49,6 @@ #define JOBS 1 -#ifndef BSD -#define BSD 1 -#endif /* #define DEBUG 1 */ typedef void *pointer; diff --git a/bin/sh/trap.c b/bin/sh/trap.c index 67f30778fd4f..f848ee122b26 100644 --- a/bin/sh/trap.c +++ b/bin/sh/trap.c @@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$"); #include "error.h" #include "trap.h" #include "mystring.h" +#include "myhistedit.h" /* @@ -81,6 +82,7 @@ static char *volatile trap[NSIG]; /* trap handler commands */ static volatile sig_atomic_t gotsig[NSIG]; /* indicates specified signal received */ static int ignore_sigchld; /* Used while handling SIGCHLD traps. */ +volatile sig_atomic_t gotwinch; static int getsigaction(int, sig_t *); @@ -246,6 +248,12 @@ setsignal(int signo) action = S_IGN; break; #endif +#ifndef NO_HISTORY + case SIGWINCH: + if (rootshell && iflag) + action = S_CATCH; + break; +#endif } } @@ -281,10 +289,8 @@ setsignal(int signo) } *t = action; sig = signal(signo, sigact); -#ifdef BSD if (sig != SIG_ERR && action == S_CATCH) siginterrupt(signo, 1); -#endif } @@ -340,9 +346,6 @@ void onsig(int signo) { -#ifndef BSD - signal(signo, onsig); -#endif if (signo == SIGINT && trap[SIGINT] == NULL) { onint(); return; @@ -364,6 +367,11 @@ onsig(int signo) ! trap[signo][0] == '\0' && ! (trap[signo][0] == ':' && trap[signo][1] == '\0')) breakwaitcmd = 1; + +#ifndef NO_HISTORY + if (signo == SIGWINCH) + gotwinch = 1; +#endif } @@ -419,6 +427,9 @@ setinteractive(int on) setsignal(SIGINT); setsignal(SIGQUIT); setsignal(SIGTERM); +#ifndef NO_HISTORY + setsignal(SIGWINCH); +#endif is_interactive = on; } diff --git a/bin/sh/trap.h b/bin/sh/trap.h index d633d7a2c0ba..557840160f1f 100644 --- a/bin/sh/trap.h +++ b/bin/sh/trap.h @@ -39,6 +39,7 @@ extern int pendingsigs; extern int in_dotrap; +extern volatile sig_atomic_t gotwinch; int trapcmd(int, char **); void clear_traps(void); diff --git a/bin/sh/var.c b/bin/sh/var.c index a4241af223a7..b3be70a89ffa 100644 --- a/bin/sh/var.c +++ b/bin/sh/var.c @@ -543,6 +543,7 @@ exportcmd(int argc, char **argv) cmdname = argv[0]; optreset = optind = 1; + opterr = 0; values = 0; while ((ch = getopt(argc, argv, "p")) != -1) { switch (ch) { |
