aboutsummaryrefslogtreecommitdiff
path: root/bin/sh
diff options
context:
space:
mode:
authorTim J. Robbins <tjr@FreeBSD.org>2002-08-27 01:36:28 +0000
committerTim J. Robbins <tjr@FreeBSD.org>2002-08-27 01:36:28 +0000
commit2d11746790dad46da5776c17f1b05ee7e3336b4a (patch)
tree4a58bd180bc718df2761fb6af915b905204e75b5 /bin/sh
parent400e4f66e2ebefc35f98022a5039148615071b82 (diff)
Notes
Diffstat (limited to 'bin/sh')
-rw-r--r--bin/sh/builtins.def4
-rw-r--r--bin/sh/cd.c72
-rw-r--r--bin/sh/error.c7
-rw-r--r--bin/sh/error.h2
-rw-r--r--bin/sh/eval.c57
-rw-r--r--bin/sh/eval.h1
-rw-r--r--bin/sh/exec.c105
-rw-r--r--bin/sh/histedit.c20
-rw-r--r--bin/sh/input.c7
-rw-r--r--bin/sh/jobs.c122
-rw-r--r--bin/sh/jobs.h4
-rw-r--r--bin/sh/myhistedit.h1
-rw-r--r--bin/sh/options.h4
-rw-r--r--bin/sh/redir.c2
-rw-r--r--bin/sh/sh.168
-rw-r--r--bin/sh/shell.h6
-rw-r--r--bin/sh/trap.c21
-rw-r--r--bin/sh/trap.h1
-rw-r--r--bin/sh/var.c1
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) {