summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1996-10-20 00:55:12 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1996-10-20 00:55:12 +0000
commit8414ed88be8de5352141730c176d30301d6700b4 (patch)
tree44a7f767c70131fb1d09f8a151860fee4e22ae5f
parent78d30b21a3fa6e2f7d7fb077246e1e015a2dafdf (diff)
Sync with NetBSD. Adds better POSIX compliance amongst others.
-rw-r--r--bin/sh/Makefile8
-rw-r--r--bin/sh/TOUR4
-rw-r--r--bin/sh/bltin/bltin.h7
-rw-r--r--bin/sh/cd.c14
-rw-r--r--bin/sh/error.c85
-rw-r--r--bin/sh/error.h5
-rw-r--r--bin/sh/eval.c21
-rw-r--r--bin/sh/exec.c24
-rw-r--r--bin/sh/exec.h5
-rw-r--r--bin/sh/expand.c45
-rw-r--r--bin/sh/histedit.c18
-rw-r--r--bin/sh/jobs.c38
-rw-r--r--bin/sh/main.c29
-rw-r--r--bin/sh/mkinit.c22
-rw-r--r--bin/sh/mknodes.c14
-rw-r--r--bin/sh/mksyntax.c11
-rw-r--r--bin/sh/mktokens4
-rw-r--r--bin/sh/myhistedit.h4
-rw-r--r--bin/sh/mystring.c6
-rw-r--r--bin/sh/options.c131
-rw-r--r--bin/sh/options.h3
-rw-r--r--bin/sh/output.c10
-rw-r--r--bin/sh/parser.c13
-rw-r--r--bin/sh/redir.c15
-rw-r--r--bin/sh/sh.1160
-rw-r--r--bin/sh/shell.h3
-rw-r--r--bin/sh/show.c18
-rw-r--r--bin/sh/show.h8
-rw-r--r--bin/sh/var.c93
-rw-r--r--bin/sh/var.h26
30 files changed, 595 insertions, 249 deletions
diff --git a/bin/sh/Makefile b/bin/sh/Makefile
index ecd8dfab913..eb2bf208bd9 100644
--- a/bin/sh/Makefile
+++ b/bin/sh/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.6 1996/10/12 01:12:02 deraadt Exp $
+# $OpenBSD: Makefile,v 1.7 1996/10/20 00:54:41 millert Exp $
# $NetBSD: Makefile,v 1.23 1996/02/18 12:29:18 mycroft Exp $
STATIC= -static
@@ -16,12 +16,12 @@ CFLAGS+=-DSHELL -I. -I${.CURDIR}
.PATH: ${.CURDIR}/bltin ${.CURDIR}/../../usr.bin/printf
CLEANFILES+=\
arith.c arith_lex.c builtins.c builtins.h init.c mkinit mknodes \
- mksyntax nodes.c nodes.h printf.o syntax.c syntax.h token.def \
+ mksyntax nodes.c nodes.h printf.o syntax.c syntax.h token.h \
y.tab.c y.tab.h
-.depend parser.o: token.def
+.depend parser.o: token.h
-token.def: mktokens
+token.h: mktokens
sh ${.CURDIR}/mktokens
builtins.h builtins.c: ${.CURDIR}/mkbuiltins ${.CURDIR}/builtins.def
diff --git a/bin/sh/TOUR b/bin/sh/TOUR
index 27592163509..244128367b5 100644
--- a/bin/sh/TOUR
+++ b/bin/sh/TOUR
@@ -1,4 +1,4 @@
-# $OpenBSD: TOUR,v 1.2 1996/06/23 14:21:05 deraadt Exp $
+# $OpenBSD: TOUR,v 1.3 1996/10/20 00:54:43 millert Exp $
# $NetBSD: TOUR,v 1.7 1995/05/11 21:28:38 christos Exp $
# @(#)TOUR 8.1 (Berkeley) 5/31/93
@@ -30,7 +30,7 @@ programs is:
mknodes nodetypes nodes.h nodes.c
mksignames - signames.h signames.c
mksyntax - syntax.h syntax.c
- mktokens - token.def
+ mktokens - token.h
bltin/mkexpr unary_op binary_op operators.h operators.c
There are undoubtedly too many of these. Mkinit searches all the
diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h
index 9061ea52dc7..bdd0b18e2ed 100644
--- a/bin/sh/bltin/bltin.h
+++ b/bin/sh/bltin/bltin.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: bltin.h,v 1.2 1996/06/23 14:21:40 deraadt Exp $ */
+/* $OpenBSD: bltin.h,v 1.3 1996/10/20 00:55:11 millert Exp $ */
/* $NetBSD: bltin.h,v 1.7 1995/03/21 09:10:46 cgd Exp $ */
/*-
@@ -58,6 +58,11 @@
#define fputs outstr
#define fflush flushout
#define INITARGS(argv)
+#define warnx(a, b, c) { \
+ char buf[64]; \
+ (void)snprintf(buf, sizeof(buf), a, b, c); \
+ error("%s", buf); \
+}
#else
#undef NULL
#include <stdio.h>
diff --git a/bin/sh/cd.c b/bin/sh/cd.c
index 140b32392a8..79f08c82111 100644
--- a/bin/sh/cd.c
+++ b/bin/sh/cd.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cd.c,v 1.7 1996/08/22 00:35:24 deraadt Exp $ */
+/* $OpenBSD: cd.c,v 1.8 1996/10/20 00:54:44 millert Exp $ */
/* $NetBSD: cd.c,v 1.15 1996/03/01 01:58:58 jtc Exp $ */
/*-
@@ -41,13 +41,14 @@
#if 0
static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: cd.c,v 1.7 1996/08/22 00:35:24 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: cd.c,v 1.8 1996/10/20 00:54:44 millert Exp $";
#endif
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
@@ -63,6 +64,7 @@ static char rcsid[] = "$OpenBSD: cd.c,v 1.7 1996/08/22 00:35:24 deraadt Exp $";
#include "output.h"
#include "memalloc.h"
#include "error.h"
+#include "exec.h"
#include "redir.h"
#include "mystring.h"
#include "show.h"
@@ -85,15 +87,18 @@ cdcmd(argc, argv)
char *path;
char *p;
struct stat statb;
- char *padvance();
int print = 0;
nextopt(nullstr);
if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME", 1)) == NULL)
error("HOME not set");
+ if (*dest == '\0')
+ dest = ".";
if (dest[0] == '-' && dest[1] == '\0') {
dest = prevdir ? prevdir : curdir;
print = 1;
+ if (!dest)
+ dest = ".";
}
if (*dest == '/' || (path = bltinlookup("CDPATH", 1)) == NULL)
path = nullstr;
@@ -126,6 +131,7 @@ cdcmd(argc, argv)
STATIC int
docd(dest, print)
char *dest;
+ int print;
{
TRACE(("docd(\"%s\", %d) called\n", dest, print));
@@ -259,7 +265,7 @@ getpwd()
*/
#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__svr4__)
if (getcwd(buf, sizeof(buf)) == NULL)
- error("getcwd() failed");
+ error("getcwd() failed: %s", strerror(errno));
curdir = savestr(buf);
#else
{
diff --git a/bin/sh/error.c b/bin/sh/error.c
index 489f00f0fee..9513437ef38 100644
--- a/bin/sh/error.c
+++ b/bin/sh/error.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: error.c,v 1.2 1996/06/23 14:21:10 deraadt Exp $ */
+/* $OpenBSD: error.c,v 1.3 1996/10/20 00:54:45 millert Exp $ */
/* $NetBSD: error.c,v 1.14 1995/05/11 21:28:51 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: error.c,v 1.2 1996/06/23 14:21:10 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: error.c,v 1.3 1996/10/20 00:54:45 millert Exp $";
#endif
#endif /* not lint */
@@ -71,6 +71,8 @@ volatile int intpending;
char *commandname;
+static void exverror __P((int, char *, va_list));
+
/*
* Called to raise an exception. Since C doesn't include exceptions, we
* just do a longjmp to the exception handler. The type of exception is
@@ -116,20 +118,36 @@ onint() {
}
-
-void
-error2(a, b)
- char *a, *b;
- {
- error("%s: %s", a, b);
-}
-
-
/*
- * Error is called to raise the error exception. If the first argument
+ * Exverror is called to raise the error exception. If the first argument
* is not NULL then error prints an error message using printf style
* formatting. It then raises the error exception.
*/
+static void
+exverror(cond, msg, ap)
+ int cond;
+ char *msg;
+ va_list ap;
+{
+ CLEAR_PENDING_INT;
+ INTOFF;
+
+#ifdef DEBUG
+ if (msg)
+ TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
+ else
+ TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
+#endif
+ if (msg) {
+ if (commandname)
+ outfmt(&errout, "%s: ", commandname);
+ doformat(&errout, msg, ap);
+ out2c('\n');
+ }
+ flushall();
+ exraise(cond);
+}
+
#if __STDC__
void
@@ -144,33 +162,42 @@ error(va_alist)
char *msg;
#endif
va_list ap;
- CLEAR_PENDING_INT;
- INTOFF;
-
#if __STDC__
va_start(ap, msg);
#else
va_start(ap);
msg = va_arg(ap, char *);
#endif
-#ifdef DEBUG
- if (msg)
- TRACE(("error(\"%s\") pid=%d\n", msg, getpid()));
- else
- TRACE(("error(NULL) pid=%d\n", getpid()));
-#endif
- if (msg) {
- if (commandname)
- outfmt(&errout, "%s: ", commandname);
- doformat(&errout, msg, ap);
- out2c('\n');
- }
+ exverror(EXERROR, msg, ap);
va_end(ap);
- flushall();
- exraise(EXERROR);
}
+#if __STDC__
+void
+exerror(int cond, char *msg, ...)
+#else
+void
+exerror(va_alist)
+ va_dcl
+#endif
+{
+#if !__STDC__
+ int cond;
+ char *msg;
+#endif
+ va_list ap;
+#if __STDC__
+ va_start(ap, msg);
+#else
+ va_start(ap);
+ cond = va_arg(ap, int);
+ msg = va_arg(ap, char *);
+#endif
+ exverror(cond, msg, ap);
+ va_end(ap);
+}
+
/*
* Table of error messages.
diff --git a/bin/sh/error.h b/bin/sh/error.h
index 4e7435887e4..44a21a6be86 100644
--- a/bin/sh/error.h
+++ b/bin/sh/error.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: error.h,v 1.2 1996/06/23 14:21:11 deraadt Exp $ */
+/* $OpenBSD: error.h,v 1.3 1996/10/20 00:54:46 millert Exp $ */
/* $NetBSD: error.h,v 1.8 1995/05/11 21:28:53 christos Exp $ */
/*-
@@ -71,6 +71,7 @@ extern int exception;
#define EXINT 0 /* SIGINT received */
#define EXERROR 1 /* a generic error */
#define EXSHELLPROC 2 /* execute a shell procedure */
+#define EXEXEC 3 /* command execution failed */
/*
@@ -92,8 +93,8 @@ extern char *commandname; /* name of command--printed on error */
void exraise __P((int));
void onint __P((void));
-void error2 __P((char *, char *));
void error __P((char *, ...));
+void exerror __P((int, char *, ...));
char *errmsg __P((int, int));
diff --git a/bin/sh/eval.c b/bin/sh/eval.c
index 52bece42a4e..3e92ad479df 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: eval.c,v 1.3 1996/06/18 10:10:06 deraadt Exp $ */
+/* $OpenBSD: eval.c,v 1.4 1996/10/20 00:54:47 millert Exp $ */
/* $NetBSD: eval.c,v 1.29.4.1 1996/06/10 19:36:36 jtc Exp $ */
/*-
@@ -208,8 +208,11 @@ evaltree(n, flags)
break;
case NAND:
evaltree(n->nbinary.ch1, EV_TESTED);
- if (evalskip || exitstatus != 0)
+ if (evalskip || exitstatus != 0) {
+ /* don't bomb out on "set -e; false && true" */
+ flags |= EV_TESTED;
goto out;
+ }
evaltree(n->nbinary.ch2, flags);
break;
case NOR:
@@ -683,7 +686,7 @@ evalcommand(cmd, flags, backcmd)
find_command(argv[0], &cmdentry, 1, path);
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
- exitstatus = 1;
+ exitstatus = 127;
flushout(&errout);
return;
}
@@ -695,7 +698,7 @@ evalcommand(cmd, flags, backcmd)
break;
if ((cmdentry.u.index = find_builtin(*argv)) < 0) {
outfmt(&errout, "%s: not found\n", *argv);
- exitstatus = 1;
+ exitstatus = 127;
flushout(&errout);
return;
}
@@ -736,7 +739,9 @@ evalcommand(cmd, flags, backcmd)
/* This is the child process if a fork occurred. */
/* Execute the command. */
if (cmdentry.cmdtype == CMDFUNCTION) {
+#ifdef DEBUG
trputs("Shell function: "); trargs(argv);
+#endif
redirect(cmd->ncmd.redirect, REDIR_PUSH);
saveparam = shellparam;
shellparam.malloc = 0;
@@ -781,7 +786,9 @@ evalcommand(cmd, flags, backcmd)
if (flags & EV_EXIT)
exitshell(exitstatus);
} else if (cmdentry.cmdtype == CMDBUILTIN) {
+#ifdef DEBUG
trputs("builtin command: "); trargs(argv);
+#endif
mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH;
if (flags == EV_BACKCMD) {
memout.nleft = 0;
@@ -817,7 +824,9 @@ cmddone:
}
handler = savehandler;
if (e != -1) {
- if (e != EXERROR || cmdentry.u.index == BLTINCMD
+ outfmt(out2, "exception %d\n", e);
+ if ((e != EXERROR && e != EXEXEC)
+ || cmdentry.u.index == BLTINCMD
|| cmdentry.u.index == DOTCMD
|| cmdentry.u.index == EVALCMD
#ifndef NO_HISTORY
@@ -835,7 +844,9 @@ cmddone:
memout.buf = NULL;
}
} else {
+#ifdef DEBUG
trputs("normal command: "); trargs(argv);
+#endif
clearredir();
redirect(cmd->ncmd.redirect, 0);
for (sp = varlist.list ; sp ; sp = sp->next)
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index b96a7dd77a8..4ef30e17d48 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec.c,v 1.2 1996/06/23 14:21:12 deraadt Exp $ */
+/* $OpenBSD: exec.c,v 1.3 1996/10/20 00:54:48 millert Exp $ */
/* $NetBSD: exec.c,v 1.17 1995/06/09 01:53:50 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
#else
-static char rcsid[] = "$OpenBSD: exec.c,v 1.2 1996/06/23 14:21:12 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: exec.c,v 1.3 1996/10/20 00:54:48 millert Exp $";
#endif
#endif /* not lint */
@@ -98,6 +98,7 @@ struct tblentry {
STATIC struct tblentry *cmdtable[CMDTABLESIZE];
STATIC int builtinloc = -1; /* index in path of %builtin, or -1 */
+int exerrno = 0; /* Last exec error */
STATIC void tryexec __P((char *, char **, char **));
@@ -137,7 +138,20 @@ shellexec(argv, envp, path, index)
stunalloc(cmdname);
}
}
- error2(argv[0], errmsg(e, E_EXEC));
+
+ /* Map to POSIX errors */
+ switch (e) {
+ case EACCES:
+ exerrno = 126;
+ break;
+ case ENOENT:
+ exerrno = 127;
+ break;
+ default:
+ exerrno = 2;
+ break;
+ }
+ exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
}
@@ -583,9 +597,9 @@ hashcd() {
void
changepath(newval)
- char *newval;
+ const char *newval;
{
- char *old, *new;
+ const char *old, *new;
int index;
int firstchange;
int bltin;
diff --git a/bin/sh/exec.h b/bin/sh/exec.h
index 24e99746f83..6ce65dc558b 100644
--- a/bin/sh/exec.h
+++ b/bin/sh/exec.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: exec.h,v 1.2 1996/06/23 14:21:13 deraadt Exp $ */
+/* $OpenBSD: exec.h,v 1.3 1996/10/20 00:54:48 millert Exp $ */
/* $NetBSD: exec.h,v 1.9 1995/06/09 01:53:53 christos Exp $ */
/*-
@@ -56,6 +56,7 @@ struct cmdentry {
extern char *pathopt; /* set by padvance */
+extern int exerrno; /* last exec error */
void shellexec __P((char **, char **, char *, int));
char *padvance __P((char **, char *));
@@ -63,7 +64,7 @@ int hashcmd __P((int, char **));
void find_command __P((char *, struct cmdentry *, int, char *));
int find_builtin __P((char *));
void hashcd __P((void));
-void changepath __P((char *));
+void changepath __P((const char *));
void deletefuncs __P((void));
void getcmdentry __P((char *, struct cmdentry *));
void addcmdentry __P((char *, struct cmdentry *));
diff --git a/bin/sh/expand.c b/bin/sh/expand.c
index c3a43e3bcfd..b42d4481903 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: expand.c,v 1.3 1996/06/23 14:21:13 deraadt Exp $ */
+/* $OpenBSD: expand.c,v 1.4 1996/10/20 00:54:49 millert Exp $ */
/* $NetBSD: expand.c,v 1.20 1996/02/12 15:11:41 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
#else
-static char rcsid[] = "$OpenBSD: expand.c,v 1.3 1996/06/23 14:21:13 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: expand.c,v 1.4 1996/10/20 00:54:49 millert Exp $";
#endif
#endif /* not lint */
@@ -101,8 +101,8 @@ STATIC char *exptilde __P((char *, int));
STATIC void expbackq __P((union node *, int, int));
STATIC int subevalvar __P((char *, char *, int, int, int, int));
STATIC char *evalvar __P((char *, int));
-STATIC int varisset __P((int));
-STATIC void varvalue __P((int, int, int));
+STATIC int varisset __P((char *));
+STATIC void varvalue __P((char *, int, int));
STATIC void recordregion __P((int, int, int));
STATIC void ifsbreakup __P((char *, struct arglist *));
STATIC void expandmeta __P((struct strlist *, int));
@@ -434,7 +434,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags)
int varflags;
{
char *startp;
- char *loc;
+ char *loc = NULL;
int c = 0;
int saveherefd = herefd;
struct nodelist *saveargbackq = argbackq;
@@ -559,7 +559,7 @@ evalvar(p, flag)
p = strchr(p, '=') + 1;
again: /* jump here after setting a variable with ${var=text} */
if (special) {
- set = varisset(*var);
+ set = varisset(var);
val = NULL;
} else {
val = lookupvar(var);
@@ -575,7 +575,7 @@ again: /* jump here after setting a variable with ${var=text} */
/* insert the value of the variable */
if (special) {
char *exp, *oexpdest = expdest;
- varvalue(*var, varflags & VSQUOTE, flag & EXP_FULL);
+ varvalue(var, varflags & VSQUOTE, flag & EXP_FULL);
if (subtype == VSLENGTH) {
for (exp = oexpdest;exp != expdest; exp++)
varlen++;
@@ -650,8 +650,10 @@ record:
case VSASSIGN:
case VSQUESTION:
if (!set) {
- if (subevalvar(p, var, 0, subtype, startloc, varflags))
+ if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
+ varflags &= ~VSNUL;
goto again;
+ }
break;
}
if (easy)
@@ -690,22 +692,22 @@ record:
STATIC int
varisset(name)
- char name;
+ char *name;
{
char **ap;
- if (name == '!') {
+ if (*name == '!') {
if (backgndpid == -1)
return 0;
- } else if (name == '@' || name == '*') {
+ } else if (*name == '@' || *name == '*') {
if (*shellparam.p == NULL)
return 0;
- } else if ((unsigned)(name -= '1') <= '9' - '1') {
+ } else if (is_digit(*name)) {
+ int num = atoi(name);
ap = shellparam.p;
- do {
+ while (--num > 0)
if (*ap++ == NULL)
return 0;
- } while (--name >= 0);
}
return 1;
}
@@ -718,7 +720,7 @@ varisset(name)
STATIC void
varvalue(name, quoted, allow_split)
- char name;
+ char *name;
int quoted;
int allow_split;
{
@@ -745,7 +747,7 @@ varvalue(name, quoted, allow_split)
} while (0)
- switch (name) {
+ switch (*name) {
case '$':
num = rootpid;
goto numvar;
@@ -786,9 +788,12 @@ allargs:
STRTODEST(p);
break;
default:
- if ((unsigned)(name -= '1') <= '9' - '1') {
- p = shellparam.p[name];
- STRTODEST(p);
+ if (is_digit(*name)) {
+ num = atoi(name);
+ if (num > 0 && num <= shellparam.nparam) {
+ p = shellparam.p[num - 1];
+ STRTODEST(p);
+ }
}
break;
}
@@ -1118,7 +1123,7 @@ msort(list, len)
struct strlist *list;
int len;
{
- struct strlist *p, *q;
+ struct strlist *p, *q = NULL;
struct strlist **lpp;
int half;
int n;
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 19eb17b1a2d..319bd86e33f 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: histedit.c,v 1.5 1996/09/16 16:33:20 millert Exp $ */
+/* $OpenBSD: histedit.c,v 1.6 1996/10/20 00:54:50 millert Exp $ */
/* $NetBSD: histedit.c,v 1.8 1995/05/11 21:29:12 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: histedit.c,v 1.5 1996/09/16 16:33:20 millert Exp $";
+static char rcsid[] = "$OpenBSD: histedit.c,v 1.6 1996/10/20 00:54:50 millert Exp $";
#endif
#endif /* not lint */
@@ -97,7 +97,7 @@ histedit()
INTON;
if (hist != NULL)
- sethistsize();
+ sethistsize(histsizeval());
else
out2str("sh: can't initialize history\n");
}
@@ -150,15 +150,14 @@ bad:
void
-sethistsize()
+sethistsize(hs)
+ const char *hs;
{
- char *cp;
int histsize;
if (hist != NULL) {
- cp = lookupvar("HISTSIZE");
- if (cp == NULL || *cp == '\0' ||
- (histsize = atoi(cp)) < 0)
+ if (hs == NULL || *hs == '\0' ||
+ (histsize = atoi(hs)) < 0)
histsize = 100;
history(hist, H_EVENT, histsize);
}
@@ -231,6 +230,7 @@ histcmd(argc, argv)
break;
case ':':
error("option -%c expects argument", optopt);
+ case '?':
default:
error("unknown option: -%c", optopt);
}
@@ -332,7 +332,7 @@ histcmd(argc, argv)
error("can't create temporary file %s", editfile);
if ((efp = fdopen(fd, "w")) == NULL) {
close(fd);
- error("can't allocate stdio buffer for temp\n");
+ error("can't allocate stdio buffer for temp");
}
}
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 428c99f0750..dbde5232ef1 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: jobs.c,v 1.2 1996/06/23 14:21:17 deraadt Exp $ */
+/* $OpenBSD: jobs.c,v 1.3 1996/10/20 00:54:51 millert Exp $ */
/* $NetBSD: jobs.c,v 1.17 1995/07/04 16:26:45 pk Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: jobs.c,v 1.2 1996/06/23 14:21:17 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: jobs.c,v 1.3 1996/10/20 00:54:51 millert Exp $";
#endif
#endif /* not lint */
@@ -57,10 +57,15 @@ static char rcsid[] = "$OpenBSD: jobs.c,v 1.2 1996/06/23 14:21:17 deraadt Exp $"
#include <sys/time.h>
#include <sys/resource.h>
#endif
+#include <sys/ioctl.h>
#include "shell.h"
#if JOBS
+#if OLD_TTY_DRIVER
#include "sgtty.h"
+#else
+#include <termios.h>
+#endif
#undef CEOF /* syntax.h redefines this */
#endif
#include "redir.h"
@@ -119,7 +124,12 @@ setjobctl(on)
return;
if (on) {
do { /* while we are in the background */
+#ifdef OLD_TTY_DRIVER
if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
+#else
+ initialpgrp = tcgetpgrp(2);
+ if (initialpgrp < 0) {
+#endif
out2str("sh: can't access tty; job control turned off\n");
mflag = 0;
return;
@@ -142,10 +152,18 @@ setjobctl(on)
setsignal(SIGTTOU);
setsignal(SIGTTIN);
setpgid(0, rootpid);
+#ifdef OLD_TTY_DRIVER
ioctl(2, TIOCSPGRP, (char *)&rootpid);
+#else
+ tcsetpgrp(2, rootpid);
+#endif
} else { /* turning job control off */
setpgid(0, initialpgrp);
+#ifdef OLD_TTY_DRIVER
ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
+#else
+ tcsetpgrp(2, initialpgrp);
+#endif
setsignal(SIGTSTP);
setsignal(SIGTTOU);
setsignal(SIGTTIN);
@@ -182,7 +200,11 @@ fgcmd(argc, argv)
if (jp->jobctl == 0)
error("job not created under job control");
pgrp = jp->ps[0].pid;
+#ifdef OLD_TTY_DRIVER
ioctl(2, TIOCSPGRP, (char *)&pgrp);
+#else
+ tcsetpgrp(2, pgrp);
+#endif
restartjob(jp);
INTOFF;
status = waitforjob(jp);
@@ -580,8 +602,13 @@ forkshell(jp, n, mode)
setpgid(0, pgrp);
if (mode == FORK_FG) {
/*** this causes superfluous TIOCSPGRPS ***/
+#ifdef OLD_TTY_DRIVER
if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
- error("TIOCSPGRP failed, errno=%d\n", errno);
+ error("TIOCSPGRP failed, errno=%d", errno);
+#else
+ if (tcsetpgrp(2, pgrp) < 0)
+ error("tcsetpgrp failed, errno=%d", errno);
+#endif
}
setsignal(SIGTSTP);
setsignal(SIGTTOU);
@@ -674,8 +701,13 @@ waitforjob(jp)
}
#if JOBS
if (jp->jobctl) {
+#ifdef OLD_TTY_DRIVER
if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
error("TIOCSPGRP failed, errno=%d\n", errno);
+#else
+ if (tcsetpgrp(2, mypgrp) < 0)
+ error("tcsetpgrp failed, errno=%d\n", errno);
+#endif
}
if (jp->state == JOBSTOPPED)
curjob = jp - jobtab + 1;
diff --git a/bin/sh/main.c b/bin/sh/main.c
index a4c6a67eb73..8580bdb5e17 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: main.c,v 1.4 1996/06/23 14:21:20 deraadt Exp $ */
+/* $OpenBSD: main.c,v 1.5 1996/10/20 00:54:52 millert Exp $ */
/* $NetBSD: main.c,v 1.23 1995/11/19 23:27:42 christos Exp $ */
/*-
@@ -47,7 +47,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)main.c 8.7 (Berkeley) 7/19/95";
#else
-static char rcsid[] = "$OpenBSD: main.c,v 1.4 1996/06/23 14:21:20 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: main.c,v 1.5 1996/10/20 00:54:52 millert Exp $";
#endif
#endif /* not lint */
@@ -122,15 +122,30 @@ main(argc, argv)
* exception EXSHELLPROC to clean up before executing
* the shell procedure.
*/
- if (exception == EXERROR)
- exitstatus = 2;
- if (exception == EXSHELLPROC) {
+ switch (exception) {
+ case EXSHELLPROC:
rootpid = getpid();
rootshell = 1;
minusc = NULL;
state = 3;
- } else if (state == 0 || iflag == 0 || ! rootshell)
- exitshell(2);
+ break;
+
+ case EXEXEC:
+ exitstatus = exerrno;
+ break;
+
+ case EXERROR:
+ exitstatus = 2;
+ break;
+
+ default:
+ break;
+ }
+
+ if (exception != EXSHELLPROC) {
+ if (state == 0 || iflag == 0 || ! rootshell)
+ exitshell(exitstatus);
+ }
reset();
if (exception == EXINT
#if ATTY
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
index 9750b99813c..abb7e21f1e3 100644
--- a/bin/sh/mkinit.c
+++ b/bin/sh/mkinit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mkinit.c,v 1.4 1996/09/15 22:58:09 millert Exp $ */
+/* $OpenBSD: mkinit.c,v 1.5 1996/10/20 00:54:53 millert Exp $ */
/* $NetBSD: mkinit.c,v 1.14 1996/02/18 12:29:21 mycroft Exp $ */
/*-
@@ -47,7 +47,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: mkinit.c,v 1.4 1996/09/15 22:58:09 millert Exp $";
+static char rcsid[] = "$OpenBSD: mkinit.c,v 1.5 1996/10/20 00:54:53 millert Exp $";
#endif
#endif /* not lint */
@@ -218,6 +218,22 @@ readfile(fname)
dodecl(line, fp);
if (line[0] == '#' && gooddefine(line))
addstr(line, &defines);
+ if (line[0] == '#' && gooddefine(line)) {
+ char *cp;
+ char line2[1024];
+ static const char undef[] = "#undef ";
+
+ strcpy(line2, line);
+ memcpy(line2, undef, sizeof(undef) - 1);
+ cp = line2 + sizeof(undef) - 1;
+ while(*cp && (*cp == ' ' || *cp == '\t'))
+ cp++;
+ while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp++ = '\n'; *cp = '\0';
+ addstr(line2, &defines);
+ addstr(line, &defines);
+ }
}
fclose(fp);
}
@@ -351,7 +367,7 @@ dodecl(line1, fp)
if (! amiddecls)
addchar('\n', &decls);
q = NULL;
- for (p = line1 + 6 ; *p != '\0' && *p != '=' && *p != '/' ; p++);
+ for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++);
if (*p == '=') { /* eliminate initialization */
for (q = p ; *q && *q != ';' ; q++);
if (*q == '\0')
diff --git a/bin/sh/mknodes.c b/bin/sh/mknodes.c
index ef4cc33c706..3ab7df2002d 100644
--- a/bin/sh/mknodes.c
+++ b/bin/sh/mknodes.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mknodes.c,v 1.3 1996/09/15 22:58:09 millert Exp $ */
+/* $OpenBSD: mknodes.c,v 1.4 1996/10/20 00:54:54 millert Exp $ */
/* $NetBSD: mknodes.c,v 1.11 1995/05/11 21:29:36 christos Exp $ */
/*-
@@ -47,7 +47,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: mknodes.c,v 1.3 1996/09/15 22:58:09 millert Exp $";
+static char rcsid[] = "$OpenBSD: mknodes.c,v 1.4 1996/10/20 00:54:54 millert Exp $";
#endif
#endif /* not lint */
@@ -124,7 +124,7 @@ main(argc, argv)
char **argv;
{
if (argc != 3)
- error("usage: mknodes file\n");
+ error("usage: mknodes file");
if ((infp = fopen(argv[1], "r")) == NULL)
error("Can't open %s", argv[1]);
while (readline()) {
@@ -187,16 +187,16 @@ parsefield()
fp->name = savestr(name);
if (strcmp(type, "nodeptr") == 0) {
fp->type = T_NODE;
- snprintf(decl, sizeof(decl), "union node *%s", name);
+ sprintf(decl, "union node *%s", name);
} else if (strcmp(type, "nodelist") == 0) {
fp->type = T_NODELIST;
- snprintf(decl, sizeof(decl), "struct nodelist *%s", name);
+ sprintf(decl, "struct nodelist *%s", name);
} else if (strcmp(type, "string") == 0) {
fp->type = T_STRING;
- snprintf(decl, sizeof(decl), "char *%s", name);
+ sprintf(decl, "char *%s", name);
} else if (strcmp(type, "int") == 0) {
fp->type = T_INT;
- snprintf(decl, sizeof(decl), "int %s", name);
+ sprintf(decl, "int %s", name);
} else if (strcmp(type, "other") == 0) {
fp->type = T_OTHER;
} else if (strcmp(type, "temp") == 0) {
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 5506ba70623..7b01c6e949a 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mksyntax.c,v 1.3 1996/09/15 22:58:08 millert Exp $ */
+/* $OpenBSD: mksyntax.c,v 1.4 1996/10/20 00:54:55 millert Exp $ */
/* $NetBSD: mksyntax.c,v 1.11 1995/05/11 21:29:37 christos Exp $ */
/*-
@@ -47,7 +47,7 @@ static char copyright[] =
#if 0
static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: mksyntax.c,v 1.3 1996/09/15 22:58:08 millert Exp $";
+static char rcsid[] = "$OpenBSD: mksyntax.c,v 1.4 1996/10/20 00:54:55 millert Exp $";
#endif
#endif /* not lint */
@@ -172,6 +172,7 @@ main(argc, argv)
}
fputs("#include <sys/cdefs.h>\n", hfile);
+ fputs("#include <ctype.h>\n", hfile);
/* Generate the #define statements in the header file */
fputs("/* Syntax classes */\n", hfile);
@@ -351,9 +352,9 @@ print(name)
static char *macro[] = {
"#define is_digit(c)\t((is_type+SYNBASE)[c] & ISDIGIT)",
- "#define is_alpha(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER))",
- "#define is_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER))",
- "#define is_in_name(c)\t((is_type+SYNBASE)[c] & (ISUPPER|ISLOWER|ISUNDER|ISDIGIT))",
+ "#define is_alpha(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))",
+ "#define is_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))",
+ "#define is_in_name(c)\t((c) != PEOF && ((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))",
"#define is_special(c)\t((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))",
NULL
};
diff --git a/bin/sh/mktokens b/bin/sh/mktokens
index d0fdda452ac..9db772981a7 100644
--- a/bin/sh/mktokens
+++ b/bin/sh/mktokens
@@ -1,5 +1,5 @@
#!/bin/sh -
-# $OpenBSD: mktokens,v 1.2 1996/06/23 14:21:25 deraadt Exp $
+# $OpenBSD: mktokens,v 1.3 1996/10/20 00:54:56 millert Exp $
# $NetBSD: mktokens,v 1.7 1995/05/11 21:29:38 christos Exp $
#
# Copyright (c) 1991, 1993
@@ -73,7 +73,7 @@ TESAC 1 "esac"
TNOT 0 "!"
!
nl=`wc -l /tmp/ka$$`
-exec > token.def
+exec > token.h
awk '{print "#define " $1 " " NR-1}' /tmp/ka$$
echo '
/* Array indicating which tokens mark the end of a list */
diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h
index 6fc9459eca8..68759ec501a 100644
--- a/bin/sh/myhistedit.h
+++ b/bin/sh/myhistedit.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: myhistedit.h,v 1.2 1996/06/23 14:21:25 deraadt Exp $ */
+/* $OpenBSD: myhistedit.h,v 1.3 1996/10/20 00:54:57 millert Exp $ */
/* $NetBSD: myhistedit.h,v 1.4 1995/05/11 21:29:40 christos Exp $ */
/*-
@@ -43,7 +43,7 @@ extern EditLine *el;
extern int displayhist;
void histedit __P((void));
-void sethistsize __P((void));
+void sethistsize __P((const char *));
int histcmd __P((int, char **));
int not_fcnumber __P((char *));
int str_to_event __P((char *, int));
diff --git a/bin/sh/mystring.c b/bin/sh/mystring.c
index 49178a9cb6b..cfe8c84c7ce 100644
--- a/bin/sh/mystring.c
+++ b/bin/sh/mystring.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mystring.c,v 1.2 1996/06/23 14:21:26 deraadt Exp $ */
+/* $OpenBSD: mystring.c,v 1.3 1996/10/20 00:54:58 millert Exp $ */
/* $NetBSD: mystring.c,v 1.10 1995/05/11 21:29:41 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: mystring.c,v 1.2 1996/06/23 14:21:26 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: mystring.c,v 1.3 1996/10/20 00:54:58 millert Exp $";
#endif
#endif /* not lint */
@@ -122,7 +122,7 @@ number(s)
{
if (! is_number(s))
- error2("Illegal number", (char *)s);
+ error("Illegal number: %s", (char *)s);
return atoi(s);
}
diff --git a/bin/sh/options.c b/bin/sh/options.c
index 6132bb00254..506a8d3b361 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.c,v 1.2 1996/06/23 14:21:28 deraadt Exp $ */
+/* $OpenBSD: options.c,v 1.3 1996/10/20 00:54:59 millert Exp $ */
/* $NetBSD: options.c,v 1.14 1995/05/11 21:29:46 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: options.c,v 1.2 1996/06/23 14:21:28 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: options.c,v 1.3 1996/10/20 00:54:59 millert Exp $";
#endif
#endif /* not lint */
@@ -79,6 +79,7 @@ char *minusc; /* argument to -c option */
STATIC void options __P((int));
STATIC void minus_o __P((char *, int));
STATIC void setoption __P((int, int));
+STATIC int getopts __P((char *, char *, char **, char ***, char **));
/*
@@ -112,6 +113,10 @@ procargs(argc, argv)
commandname = arg0 = *argptr++;
setinputfile(commandname, 0);
}
+ /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
+ if (argptr && minusc)
+ arg0 = *argptr++;
+
shellparam.p = argptr;
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
while (*argptr) {
@@ -352,6 +357,15 @@ setcmd(argc, argv)
}
+void
+getoptsreset(value)
+ const char *value;
+{
+ if (number(value) == 1)
+ shellparam.optnext;
+}
+
+
/*
* The getopts builtin. Shellparam.optnext points to the next argument
* to be processed. Shellparam.optptr points to the next character to
@@ -364,55 +378,118 @@ getoptscmd(argc, argv)
int argc;
char **argv;
{
- register char *p, *q;
- char c;
- char s[10];
+ char **optbase;
+
+ if (argc < 3)
+ error("Usage: getopts optstring var [arg]");
+ else if (argc == 3)
+ optbase = shellparam.p;
+ else
+ optbase = &argv[3];
- if (argc != 3)
- error("Usage: getopts optstring var");
if (shellparam.optnext == NULL) {
- shellparam.optnext = shellparam.p;
+ shellparam.optnext = optbase;
shellparam.optptr = NULL;
}
- if ((p = shellparam.optptr) == NULL || *p == '\0') {
- p = *shellparam.optnext;
+
+ return getopts(argv[1], argv[2], optbase, &shellparam.optnext,
+ &shellparam.optptr);
+}
+
+
+STATIC int
+getopts(optstr, optvar, optfirst, optnext, optptr)
+ char *optstr;
+ char *optvar;
+ char **optfirst;
+ char ***optnext;
+ char **optptr;
+{
+ register char *p, *q;
+ char c = '?';
+ int done = 0;
+ int ind = 0;
+ int err = 0;
+ char s[10];
+
+ if ((p = *optptr) == NULL || *p == '\0') {
+ /* Current word is done, advance */
+ p = **optnext;
if (p == NULL || *p != '-' || *++p == '\0') {
atend:
- fmtstr(s, 10, "%d", shellparam.optnext - shellparam.p + 1);
- setvar("OPTIND", s, 0);
- shellparam.optnext = NULL;
- return 1;
+ **optnext = NULL;
+ ind = *optnext - optfirst + 1;
+ done = 1;
+ goto out;
}
- shellparam.optnext++;
+ (*optnext)++;
if (p[0] == '-' && p[1] == '\0') /* check for "--" */
goto atend;
}
+
c = *p++;
- for (q = argv[1] ; *q != c ; ) {
+ for (q = optstr; *q != c; ) {
if (*q == '\0') {
- out1fmt("Illegal option -%c\n", c);
+ if (optstr[0] == ':') {
+ s[0] = c;
+ s[1] = '\0';
+ err |= setvarsafe("OPTARG", s, 0);
+ }
+ else {
+ out1fmt("Illegal option -%c\n", c);
+ (void) unsetvar("OPTARG");
+ }
c = '?';
- goto out;
+ goto bad;
}
+
if (*++q == ':')
q++;
}
+
if (*++q == ':') {
- if (*p == '\0' && (p = *shellparam.optnext) == NULL) {
- out1fmt("No arg for -%c option\n", c);
- c = '?';
- goto out;
+ if (*p == '\0' && (p = **optnext) == NULL) {
+ if (optstr[0] == ':') {
+ s[0] = c;
+ s[1] = '\0';
+ err |= setvarsafe("OPTARG", s, 0);
+ c = ':';
+ }
+ else {
+ out1fmt("No arg for -%c option\n", c);
+ (void) unsetvar("OPTARG");
+ c = '?';
+ }
+ ind = 1;
+ *optnext = NULL;
+ goto bad;
}
- shellparam.optnext++;
- setvar("OPTARG", p, 0);
+
+ if (p == **optnext)
+ (*optnext)++;
+ ind = *optnext - optfirst + 1;
+ setvarsafe("OPTARG", p, 0);
p = NULL;
+ goto out;
}
+bad:
+ ind = 1;
+ *optnext = NULL;
+ p = NULL;
out:
- shellparam.optptr = p;
+ *optptr = p;
+ fmtstr(s, sizeof(s), "%d", ind);
+ err |= setvarsafe("OPTIND", s, VNOFUNC);
s[0] = c;
s[1] = '\0';
- setvar(argv[2], s, 0);
- return 0;
+ err |= setvarsafe(optvar, s, 0);
+ if (err) {
+ *optnext = NULL;
+ *optptr = NULL;
+ flushall();
+ exraise(EXERROR);
+ }
+ return done;
}
/*
diff --git a/bin/sh/options.h b/bin/sh/options.h
index abc9d7ac770..f1cb36a5763 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: options.h,v 1.2 1996/06/23 14:21:29 deraadt Exp $ */
+/* $OpenBSD: options.h,v 1.3 1996/10/20 00:54:59 millert Exp $ */
/* $NetBSD: options.h,v 1.8 1995/05/11 21:29:48 christos Exp $ */
/*-
@@ -111,3 +111,4 @@ int shiftcmd __P((int, char **));
int setcmd __P((int, char **));
int getoptscmd __P((int, char **));
int nextopt __P((char *));
+void getoptsreset __P((const char *));
diff --git a/bin/sh/output.c b/bin/sh/output.c
index 49e7a85408e..2f0d97cfbf7 100644
--- a/bin/sh/output.c
+++ b/bin/sh/output.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: output.c,v 1.2 1996/06/23 14:21:30 deraadt Exp $ */
+/* $OpenBSD: output.c,v 1.3 1996/10/20 00:55:00 millert Exp $ */
/* $NetBSD: output.c,v 1.15 1995/09/14 16:19:06 jtc Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: output.c,v 1.2 1996/06/23 14:21:30 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: output.c,v 1.3 1996/10/20 00:55:00 millert Exp $";
#endif
#endif /* not lint */
@@ -354,11 +354,7 @@ fmtstr(va_alist)
#define TEMPSIZE 24
-#ifdef __STDC__
-static const char digit[16] = "0123456789ABCDEF";
-#else
-static const char digit[17] = "0123456789ABCDEF";
-#endif
+static const char digit[] = "0123456789ABCDEF";
void
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 06ab737ecd7..e30da0c5457 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parser.c,v 1.4 1996/05/21 21:13:04 deraadt Exp $ */
+/* $OpenBSD: parser.c,v 1.5 1996/10/20 00:55:02 millert Exp $ */
/* $NetBSD: parser.c,v 1.29 1996/05/09 19:40:08 christos Exp $ */
/*-
@@ -73,7 +73,7 @@ static char rcsid[] = "$NetBSD: parser.c,v 1.29 1996/05/09 19:40:08 christos Exp
#define EOFMARKLEN 79
/* values returned by readtoken */
-#include "token.def"
+#include "token.h"
@@ -474,6 +474,8 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
*/
if (!redir)
synexpect(-1);
+ case TAND:
+ case TOR:
case TNL:
case TEOF:
case TWORD:
@@ -511,7 +513,7 @@ simplecmd(rpp, redir)
{
union node *args, **app;
union node **orig_rpp = rpp;
- union node *n;
+ union node *n = NULL;
/* If we don't have any redirections already, then we must reset */
/* rpp to be the address of the local redir variable. */
@@ -1299,6 +1301,11 @@ parsebackq: {
needprompt = doprompt;
break;
+ case PEOF:
+ startlinno = plinno;
+ synerror("EOF in backquote substitution");
+ break;
+
default:
break;
}
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index 94b43609fb6..1bad4d0246c 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: redir.c,v 1.2 1996/06/23 14:21:31 deraadt Exp $ */
+/* $OpenBSD: redir.c,v 1.3 1996/10/20 00:55:03 millert Exp $ */
/* $NetBSD: redir.c,v 1.12 1995/05/11 21:30:10 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: redir.c,v 1.2 1996/06/23 14:21:31 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: redir.c,v 1.3 1996/10/20 00:55:03 millert Exp $";
#endif
#endif /* not lint */
@@ -122,6 +122,9 @@ redirect(redir, flags)
}
for (n = redir ; n ; n = n->nfile.next) {
fd = n->nfile.fd;
+ if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
+ n->ndup.dupfd == fd)
+ continue; /* redirect from/to same file descriptor */
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF;
if ((i = copyfd(fd, 10)) != EMPTY) {
@@ -344,7 +347,11 @@ copyfd(from, to)
int newfd;
newfd = fcntl(from, F_DUPFD, to);
- if (newfd < 0 && errno == EMFILE)
- return EMPTY;
+ if (newfd < 0) {
+ if (errno == EMFILE)
+ return EMPTY;
+ else
+ error("%d: %s", from, strerror(errno));
+ }
return newfd;
}
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 24a4a329abd..cebc1e3aa2f 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: sh.1,v 1.3 1996/09/15 03:41:57 millert Exp $
+.\" $OpenBSD: sh.1,v 1.4 1996/10/20 00:55:04 millert Exp $
.\" $NetBSD: sh.1,v 1.15 1995/05/11 21:30:18 christos Exp $
.\" Copyright (c) 1991, 1993
.\" The Regents of the University of California. All rights reserved.
@@ -133,7 +133,7 @@ the description below.
Specifying a dash ``-'' turns the option on, while using a plus ``+''
disables the option.
The following options can be set from the command line or
-with the set(1) builtin (described later).
+with the set(1) built-in (described later).
.TP
-a allexport
Export all variables assigned to.
@@ -192,11 +192,11 @@ no effect when set after the shell has already started
running (i.e. with set(1)).
.TP
-V vi
-Enable the builtin vi(1) command line editor (disables
+Enable the built-in vi(1) command line editor (disables
-E if it has been set).
.TP
-E emacs
-Enable the builtin emacs(1) command line editor (disables
+Enable the built-in emacs(1) command line editor (disables
-V if it has been set).
.TP
-b notify
@@ -242,7 +242,8 @@ a <newline> is treated as a line continuation.
.sp
.LP
Enclosing characters in single quotes preserves the literal
-meaning of all the characters.
+meaning of all the characters (except single quotes, making
+it impossible to put single-quotes in a single-quoted string).
.sp 2
.B Double Quotes
.sp
@@ -273,7 +274,7 @@ Their meaning is discussed later.
.sp
.LP
An alias is a name and corresponding value set using the alias(1)
-builtin command. Whenever a reserved word may occur (see above),
+built-in command. Whenever a reserved word may occur (see above),
and after checking for reserved words, the shell
checks the word to see if it matches an alias. If it does,
it replaces it in the input stream with its value. For example,
@@ -398,11 +399,13 @@ in the here-doc-text are stripped.
.B Search and Execution
.sp
.LP
-There are three types of commands: shell functions, builtin commands, and normal programs -- and the
+There are three types of commands: shell functions,
+built-in commands, and normal programs -- and the
command is searched for (by name) in that order. They
each are executed in a different way.
.LP
-When a shell function is executed, all of the shell positional parameters (except $0, which remains unchanged) are
+When a shell function is executed, all of the shell positional
+parameters (except $0, which remains unchanged) are
set to the arguments of the shell function.
The variables which are explicitly placed in the environment of
the command (by placing assignments to them before the
@@ -410,37 +413,49 @@ function name) are made local to the function and are set
to the values given. Then the command given in the function
definition is executed. The positional parameters are
restored to their original values when the command completes.
+This all occurs within the current shell.
.LP
-Shell builtins are executed internally to the shell, without spawning a new process.
+Shell builtins are executed internally to the shell, without
+spawning a new process.
.LP
Otherwise, if the command name doesn't match a function
or builtin, the command is searched for as a normal
program in the filesystem (as described in the next section).
When a normal program is executed, the shell runs the program,
passing the arguments and the environment to the
-program. If the program is a shell procedure, the shell
-will interpret the program in a subshell. The shell will
+program. If the program is not a normal executable file
+(i.e., if it does not begin with the "magic number"
+whose ASCII representation is "#!", so execve(2) returns
+ENOEXEC then) 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 shell
-procedure, except that the location of commands located in
+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.
+.LP
+Note that previous versions of this document
+and the source code itself misleadingly and sporadically
+refer to a shell script without a magic number
+as a "shell procedure".
.sp 2
.B Path Search
.sp
.LP
When locating a command, the shell first looks to see if
it has a shell function by that name. Then it looks for a
-builtin command by that name.
-Finally, it searches each
-entry in PATH in turn for the command.
-.LP
+builtin command by that name. If a builtin command is not found,
+one of two things happen:
+.sp
+1) Command names containing a slash are simply executed without
+performing any searches.
+.sp
+2) The shell searches each entry in PATH in turn for the command.
The value of the PATH variable should be a series of
entries separated by colons. Each entry consists of a
directory name.
The current directory
-may be indicated by an empty directory name.
-.LP
-Command names containing a slash are simply executed without performing any of the above searches.
+may be indicated implicitly by an empty directory name,
+or explicitly by a single period.
.sp 2
.B Command Exit Status
.sp
@@ -451,7 +466,7 @@ with zero for normal or success, and non-zero for failure,
error, or a false indication. The man page for each command
should indicate the various exit codes and what they mean.
Additionally, the builtin commands return exit codes, as does
-an executed function.
+an executed shell function.
.sp 2
.B Complex Commands
.sp
@@ -476,13 +491,14 @@ command. More generally, a command is one of the following:
Unless otherwise stated, the exit status of a command is
that of the last simple command executed by the command.
.sp 2
-.B Pipeline
+.B Pipelines
.sp
.LP
A pipeline is a sequence of one or more commands separated
by the control operator |. The standard output of all but
the last command is connected to the standard input
-of the next command.
+of the next command. The standard output of the last
+command is inherited from the shell, as usual.
.LP
The format for a pipeline is:
.nf
@@ -522,6 +538,12 @@ to the standard input of command2.
A ; or <newline> terminator causes the preceding
AND-OR-list (described next) to be executed sequentially; a & causes
asynchronous execution of the preceding AND-OR-list.
+.LP
+Note that unlike some other shells, each process in the
+pipeline is a child of the invoking shell (unless it
+is a shell builtin, in which case it executes in the
+current shell -- but any effect it has on the
+environment is wiped).
.sp 2
.B Background Commands -- &
.sp
@@ -552,6 +574,9 @@ If command is followed by an ampersand, the shell starts the
command and immediately proceed onto the next command;
otherwise it waits for the command to terminate before
proceeding to the next one.
+.sp 2
+.B Short-Circuit List Operators
+.sp
.LP
``&&'' and ``||'' are AND-OR list operators. ``&&'' executes
the first command, and then executes the second command
@@ -559,6 +584,9 @@ iff the exit status of the first command is zero. ``||''
is similar, but executes the second command iff the exit
status of the first command is nonzero. ``&&'' and ``||''
both have the same priority.
+.sp 2
+.B Flow-Control Constructs -- if, while, for, case
+.sp
.LP
The syntax of the if command is
.nf
@@ -579,7 +607,9 @@ The syntax of the while command is
done
.fi
-The two lists are executed repeatedly while the exit status of the first list is zero. The until command is similar, but has the word until in place of while
+The two lists are executed repeatedly while the exit status of the
+first list is zero. The until command is similar, but has the word
+until in place of while, which causes it to
repeat until the exit status of the first list is zero.
.LP
The syntax of the for command is
@@ -602,7 +632,8 @@ The syntax of the break and continue command is
.fi
Break terminates the num innermost for or while loops.
-Continue continues with the next iteration of the innermost loop. These are implemented as builtin commands.
+Continue continues with the next iteration of the innermost loop.
+These are implemented as builtin commands.
.LP
The syntax of the case command is
.nf
@@ -616,7 +647,9 @@ The syntax of the case command is
.LP
The pattern can actually be one or more patterns (see Shell
Patterns described later), separated by ``|'' characters.
-
+.sp 2
+.B Grouping Commands Together
+.sp
.LP
Commands may be grouped by writing either
.nf
@@ -631,6 +664,17 @@ or
.fi
The first of these executes the commands in a subshell.
+Builtin commands grouped into a (list) will not affect
+the current shell.
+The second form does not fork another shell so is
+slightly more efficient.
+Grouping commands together this way allows you to
+redirect their output as though they were one program:
+.nf
+
+ { echo -n "hello"; echo " world" } > greeting
+
+.fi
.sp 2
.B Functions
.sp
@@ -662,7 +706,8 @@ value and exported and readonly flags from the variable
with the same name in the surrounding scope, if there is
one. Otherwise, the variable is initially unset. The shell
uses dynamic scoping, so that if you make the variable x
-local to function f, which then calls function g, references to the variable x made inside g will refer to the
+local to function f, which then calls function g, references
+to the variable x made inside g will refer to the
variable x declared inside f, not to the global variable
named x.
.LP
@@ -880,8 +925,8 @@ String Length. The length in characters of
the value of parameter.
.LP
The following four varieties of parameter expansion provide for substring
-processing. In each case, pattern matching notation (see Shell Patterns), rather
-than regular expression notation, is used to evaluate the patterns.
+processing. In each case, pattern matching notation (see Shell Patterns),
+rather than regular expression notation, is used to evaluate the patterns.
If parameter is * or @, the result of the expansion is unspecified.
Enclosing the full parameter expansion string in double-quotes does not
cause the following four varieties of pattern characters to be quoted,
@@ -893,7 +938,6 @@ is expanded to produce a pattern. The
parameter expansion then results in
parameter, with the smallest portion of the
suffix matched by the pattern deleted.
-
.TP
${parameter%%word}
Remove Largest Suffix Pattern. The word
@@ -981,12 +1025,14 @@ substitution into fields.
.B Pathname Expansion (File Name Generation)
.sp
.LP
-Unless the -f flag is set, file name generation is performed after word splitting is complete. Each word is
+Unless the -f flag is set, file name generation is performed
+after word splitting is complete. Each word is
viewed as a series of patterns, separated by slashes. The
process of expansion replaces the word with the names of
all existing files whose names can be formed by replacing
each pattern with a string that matches the specified pattern.
-There are two restrictions on this: first, a pattern cannot match a string containing a slash, and second,
+There are two restrictions on this: first, a pattern cannot
+match a string containing a slash, and second,
a pattern cannot match a string starting with a period
unless the first character of the pattern is a period.
The next section describes the patterns used for both
@@ -996,9 +1042,10 @@ Pathname Expansion and the case(1) command.
.B Shell Patterns
.sp
.LP
-A pattern consists of normal characters, which match themselves, and meta-characters. The meta-characters are
+A pattern consists of normal characters, which match themselves,
+and meta-characters. The meta-characters are
``!'', ``*'', ``?'', and ``[''. These characters lose
-there special meanings if they are quoted. When command
+their special meanings if they are quoted. When command
or variable substitution is performed and the dollar sign
or back quotes are not double quoted, the value of the
variable or the output of the command is scanned for these
@@ -1026,7 +1073,8 @@ minus sign, make it the first or last character listed
.LP
This section lists the builtin commands which
are builtin because they need to perform some operation
-that can't be performed by a separate process. In addition to these, there are several other commands that may
+that can't be performed by a separate process. In addition
+to these, there are several other commands that may
be builtin for efficiency (e.g. printf(1), echo(1), test(1),
etc).
.TP
@@ -1048,7 +1096,8 @@ Continue the specified jobs (or the current job if no
jobs are given) in the background.
.TP
command command arg...
-Execute the specified builtin command. (This is useful when you have a shell function with the same name
+Execute the specified built-in command. (This is useful
+when you have a shell function with the same name
as a builtin command.)
.TP
cd [ directory ]
@@ -1058,7 +1107,8 @@ of the cd command or the shell variable CDPATH is set
and the directory name does not begin with a slash,
then the directories listed in CDPATH will be
searched for the specified directory. The format of
-CDPATH is the same as that of PATH. In an interactive shell, the cd command will print out the name of
+CDPATH is the same as that of PATH. In an interactive shell,
+the cd command will print out the name of
the directory that it actually switched to if this is
different from the name that the user gave. These
may be different either because the CDPATH mechanism
@@ -1072,7 +1122,8 @@ exec [ command arg... ]
Unless command is omitted, the shell process is
replaced with the specified program (which must be a
real program, not a shell builtin or function). Any
-redirections on the exec command are marked as permanent, so that they are not undone when the exec command finishes.
+redirections on the exec command are marked as permanent,
+so that they are not undone when the exec command finishes.
.TP
exit [ exitstatus ]
Terminate the shell process. If exitstatus is given
@@ -1170,6 +1221,14 @@ foreground.
.TP
getopts optstring var
The POSIX getopts command.
+The getopts command deprecates the older getopt command.
+The first argument should be a series of letters, each possibly
+followed by a colon which indicates that the option takes an argument.
+The specified variable is set to the parsed option. The index of
+the next argument is placed into the shell variable OPTIND.
+If an option takes an argument, it is placed into the shell variable
+OPTARG. If an invalid option is encountered, var is set to '?'.
+It returns a false value (1) when it encounters the end of the options.
.TP
hash -rv command...
The shell maintains a hash table which remembers the
@@ -1179,7 +1238,8 @@ table. Entries which have not been looked at since
the last cd command are marked with an asterisk; it
is possible for these entries to be invalid.
.sp
-With arguments, the hash command removes the specified commands from the hash table (unless they are
+With arguments, the hash command removes the specified
+commands from the hash table (unless they are
functions) and then locates them. With the -v
option, hash prints the locations of the commands as
it finds them. The -r option causes the hash command
@@ -1210,15 +1270,18 @@ read from the standard input. The trailing newline
is deleted from the line and the line is split as
described in the section on word splitting above, and
the pieces are assigned to the variables in order.
-If there are more pieces than variables, the remaining pieces (along with the characters in IFS that
+If there are more pieces than variables, the remaining
+pieces (along with the characters in IFS that
separated them) are assigned to the last variable.
-If there are more variables than pieces, the remaining variables are assigned the null string.
+If there are more variables than pieces, the remaining
+variables are assigned the null string.
.sp
The -e option causes any backslashes in the input to
be treated specially. If a backslash is followed by
a newline, the backslash and the newline will be
deleted. If a backslash is followed by any other
-character, the backslash will be deleted and the following character will be treated as though it were
+character, the backslash will be deleted and the following
+character will be treated as though it were
not in IFS, even if it is.
.TP
readonly name...
@@ -1244,7 +1307,8 @@ called ``Argument List Processing''.
The third use of the set command is to set the values
of the shell's positional parameters to the specified
args. To change the positional parameters without
-changing any options, use ``--'' as the first argument to set. If no args are present, the set command
+changing any options, use ``--'' as the first argument
+to set. If no args are present, the set command
will clear all the positional parameters (equivalent
to executing ``shift $#''.
.TP
@@ -1291,8 +1355,8 @@ If no resource is specified,
size is assumed.
.TP
umask [ mask ]
-Set the value of umask (see umask(2)) to the specified octal value.
-If the argument is omitted, the
+Set the value of umask (see umask(2)) to the specified
+octal value. If the argument is omitted, the
umask value is printed.
.TP
unalias [-a] [name]
@@ -1326,3 +1390,9 @@ mode. The editor is not described in full here, but will be in a later
document. It's similar to vi: typing <ESC> will throw you into
command VI command mode. Hitting <return> while in command mode
will pass the line to the shell.
+.SH HISTORY
+A
+.I sh
+command appeared in
+Version 1 AT&T UNIX.
+It was, however, unmaintainable so we wrote this one.
diff --git a/bin/sh/shell.h b/bin/sh/shell.h
index 2074af9d85a..22ff9875288 100644
--- a/bin/sh/shell.h
+++ b/bin/sh/shell.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: shell.h,v 1.4 1996/06/23 14:21:33 deraadt Exp $ */
+/* $OpenBSD: shell.h,v 1.5 1996/10/20 00:55:05 millert Exp $ */
/* $NetBSD: shell.h,v 1.9 1996/03/01 01:59:00 jtc Exp $ */
/*-
@@ -57,7 +57,6 @@
#ifndef BSD
#define BSD 1
#endif
-#define DEBUG 1
#ifdef __STDC__
typedef void *pointer;
diff --git a/bin/sh/show.c b/bin/sh/show.c
index e9246b8975b..72815970ca0 100644
--- a/bin/sh/show.c
+++ b/bin/sh/show.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: show.c,v 1.2 1996/06/23 14:21:34 deraadt Exp $ */
+/* $OpenBSD: show.c,v 1.3 1996/10/20 00:55:06 millert Exp $ */
/* $NetBSD: show.c,v 1.11 1995/05/11 21:30:24 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: show.c,v 1.2 1996/06/23 14:21:34 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: show.c,v 1.3 1996/10/20 00:55:06 millert Exp $";
#endif
#endif /* not lint */
@@ -292,18 +292,18 @@ int debug = 0;
#endif
+#ifdef DEBUG
void
trputc(c)
int c;
{
-#ifdef DEBUG
if (tracefile == NULL)
return;
putc(c, tracefile);
if (c == '\n')
fflush(tracefile);
-#endif
}
+#endif
void
#if __STDC__
@@ -332,17 +332,16 @@ trace(va_alist)
}
+#ifdef DEBUG
void
trputs(s)
char *s;
{
-#ifdef DEBUG
if (tracefile == NULL)
return;
fputs(s, tracefile);
if (strchr(s, '\n'))
fflush(tracefile);
-#endif
}
@@ -353,7 +352,6 @@ trstring(s)
register char *p;
char c;
-#ifdef DEBUG
if (tracefile == NULL)
return;
putc('"', tracefile);
@@ -385,8 +383,8 @@ backslash: putc('\\', tracefile);
}
}
putc('"', tracefile);
-#endif
}
+#endif
void
@@ -408,6 +406,7 @@ trargs(ap)
}
+#ifdef DEBUG
void
opentrace() {
char s[100];
@@ -416,7 +415,6 @@ opentrace() {
int flags;
#endif
-#ifdef DEBUG
if (!debug)
return;
#ifdef not_this_way
@@ -444,5 +442,5 @@ opentrace() {
#endif
fputs("\nTracing started.\n", tracefile);
fflush(tracefile);
-#endif /* DEBUG */
}
+#endif /* DEBUG */
diff --git a/bin/sh/show.h b/bin/sh/show.h
index 60537fa6b1e..340b332c0a9 100644
--- a/bin/sh/show.h
+++ b/bin/sh/show.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: show.h,v 1.2 1996/06/23 14:21:34 deraadt Exp $ */
+/* $OpenBSD: show.h,v 1.3 1996/10/20 00:55:07 millert Exp $ */
/* $NetBSD: show.h,v 1.1 1995/05/11 21:30:27 christos Exp $ */
/*-
@@ -37,8 +37,10 @@
*/
void showtree __P((union node *));
-void trputc __P((int));
void trace __P((const char *, ...));
-void trputs __P((char *));
void trargs __P((char **));
+#ifdef DEBUG
+void trputc __P((int));
+void trputs __P((char *));
void opentrace __P((void));
+#endif
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 668e3e68815..1f020ccccf2 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: var.c,v 1.2 1996/06/23 14:21:36 deraadt Exp $ */
+/* $OpenBSD: var.c,v 1.3 1996/10/20 00:55:08 millert Exp $ */
/* $NetBSD: var.c,v 1.13 1995/05/11 21:30:39 christos Exp $ */
/*-
@@ -41,7 +41,7 @@
#if 0
static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
#else
-static char rcsid[] = "$OpenBSD: var.c,v 1.2 1996/06/23 14:21:36 deraadt Exp $";
+static char rcsid[] = "$OpenBSD: var.c,v 1.3 1996/10/20 00:55:08 millert Exp $";
#endif
#endif /* not lint */
@@ -65,6 +65,7 @@ static char rcsid[] = "$OpenBSD: var.c,v 1.2 1996/06/23 14:21:36 deraadt Exp $";
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
+#include "parser.h"
#ifndef NO_HISTORY
#include "myhistedit.h"
#endif
@@ -77,6 +78,7 @@ struct varinit {
struct var *var;
int flags;
char *text;
+ void (*func) __P((const char *));
};
@@ -96,31 +98,42 @@ struct var vvers;
#if ATTY
struct var vterm;
#endif
+struct var voptind;
const struct varinit varinit[] = {
#if ATTY
- {&vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY="},
+ { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
+ NULL },
#endif
#ifndef NO_HISTORY
- {&vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE="},
+ { &vhistsize, VSTRFIXED|VTEXTFIXED|VUNSET, "HISTSIZE=",
+ sethistsize },
#endif
- {&vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n"},
- {&vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL="},
- {&vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH="},
- {&vpath, VSTRFIXED|VTEXTFIXED, "PATH=/bin:/usr/bin"},
+ { &vifs, VSTRFIXED|VTEXTFIXED, "IFS= \t\n",
+ NULL },
+ { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
+ NULL },
+ { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
+ NULL },
+ { &vpath, VSTRFIXED|VTEXTFIXED, "PATH=/bin:/usr/bin",
+ changepath },
/*
* vps1 depends on uid
*/
- {&vps2, VSTRFIXED|VTEXTFIXED, "PS2=> "},
+ { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
+ NULL },
#if ATTY
- {&vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM="},
+ { &vterm, VSTRFIXED|VTEXTFIXED|VUNSET, "TERM=",
+ NULL },
#endif
- {NULL, 0, NULL}
+ { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
+ getoptsreset },
+ { NULL, 0, NULL,
+ NULL }
};
struct var *vartab[VTABSIZE];
-STATIC int unsetvar __P((char *));
STATIC struct var **hashvar __P((char *));
STATIC int varequal __P((char *, char *));
@@ -162,6 +175,7 @@ initvar() {
*vpp = vp;
vp->text = ip->text;
vp->flags = ip->flags;
+ vp->func = ip->func;
}
}
/*
@@ -177,6 +191,29 @@ initvar() {
}
/*
+ * Safe version of setvar, returns 1 on success 0 on failure.
+ */
+
+int
+setvarsafe(name, val, flags)
+ char *name, *val;
+ int flags;
+{
+ struct jmploc jmploc;
+ struct jmploc *volatile savehandler = handler;
+ int err = 0;
+
+ if (setjmp(jmploc.loc))
+ err = 1;
+ else {
+ handler = &jmploc;
+ setvar(name, val, flags);
+ }
+ handler = savehandler;
+ return err;
+}
+
+/*
* Set the value of a variable. The flags argument is ored with the
* flags of the variable. If val is NULL, the variable is unset.
*/
@@ -194,8 +231,9 @@ setvar(name, val, flags)
isbad = 0;
p = name;
- if (! is_name(*p++))
+ if (! is_name(*p))
isbad = 1;
+ p++;
for (;;) {
if (! is_in_name(*p)) {
if (*p == '\0' || *p == '=')
@@ -244,23 +282,27 @@ setvareq(s, flags)
for (vp = *vpp ; vp ; vp = vp->next) {
if (varequal(s, vp->text)) {
if (vp->flags & VREADONLY) {
- int len = strchr(s, '=') - s;
+ size_t len = strchr(s, '=') - s;
error("%.*s: is read only", len, s);
}
INTOFF;
- if (vp == &vpath)
- changepath(s + 5); /* 5 = strlen("PATH=") */
+
+ if (vp->func && (flags & VNOFUNC) == 0)
+ (*vp->func)(strchr(s, '=') + 1);
+
if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
ckfree(vp->text);
- vp->flags &=~ (VTEXTFIXED|VSTACK|VUNSET);
+
+ vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
vp->flags |= flags;
vp->text = s;
+
+ /*
+ * We could roll this to a function, to handle it as
+ * a regular variable function callback, but why bother?
+ */
if (vp == &vmpath || (vp == &vmail && ! mpathset()))
chkmail(1);
-#ifndef NO_HISTORY
- if (vp == &vhistsize)
- sethistsize();
-#endif
INTON;
return;
}
@@ -270,6 +312,7 @@ setvareq(s, flags)
vp->flags = flags;
vp->text = s;
vp->next = *vpp;
+ vp->func = NULL;
*vpp = vp;
}
@@ -639,7 +682,7 @@ unsetcmd(argc, argv)
* Unset the specified variable.
*/
-STATIC int
+int
unsetvar(s)
char *s;
{
@@ -654,7 +697,7 @@ unsetvar(s)
INTOFF;
if (*(strchr(vp->text, '=') + 1) != '\0')
setvar(s, nullstr, 0);
- vp->flags &=~ VEXPORT;
+ vp->flags &= ~VEXPORT;
vp->flags |= VUNSET;
if ((vp->flags & VSTRFIXED) == 0) {
if ((vp->flags & VTEXTFIXED) == 0)
@@ -682,9 +725,9 @@ hashvar(p)
{
unsigned int hashval;
- hashval = *p << 4;
+ hashval = ((unsigned char) *p) << 4;
while (*p && *p != '=')
- hashval += *p++;
+ hashval += (unsigned char) *p++;
return &vartab[hashval % VTABSIZE];
}
diff --git a/bin/sh/var.h b/bin/sh/var.h
index a7cd07bd712..00ed16c3983 100644
--- a/bin/sh/var.h
+++ b/bin/sh/var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: var.h,v 1.2 1996/06/23 14:21:37 deraadt Exp $ */
+/* $OpenBSD: var.h,v 1.3 1996/10/20 00:55:09 millert Exp $ */
/* $NetBSD: var.h,v 1.9 1995/05/11 21:30:44 christos Exp $ */
/*-
@@ -44,18 +44,22 @@
*/
/* flags */
-#define VEXPORT 01 /* variable is exported */
-#define VREADONLY 02 /* variable cannot be modified */
-#define VSTRFIXED 04 /* variable struct is staticly allocated */
-#define VTEXTFIXED 010 /* text is staticly allocated */
-#define VSTACK 020 /* text is allocated on the stack */
-#define VUNSET 040 /* the variable is not set */
+#define VEXPORT 0x01 /* variable is exported */
+#define VREADONLY 0x02 /* variable cannot be modified */
+#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
+#define VTEXTFIXED 0x08 /* text is staticly allocated */
+#define VSTACK 0x10 /* text is allocated on the stack */
+#define VUNSET 0x20 /* the variable is not set */
+#define VNOFUNC 0x40 /* don't call the callback function */
struct var {
struct var *next; /* next entry in hash list */
int flags; /* flags are defined above */
char *text; /* name=value */
+ void (*func) __P((const char *));
+ /* function to be called when */
+ /* the variable gets set/unset */
};
@@ -81,6 +85,9 @@ extern struct var vps2;
#if ATTY
extern struct var vterm;
#endif
+#ifndef NO_HISTORY
+extern struct var vhistsize;
+#endif
/*
* The following macros access the values of the above variables.
@@ -97,6 +104,10 @@ extern struct var vterm;
#if ATTY
#define termval() (vterm.text + 5)
#endif
+#define optindval() (voptind.text + 7)
+#ifndef NO_HISTORY
+#define histsizeval() (vhistsize.text + 9)
+#endif
#if ATTY
#define attyset() ((vatty.flags & VUNSET) == 0)
@@ -119,3 +130,4 @@ void mklocal __P((char *));
void poplocalvars __P((void));
int setvarcmd __P((int, char **));
int unsetcmd __P((int, char **));
+int unsetvar __P((char *));