summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/sh/alias.c4
-rw-r--r--bin/sh/arith.y13
-rw-r--r--bin/sh/arith_lex.l8
-rw-r--r--bin/sh/bltin/bltin.h11
-rw-r--r--bin/sh/bltin/echo.c5
-rw-r--r--bin/sh/cd.c36
-rw-r--r--bin/sh/cd.h34
-rw-r--r--bin/sh/error.c81
-rw-r--r--bin/sh/error.h4
-rw-r--r--bin/sh/eval.c82
-rw-r--r--bin/sh/eval.h9
-rw-r--r--bin/sh/exec.c28
-rw-r--r--bin/sh/exec.h5
-rw-r--r--bin/sh/expand.c46
-rw-r--r--bin/sh/histedit.c27
-rw-r--r--bin/sh/input.c27
-rw-r--r--bin/sh/input.h4
-rw-r--r--bin/sh/jobs.c68
-rw-r--r--bin/sh/mail.c4
-rw-r--r--bin/sh/main.c56
-rw-r--r--bin/sh/memalloc.c10
-rw-r--r--bin/sh/miscbltin.c24
-rw-r--r--bin/sh/mkinit.c38
-rw-r--r--bin/sh/mknodes.c6
-rw-r--r--bin/sh/mksyntax.c14
-rw-r--r--bin/sh/myhistedit.h4
-rw-r--r--bin/sh/mystring.c4
-rw-r--r--bin/sh/options.c141
-rw-r--r--bin/sh/options.h16
-rw-r--r--bin/sh/output.c26
-rw-r--r--bin/sh/output.h4
-rw-r--r--bin/sh/parser.c166
-rw-r--r--bin/sh/parser.h4
-rw-r--r--bin/sh/redir.c20
-rw-r--r--bin/sh/redir.h4
-rw-r--r--bin/sh/sh.1156
-rw-r--r--bin/sh/shell.h4
-rw-r--r--bin/sh/show.c26
-rw-r--r--bin/sh/show.h6
-rw-r--r--bin/sh/trap.c18
-rw-r--r--bin/sh/trap.h8
-rw-r--r--bin/sh/var.c105
-rw-r--r--bin/sh/var.h43
43 files changed, 908 insertions, 491 deletions
diff --git a/bin/sh/alias.c b/bin/sh/alias.c
index d6ae730..0984860 100644
--- a/bin/sh/alias.c
+++ b/bin/sh/alias.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: alias.c,v 1.3 1995/05/30 00:07:10 rgrimes Exp $
+ * $Id: alias.c,v 1.4 1996/09/01 10:19:26 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)alias.c 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include <stdlib.h>
diff --git a/bin/sh/arith.y b/bin/sh/arith.y
index 0a08dc5..fe04ff1 100644
--- a/bin/sh/arith.y
+++ b/bin/sh/arith.y
@@ -1,4 +1,4 @@
-%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
+%token ARITH_NUM ARITH_LPAREN ARITH_RPAREN
%left ARITH_OR
%left ARITH_AND
@@ -39,12 +39,12 @@ expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
| expr ARITH_DIV expr = {
if ($3 == 0)
yyerror("division by zero");
- $$ = $1 / $3;
+ $$ = $1 / $3;
}
| expr ARITH_REM expr = {
if ($3 == 0)
yyerror("division by zero");
- $$ = $1 % $3;
+ $$ = $1 % $3;
}
| ARITH_NOT expr = { $$ = !($2); }
| ARITH_BNOT expr = { $$ = ~($2); }
@@ -88,11 +88,11 @@ expr: ARITH_LPAREN expr ARITH_RPAREN = { $$ = $2; }
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: arith.y,v 1.2 1994/09/24 02:57:21 davidg Exp $
+ * $Id: arith.y,v 1.3 1996/09/01 10:19:38 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include "shell.h"
@@ -101,10 +101,11 @@ static char sccsid[] = "@(#)arith.y 8.3 (Berkeley) 5/4/95";
#include "memalloc.h"
char *arith_buf, *arith_startbuf;
+extern void arith_lex_reset();
int
arith(s)
- char *s;
+ char *s;
{
long result;
diff --git a/bin/sh/arith_lex.l b/bin/sh/arith_lex.l
index 61f21da..29d73f4 100644
--- a/bin/sh/arith_lex.l
+++ b/bin/sh/arith_lex.l
@@ -34,11 +34,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: arith_lex.l,v 1.4 1996/06/02 17:06:40 phk Exp $
+ * $Id: arith_lex.l,v 1.5 1996/09/01 10:19:41 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)arith_lex.l 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include <unistd.h>
@@ -50,6 +50,7 @@ extern char *arith_buf, *arith_startbuf;
#undef YY_INPUT
#define YY_INPUT(buf,result,max) \
result = (*buf = *arith_buf++) ? 1 : YY_NULL;
+#define YY_NO_UNPUT
%}
%%
@@ -73,12 +74,13 @@ extern char *arith_buf, *arith_startbuf;
"*" { return(ARITH_MUL); }
"/" { return(ARITH_DIV); }
"%" { return(ARITH_REM); }
-"+" { return(ARITH_ADD); }
+"+" { return(ARITH_ADD); }
"-" { return(ARITH_SUB); }
"~" { return(ARITH_BNOT); }
"!" { return(ARITH_NOT); }
. { error("arith: syntax error: \"%s\"\n", arith_startbuf); }
%%
+#undef yyunput
void
arith_lex_reset() {
diff --git a/bin/sh/bltin/bltin.h b/bin/sh/bltin/bltin.h
index 7745dac..ff79458 100644
--- a/bin/sh/bltin/bltin.h
+++ b/bin/sh/bltin/bltin.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)bltin.h 8.2 (Berkeley) 5/4/95
- * $Id: bltin.h,v 1.4 1995/12/14 23:19:36 bde Exp $
+ * $Id: bltin.h,v 1.5 1996/09/01 10:22:13 peter Exp $
*/
/*
@@ -60,11 +60,12 @@
#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(buf); \
+#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/bltin/echo.c b/bin/sh/bltin/echo.c
index 7c6e0f1..1d78f14 100644
--- a/bin/sh/bltin/echo.c
+++ b/bin/sh/bltin/echo.c
@@ -34,16 +34,13 @@
* SUCH DAMAGE.
*
* @(#)echo.c 8.2 (Berkeley) 5/4/95
- * $Id: echo.c,v 1.3 1995/08/23 05:31:06 pst Exp $
+ * $Id: echo.c,v 1.4 1996/09/01 10:22:16 peter Exp $
*/
/*
* Echo command.
*/
-#ifdef main
-#undef main
-#endif
#define main echocmd
#include "bltin.h"
diff --git a/bin/sh/cd.c b/bin/sh/cd.c
index 34d1bd2..34cc4ea 100644
--- a/bin/sh/cd.c
+++ b/bin/sh/cd.c
@@ -33,16 +33,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: cd.c,v 1.5 1995/11/14 01:04:52 peter Exp $
+ * $Id: cd.c,v 1.6 1996/09/01 10:19:47 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
+#include <string.h>
#include <unistd.h>
#include <errno.h>
@@ -58,29 +59,29 @@ static char sccsid[] = "@(#)cd.c 8.2 (Berkeley) 5/4/95";
#include "output.h"
#include "memalloc.h"
#include "error.h"
+#include "exec.h"
#include "redir.h"
#include "mystring.h"
#include "show.h"
+#include "cd.h"
STATIC int docd __P((char *, int));
STATIC char *getcomponent __P((void));
STATIC void updatepwd __P((char *));
-STATIC void getpwd __P((void));
-char *curdir; /* current working directory */
+char *curdir = NULL; /* current working directory */
char *prevdir; /* previous working directory */
STATIC char *cdcomppath;
int
cdcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char *dest;
char *path;
char *p;
struct stat statb;
- char *padvance();
int print = 0;
nextopt(nullstr);
@@ -133,7 +134,9 @@ STATIC int
docd(dest, print)
char *dest;
int print;
- {
+{
+
+ TRACE(("docd(\"%s\", %d) called\n", dest, print));
INTOFF;
if (chdir(dest) < 0) {
INTON;
@@ -319,7 +322,7 @@ updatepwd(dir)
int
pwdcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
getpwd();
out1str(curdir);
@@ -329,17 +332,18 @@ pwdcmd(argc, argv)
+
+#define MAXPWD 256
+
/*
* Run /bin/pwd to find out what the current directory is. We suppress
* interrupts throughout most of this, but the user can still break out
* of it by killing the pwd program. If we already know the current
* directory, this routine returns immediately.
*/
-
-#define MAXPWD 256
-
-STATIC void
-getpwd() {
+void
+getpwd()
+{
char buf[MAXPWD];
char *p;
int i;
@@ -364,10 +368,10 @@ getpwd() {
copyfd(pip[1], 1);
close(pip[1]);
}
- execl(pwd_bin, "pwd", (char *)0);
+ (void) execl(pwd_bin, "pwd", (char *)0);
error("Cannot exec %s", pwd_bin);
}
- close(pip[1]);
+ (void) close(pip[1]);
pip[1] = -1;
p = buf;
while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
@@ -375,7 +379,7 @@ getpwd() {
if (i > 0)
p += i;
}
- close(pip[0]);
+ (void) close(pip[0]);
pip[0] = -1;
status = waitforjob(jp);
if (status != 0)
diff --git a/bin/sh/cd.h b/bin/sh/cd.h
new file mode 100644
index 0000000..1fccd7b
--- /dev/null
+++ b/bin/sh/cd.h
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+void getpwd __P((void));
diff --git a/bin/sh/error.c b/bin/sh/error.c
index 9bd94ca..cfc270d 100644
--- a/bin/sh/error.c
+++ b/bin/sh/error.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: error.c,v 1.4 1996/09/01 10:19:53 peter Exp $
+ * $Id: error.c,v 1.5 1996/09/03 14:15:46 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)error.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
@@ -66,6 +66,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
@@ -73,7 +75,7 @@ char *commandname;
*/
void
-exraise(e)
+exraise(e)
int e;
{
if (handler == NULL)
@@ -104,6 +106,7 @@ onint() {
intpending = 0;
sigemptyset(&sigset);
sigprocmask(SIG_SETMASK, &sigset, NULL);
+ out2str("\n");
if (rootshell && iflag)
exraise(EXINT);
else
@@ -111,12 +114,36 @@ onint() {
}
-
/*
- * 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
@@ -131,30 +158,40 @@ 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()));
+ exverror(EXERROR, msg, ap);
+ va_end(ap);
+}
+
+
+#if __STDC__
+void
+exerror(int cond, char *msg, ...)
+#else
+void
+exerror(va_alist)
+ va_dcl
#endif
- if (msg) {
- if (commandname)
- outfmt(&errout, "%s: ", commandname);
- doformat(&errout, msg, ap);
- out2c('\n');
- }
+{
+#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);
- flushall();
- exraise(EXERROR);
}
@@ -234,7 +271,7 @@ STATIC const struct errname errormsg[] = {
*/
char *
-errmsg(e, action)
+errmsg(e, action)
int e;
int action;
{
diff --git a/bin/sh/error.h b/bin/sh/error.h
index fb26f1e..767ba66 100644
--- a/bin/sh/error.h
+++ b/bin/sh/error.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)error.h 8.2 (Berkeley) 5/4/95
- * $Id: error.h,v 1.3 1996/09/01 10:19:55 peter Exp $
+ * $Id: error.h,v 1.4 1996/09/03 14:15:48 peter Exp $
*/
/*
@@ -69,6 +69,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 */
/*
@@ -91,6 +92,7 @@ extern char *commandname; /* name of command--printed on error */
void exraise __P((int));
void onint __P((void));
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 a74b6ca..1539ec0 100644
--- a/bin/sh/eval.c
+++ b/bin/sh/eval.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: eval.c,v 1.7 1996/10/22 03:02:07 steve Exp $
+ * $Id: eval.c,v 1.8 1996/11/12 18:35:06 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
+static char const sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#endif /* not lint */
#include <signal.h>
@@ -76,12 +76,6 @@ static char sccsid[] = "@(#)eval.c 8.9 (Berkeley) 6/8/95";
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */
-
-/* reasons for skipping commands (see comment on breakcmd routine) */
-#define SKIPBREAK 1
-#define SKIPCONT 2
-#define SKIPFUNC 3
-
MKINIT int evalskip; /* set if we are skipping commands */
STATIC int skipcount; /* number of levels to skip */
MKINIT int loopnest; /* current loop nesting level */
@@ -129,9 +123,9 @@ SHELLPROC {
*/
int
-evalcmd(argc, argv)
+evalcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char *p;
char *concat;
@@ -234,17 +228,15 @@ evaltree(n, flags)
evalsubshell(n, flags);
break;
case NIF: {
- int status;
-
evaltree(n->nif.test, EV_TESTED);
- status = exitstatus;
- exitstatus = 0;
if (evalskip)
goto out;
- if (status == 0)
+ if (exitstatus == 0)
evaltree(n->nif.ifpart, flags);
else if (n->nif.elsepart)
evaltree(n->nif.elsepart, flags);
+ else
+ exitstatus = 0;
break;
}
case NWHILE:
@@ -688,7 +680,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;
}
@@ -700,7 +692,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;
}
@@ -741,10 +733,13 @@ 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;
+ shellparam.reset = 1;
shellparam.nparam = argc - 1;
shellparam.p = argv + 1;
shellparam.optnext = NULL;
@@ -786,7 +781,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;
@@ -822,13 +819,14 @@ cmddone:
}
handler = savehandler;
if (e != -1) {
- if (e != EXERROR || cmdentry.u.index == BLTINCMD
- || cmdentry.u.index == DOTCMD
- || cmdentry.u.index == EVALCMD
+ if ((e != EXERROR && e != EXEXEC)
+ || cmdentry.u.index == BLTINCMD
+ || cmdentry.u.index == DOTCMD
+ || cmdentry.u.index == EVALCMD
#ifndef NO_HISTORY
- || cmdentry.u.index == HISTCMD
+ || cmdentry.u.index == HISTCMD
#endif
- || cmdentry.u.index == EXECCMD)
+ || cmdentry.u.index == EXECCMD)
exraise(e);
FORCEINTON;
}
@@ -840,7 +838,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)
@@ -904,12 +904,12 @@ prehash(n)
int
bltincmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
listsetvar(cmdenviron);
- /*
+ /*
* Preserve exitstatus of a previous possible redirection
- * as POSIX mandates
+ * as POSIX mandates
*/
return exitstatus;
}
@@ -929,13 +929,10 @@ bltincmd(argc, argv)
int
breakcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
- int n;
+ int n = argc > 1 ? number(argv[1]) : 1;
- n = 1;
- if (argc > 1)
- n = number(argv[1]);
if (n > loopnest)
n = loopnest;
if (n > 0) {
@@ -951,45 +948,46 @@ breakcmd(argc, argv)
*/
int
-returncmd(argc, argv)
+returncmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
- int ret;
+ int ret = argc > 1 ? number(argv[1]) : oexitstatus;
- ret = exitstatus;
- if (argc > 1)
- ret = number(argv[1]);
if (funcnest) {
evalskip = SKIPFUNC;
skipcount = 1;
+ } else {
+ /* skip the rest of the file */
+ evalskip = SKIPFILE;
+ skipcount = 1;
}
return ret;
}
int
-falsecmd(argc, argv)
+falsecmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
return 1;
}
int
-truecmd(argc, argv)
+truecmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
return 0;
}
int
-execcmd(argc, argv)
+execcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
if (argc > 1) {
struct strlist *sp;
diff --git a/bin/sh/eval.h b/bin/sh/eval.h
index 8649bf8..ceaef6d 100644
--- a/bin/sh/eval.h
+++ b/bin/sh/eval.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)eval.h 8.2 (Berkeley) 5/4/95
- * $Id: eval.h,v 1.2 1994/09/24 02:57:31 davidg Exp $
+ * $Id: eval.h,v 1.3 1996/09/01 10:19:59 peter Exp $
*/
extern char *commandname; /* currently executing command */
@@ -64,3 +64,10 @@ int execcmd __P((int, char **));
/* in_function returns nonzero if we are currently evaluating a function */
#define in_function() funcnest
extern int funcnest;
+extern int evalskip;
+
+/* reasons for skipping commands (see comment on breakcmd routine) */
+#define SKIPBREAK 1
+#define SKIPCONT 2
+#define SKIPFUNC 3
+#define SKIPFILE 4
diff --git a/bin/sh/exec.c b/bin/sh/exec.c
index dec1eaf..3ebdc49 100644
--- a/bin/sh/exec.c
+++ b/bin/sh/exec.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: exec.c,v 1.5 1996/09/01 10:20:02 peter Exp $
+ * $Id: exec.c,v 1.6 1996/09/03 14:15:49 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
+static char const sccsid[] = "@(#)exec.c 8.4 (Berkeley) 6/8/95";
#endif /* not lint */
#include <sys/types.h>
@@ -93,10 +93,13 @@ 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 **));
+#ifndef BSD
STATIC void execinterp __P((char **, char **));
+#endif
STATIC void printentry __P((struct tblentry *, int));
STATIC void clearcmdentry __P((int));
STATIC struct tblentry *cmdlookup __P((char *, int));
@@ -132,7 +135,20 @@ shellexec(argv, envp, path, index)
stunalloc(cmdname);
}
}
- error("%s: %s", 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));
}
@@ -309,7 +325,7 @@ padvance(path, name)
int
hashcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct tblentry **pp;
struct tblentry *cmdp;
@@ -578,9 +594,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 fea5bd5..faeb9f2 100644
--- a/bin/sh/exec.h
+++ b/bin/sh/exec.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)exec.h 8.3 (Berkeley) 6/8/95
- * $Id: exec.h,v 1.2 1994/09/24 02:57:33 davidg Exp $
+ * $Id: exec.h,v 1.3 1996/09/01 10:20:05 peter Exp $
*/
/* values of cmdtype */
@@ -54,6 +54,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 *));
@@ -61,7 +62,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 659da14..4af0aac 100644
--- a/bin/sh/expand.c
+++ b/bin/sh/expand.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: expand.c,v 1.10 1996/09/10 02:42:30 peter Exp $
+ * $Id: expand.c,v 1.11 1996/10/31 07:15:54 ache Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
+static char const sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95";
#endif /* not lint */
#include <sys/types.h>
@@ -95,7 +95,7 @@ struct arglist exparg; /* holds expanded arg list */
STATIC void argstr __P((char *, int));
STATIC char *exptilde __P((char *, int));
STATIC void expbackq __P((union node *, int, int));
-STATIC int subevalvar __P((char *, char *, int, int, int));
+STATIC int subevalvar __P((char *, char *, int, int, int, int));
STATIC char *evalvar __P((char *, int));
STATIC int varisset __P((char *));
STATIC void varvalue __P((char *, int, int));
@@ -439,30 +439,35 @@ expbackq(cmd, quoted, flag)
STATIC int
-subevalvar(p, str, subtype, startloc, varflags)
+subevalvar(p, str, strloc, subtype, startloc, varflags)
char *p;
char *str;
+ int strloc;
int subtype;
int startloc;
int varflags;
{
-
char *startp;
char *loc = NULL;
int c = 0;
int saveherefd = herefd;
struct nodelist *saveargbackq = argbackq;
+ int amount;
+
herefd = -1;
argstr(p, 0);
STACKSTRNUL(expdest);
herefd = saveherefd;
argbackq = saveargbackq;
startp = stackblock() + startloc;
+ if (str == NULL)
+ str = stackblock() + strloc;
switch (subtype) {
case VSASSIGN:
setvar(str, startp, 0);
- STADJUST(startp - expdest, expdest);
+ amount = startp - expdest;
+ STADJUST(amount, expdest);
varflags &= ~VSNUL;
if (c != 0)
*loc = c;
@@ -505,7 +510,8 @@ subevalvar(p, str, subtype, startloc, varflags)
case VSTRIMRIGHT:
for (loc = str - 1; loc >= startp; loc--) {
if (patmatch(str, loc)) {
- expdest = loc;
+ amount = loc - expdest;
+ STADJUST(amount, expdest);
return 1;
}
}
@@ -514,7 +520,8 @@ subevalvar(p, str, subtype, startloc, varflags)
case VSTRIMRIGHTMAX:
for (loc = startp; loc < str - 1; loc++) {
if (patmatch(str, loc)) {
- expdest = loc;
+ amount = loc - expdest;
+ STADJUST(amount, expdest);
return 1;
}
}
@@ -526,7 +533,8 @@ subevalvar(p, str, subtype, startloc, varflags)
}
recordleft:
- expdest = (str - 1) - (loc - startp);
+ amount = ((str - 1) - (loc - startp)) - expdest;
+ STADJUST(amount, expdest);
while (loc != str - 1)
*startp++ = *loc++;
return 1;
@@ -588,7 +596,7 @@ again: /* jump here after setting a variable with ${var=text} */
expdest = oexpdest;
}
} else {
- char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
+ char const *syntax = (varflags & VSQUOTE) ? DQSYNTAX
: BASESYNTAX;
if (subtype == VSLENGTH) {
@@ -605,11 +613,11 @@ again: /* jump here after setting a variable with ${var=text} */
}
}
}
-
+
if (subtype == VSPLUS)
set = ! set;
- easy = ((varflags & VSQUOTE) == 0 ||
+ easy = ((varflags & VSQUOTE) == 0 ||
(*var == '@' && shellparam.nparam != 1));
@@ -622,7 +630,7 @@ again: /* jump here after setting a variable with ${var=text} */
if (!easy)
break;
record:
- recordregion(startloc, expdest - stackblock(),
+ recordregion(startloc, expdest - stackblock(),
varflags & VSQUOTE);
break;
@@ -648,15 +656,18 @@ record:
*/
STPUTC('\0', expdest);
pat = expdest;
- if (subevalvar(p, pat, subtype, startloc, varflags))
+ if (subevalvar(p, NULL, expdest - stackblock(), subtype,
+ startloc, varflags))
goto record;
break;
case VSASSIGN:
case VSQUESTION:
if (!set) {
- if (subevalvar(p, var, subtype, startloc, varflags))
+ if (subevalvar(p, var, 0, subtype, startloc, varflags)) {
+ varflags &= ~VSNUL;
goto again;
+ }
break;
}
if (easy)
@@ -698,7 +709,6 @@ varisset(name)
char *name;
{
char **ap;
- int num;
if (*name == '!') {
if (backgndpid == -1)
@@ -707,7 +717,7 @@ varisset(name)
if (*shellparam.p == NULL)
return 0;
} else if (is_digit(*name)) {
- num = atoi(name);
+ int num = atoi(name);
ap = shellparam.p;
while (num-- > 0)
if (*ap++ == NULL)
@@ -811,7 +821,7 @@ allargs:
*/
STATIC void
-recordregion(start, end, nulonly)
+recordregion(start, end, nulonly)
int start;
int end;
int nulonly;
diff --git a/bin/sh/histedit.c b/bin/sh/histedit.c
index 6d5e280..8f40d97 100644
--- a/bin/sh/histedit.c
+++ b/bin/sh/histedit.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: histedit.c,v 1.5 1996/09/01 10:20:12 peter Exp $
+ * $Id: histedit.c,v 1.6 1996/09/03 13:35:09 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)histedit.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
#include <sys/param.h>
@@ -77,7 +77,7 @@ STATIC char *fc_replace __P((const char *, char *, char *));
* have changed (figures out what to do).
*/
void
-histedit()
+histedit()
{
#define editing (Eflag || Vflag)
@@ -92,7 +92,7 @@ histedit()
INTON;
if (hist != NULL)
- sethistsize();
+ sethistsize(histsizeval());
else
out2str("sh: can't initialize history\n");
}
@@ -145,15 +145,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);
}
@@ -418,14 +417,12 @@ fc_replace(s, p, r)
int
not_fcnumber(s)
- char *s;
+ char *s;
{
- if (s == NULL) {
- /* NULL is not a fc_number */
+ if (s == NULL)
return (1);
- }
- if (*s == '-')
- s++;
+ if (*s == '-')
+ s++;
return (!is_number(s));
}
diff --git a/bin/sh/input.c b/bin/sh/input.c
index e1c530c..f8ca1da 100644
--- a/bin/sh/input.c
+++ b/bin/sh/input.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: input.c,v 1.5 1996/09/01 10:20:18 peter Exp $
+ * $Id: input.c,v 1.6 1996/09/03 14:15:50 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
+static char const sccsid[] = "@(#)input.c 8.3 (Berkeley) 6/9/95";
#endif /* not lint */
#include <stdio.h> /* defines BUFSIZ */
@@ -84,8 +84,8 @@ struct parsefile {
struct parsefile *prev; /* preceding file on stack */
int linno; /* current line */
int fd; /* file descriptor (or -1 if string) */
- int nleft; /* number of chars left in line */
- int lleft; /* number of lines left in buffer */
+ int nleft; /* number of chars left in this line */
+ int lleft; /* number of lines left in this buffer */
char *nextc; /* next char in buffer */
char *buf; /* input buffer */
struct strpush *strpush; /* for pushing strings at this level */
@@ -106,6 +106,7 @@ int whichprompt; /* 1 == PS1, 2 == PS2 */
EditLine *el; /* cookie for editline package */
STATIC void pushfile __P((void));
+static int pread __P((void));
#ifdef mkinit
INCLUDE "input.h"
@@ -165,16 +166,18 @@ pfgets(line, len)
*/
int
-pgetc() {
+pgetc()
+{
return pgetc_macro();
}
+
static int
pread()
{
int nr;
-
parsenextc = parsefile->buf;
+
retry:
if (parsefile->fd == 0 && el) {
const char *rl_cp;
@@ -184,9 +187,8 @@ retry:
nr = 0;
else {
/* XXX - BUFSIZE should redesign so not necessary */
- (void)strcpy(parsenextc, rl_cp);
+ (void) strcpy(parsenextc, rl_cp);
}
-
} else {
nr = read(parsefile->fd, parsenextc, BUFSIZ - 1);
}
@@ -206,7 +208,7 @@ retry:
}
}
}
- nr = -1;
+ nr = -1;
}
return nr;
}
@@ -217,12 +219,13 @@ retry:
* 1) If a string was pushed back on the input, pop it;
* 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
* from a string so we can't refill the buffer, return EOF.
- * 3) If there is more in the buffer, use it; else call read to fill it.
- * 4) Process input up to next newline, deleting nul characters.
+ * 3) If there is more in this buffer, use it else call read to fill it.
+ * 4) Process input up to the next newline, deleting nul characters.
*/
int
-preadbuffer() {
+preadbuffer()
+{
char *p, *q;
int more;
int something;
diff --git a/bin/sh/input.h b/bin/sh/input.h
index b90725a..e2d2571 100644
--- a/bin/sh/input.h
+++ b/bin/sh/input.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)input.h 8.2 (Berkeley) 5/4/95
- * $Id: input.h,v 1.2 1994/09/24 02:57:40 davidg Exp $
+ * $Id: input.h,v 1.3 1996/09/01 10:20:21 peter Exp $
*/
/* PEOF (the end of file marker) is defined in syntax.h */
@@ -57,7 +57,7 @@ void pushstring __P((char *, int, void *));
void popstring __P((void));
void setinputfile __P((char *, int));
void setinputfd __P((int, int));
-void setinputstring __P((char *, int));
+void setinputstring __P((char *, int));
void popfile __P((void));
void popallfiles __P((void));
void closescript __P((void));
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index 28c0048..b57b870 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: jobs.c,v 1.7 1996/09/03 14:15:52 peter Exp $
+ * $Id: jobs.c,v 1.8 1996/10/16 02:30:39 steve Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)jobs.c 8.5 (Berkeley) 5/4/95";
#endif /* not lint */
#include <fcntl.h>
@@ -87,11 +87,15 @@ int initialpgrp; /* pgrp of shell on invocation */
short curjob; /* current job */
#endif
+#if JOBS
STATIC void restartjob __P((struct job *));
+#endif
STATIC void freejob __P((struct job *));
STATIC struct job *getjob __P((char *));
STATIC int dowait __P((int, struct job *));
+#if SYSV
STATIC int onsigchild __P((void));
+#endif
STATIC int waitproc __P((int, int *));
STATIC void cmdtxt __P((union node *));
STATIC void cmdputs __P((char *));
@@ -107,8 +111,9 @@ STATIC void cmdputs __P((char *));
MKINIT int jobctl;
+#if JOBS
void
-setjobctl(on)
+setjobctl(on)
int on;
{
#ifdef OLD_TTY_DRIVER
@@ -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,16 +152,25 @@ 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);
}
jobctl = on;
}
+#endif
#ifdef mkinit
@@ -172,7 +191,7 @@ SHELLPROC {
int
fgcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct job *jp;
int pgrp;
@@ -182,7 +201,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);
@@ -194,7 +217,7 @@ fgcmd(argc, argv)
int
bgcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct job *jp;
@@ -233,7 +256,7 @@ restartjob(jp)
int
jobscmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
showjobs(0);
return 0;
@@ -250,7 +273,7 @@ jobscmd(argc, argv)
*/
void
-showjobs(change)
+showjobs(change)
int change;
{
int jobno;
@@ -346,9 +369,9 @@ freejob(jp)
int
-waitcmd(argc, argv)
+waitcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct job *job;
int status;
@@ -391,9 +414,9 @@ waitcmd(argc, argv)
int
-jobidcmd(argc, argv)
+jobidcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct job *jp;
int i;
@@ -486,15 +509,12 @@ makejob(node, nprocs)
if (njobs == 0) {
jobtab = ckmalloc(4 * sizeof jobtab[0]);
} else {
- struct job *ojp;
-
jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
- for (i = njobs, ojp = jobtab; --i >= 0;
- jp++, ojp++)
- if (ojp->ps == &ojp->ps0)
- ojp->ps = &jp->ps0;
- jp -= njobs;
memcpy(jp, jobtab, njobs * sizeof jp[0]);
+ /* Relocate `ps' pointers */
+ for (i = 0; i < njobs; i++)
+ if (jp[i].ps == &jobtab[i].ps0)
+ jp[i].ps = &jp[i].ps0;
ckfree(jobtab);
jobtab = jp;
}
@@ -583,8 +603,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", errno);
+#else
+ if (tcsetpgrp(2, pgrp) < 0)
+ error("tcsetpgrp failed, errno=%d", errno);
+#endif
}
setsignal(SIGTSTP);
setsignal(SIGTTOU);
@@ -677,8 +702,13 @@ waitforjob(jp)
}
#if JOBS
if (jp->jobctl) {
+#ifdef OLD_TTY_DRIVER
if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
- error("TIOCSPGRP failed, errno=%d", errno);
+ 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/mail.c b/bin/sh/mail.c
index 8b747c2..1470ee3 100644
--- a/bin/sh/mail.c
+++ b/bin/sh/mail.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mail.c,v 1.2 1994/09/24 02:57:44 davidg Exp $
+ * $Id: mail.c,v 1.3 1996/09/01 10:20:35 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)mail.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
diff --git a/bin/sh/main.c b/bin/sh/main.c
index f392c12..55f340c 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -33,17 +33,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: main.c,v 1.8 1996/09/12 12:41:46 adam Exp $
+ * $Id: main.c,v 1.9 1996/10/29 03:12:47 steve Exp $
*/
#ifndef lint
-static char copyright[] =
+static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
+static char const sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
#endif /* not lint */
#include <stdio.h>
@@ -73,13 +73,12 @@ static char sccsid[] = "@(#)main.c 8.6 (Berkeley) 5/28/95";
#include "init.h"
#include "mystring.h"
#include "exec.h"
+#include "cd.h"
#define PROFILE 0
int rootpid;
int rootshell;
-STATIC union node *curcmd;
-STATIC union node *prevcmd;
extern int errno;
#if PROFILE
short profile_buf[16384];
@@ -100,7 +99,7 @@ STATIC char *find_dot_file __P((char *));
int
main(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct jmploc jmploc;
struct stackmark smark;
@@ -118,15 +117,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
@@ -157,6 +171,7 @@ main(argc, argv)
init();
setstackmark(&smark);
procargs(argc, argv);
+ getpwd();
if (argv[0] && argv[0][0] == '-') {
state = 1;
read_profile("/etc/profile");
@@ -199,7 +214,7 @@ state4: /* XXX ??? - why isn't this before the "if" statement */
*/
void
-cmdloop(top)
+cmdloop(top)
int top;
{
union node *n;
@@ -236,6 +251,10 @@ cmdloop(top)
evaltree(n, 0);
}
popstackmark(&smark);
+ if (evalskip == SKIPFILE) {
+ evalskip = 0;
+ break;
+ }
}
popstackmark(&smark); /* unnecessary */
}
@@ -315,9 +334,9 @@ find_dot_file(basename)
}
int
-dotcmd(argc, argv)
+dotcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct strlist *sp;
exitstatus = 0;
@@ -338,15 +357,18 @@ dotcmd(argc, argv)
int
-exitcmd(argc, argv)
+exitcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
extern int oexitstatus;
if (stoppedjobs())
return 0;
- exitstatus = (argc > 1) ? number(argv[1]) : oexitstatus;
+ if (argc > 1)
+ exitstatus = number(argv[1]);
+ else
+ exitstatus = oexitstatus;
exitshell(exitstatus);
/*NOTREACHED*/
return 0;
diff --git a/bin/sh/memalloc.c b/bin/sh/memalloc.c
index adaf1fe..5870c9d 100644
--- a/bin/sh/memalloc.c
+++ b/bin/sh/memalloc.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: memalloc.c,v 1.3 1996/09/01 10:20:42 peter Exp $
+ * $Id: memalloc.c,v 1.4 1996/09/03 14:15:53 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include "shell.h"
@@ -54,7 +54,7 @@ static char sccsid[] = "@(#)memalloc.c 8.3 (Berkeley) 5/4/95";
*/
pointer
-ckmalloc(nbytes)
+ckmalloc(nbytes)
int nbytes;
{
register pointer p;
@@ -124,7 +124,7 @@ int herefd = -1;
pointer
-stalloc(nbytes)
+stalloc(nbytes)
int nbytes;
{
register char *p;
@@ -233,7 +233,7 @@ growstackblock() {
void
-grabstackblock(len)
+grabstackblock(len)
int len;
{
len = ALIGN(len);
diff --git a/bin/sh/miscbltin.c b/bin/sh/miscbltin.c
index 60311dd..a0c1686 100644
--- a/bin/sh/miscbltin.c
+++ b/bin/sh/miscbltin.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: miscbltin.c,v 1.7 1996/09/03 14:15:54 peter Exp $
+ * $Id: miscbltin.c,v 1.8 1996/09/03 14:24:44 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95";
#endif /* not lint */
/*
@@ -76,7 +76,7 @@ extern char **argptr; /* argument list for builtin command */
int
readcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char **ap;
int backslash;
@@ -160,7 +160,7 @@ readcmd(argc, argv)
int
umaskcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char *ap;
int mask;
@@ -221,7 +221,7 @@ umaskcmd(argc, argv)
} while (*++ap != '\0');
umask(mask);
} else {
- void *set;
+ void *set;
if ((set = setmode (ap)) == 0)
error("Illegal number: %s", ap);
@@ -320,14 +320,14 @@ ulimitcmd(argc, argv)
for (l = limits; l->name && l->option != what; l++)
;
if (!l->name)
- error("internal error (%c)", what);
+ error("ulimit: internal error (%c)", what);
set = *argptr ? 1 : 0;
if (set) {
char *p = *argptr;
if (all || argptr[1])
- error("too many arguments");
+ error("ulimit: too many arguments");
if (strcmp(p, "unlimited") == 0)
val = RLIM_INFINITY;
else {
@@ -340,7 +340,7 @@ ulimitcmd(argc, argv)
break;
}
if (c)
- error("bad number");
+ error("ulimit: bad number");
val *= l->factor;
}
}
@@ -348,7 +348,7 @@ ulimitcmd(argc, argv)
for (l = limits; l->name; l++) {
char optbuf[40];
if (getrlimit(l->cmd, &limit) < 0)
- error("can't get limit: %s", strerror(errno));
+ error("ulimit: can't get limit: %s", strerror(errno));
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
@@ -373,22 +373,20 @@ ulimitcmd(argc, argv)
}
if (getrlimit(l->cmd, &limit) < 0)
- error("can't get limit: %s", strerror(errno));
+ error("ulimit: can't get limit: %s", strerror(errno));
if (set) {
if (how & SOFT)
limit.rlim_cur = val;
if (how & HARD)
limit.rlim_max = val;
if (setrlimit(l->cmd, &limit) < 0)
- error("bad limit: %s", strerror(errno));
+ error("ulimit: bad limit: %s", strerror(errno));
} else {
if (how & SOFT)
val = limit.rlim_cur;
else if (how & HARD)
val = limit.rlim_max;
- }
- if (!set) {
if (val == RLIM_INFINITY)
out1fmt("unlimited\n");
else
diff --git a/bin/sh/mkinit.c b/bin/sh/mkinit.c
index 6afe601..d27a251 100644
--- a/bin/sh/mkinit.c
+++ b/bin/sh/mkinit.c
@@ -33,17 +33,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mkinit.c,v 1.5 1995/10/01 15:13:31 joerg Exp $
+ * $Id: mkinit.c,v 1.6 1996/09/01 10:20:50 peter Exp $
*/
#ifndef lint
-static char copyright[] =
+static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
@@ -68,8 +68,7 @@ static char sccsid[] = "@(#)mkinit.c 8.2 (Berkeley) 5/4/95";
/*
* OUTFILE is the name of the output file. Output is initially written
- * to the file OUTTEMP, which is then moved to OUTFILE if OUTTEMP and
- * OUTFILE are different.
+ * to the file OUTTEMP, which is then moved to OUTFILE.
*/
#define OUTFILE "init.c"
@@ -107,7 +106,7 @@ struct event {
char *name; /* name of event (e.g. INIT) */
char *routine; /* name of routine called on event */
char *comment; /* comment describing routine */
- struct text code; /* code for handling event */
+ struct text code; /* code for handling event */
};
@@ -162,8 +161,8 @@ void addchar __P((int, struct text *));
void writetext __P((struct text *, FILE *));
FILE *ckfopen __P((char *, char *));
void *ckmalloc __P((int));
-char *savestr __P((char *));
-void error __P((char *));
+char *savestr __P((char *));
+void error __P((char *));
#define equal(s1, s2) (strcmp(s1, s2) == 0)
@@ -174,16 +173,12 @@ main(argc, argv)
{
char **ap;
- if (argc < 2)
- error("Usage: mkinit file...");
header_files[0] = "\"shell.h\"";
header_files[1] = "\"mystring.h\"";
for (ap = argv + 1 ; *ap ; ap++)
readfile(*ap);
output();
- unlink(OUTFILE);
- link(OUTTEMP, OUTFILE);
- unlink(OUTTEMP);
+ rename(OUTTEMP, OUTFILE);
exit(0);
}
@@ -197,7 +192,7 @@ readfile(fname)
char *fname;
{
FILE *fp;
- char line[1024], line2[1024];
+ char line[1024];
struct event *ep;
fp = ckfopen(fname, "r");
@@ -218,14 +213,16 @@ readfile(fname)
dodecl(line, fp);
if (line[0] == '#' && gooddefine(line)) {
char *cp;
+ char line2[1024];
+ static const char undef[] = "#undef ";
strcpy(line2, line);
- memcpy(line2, "#undef ", strlen("#undef "));
- cp = line2 + strlen("#undef ");
+ memcpy(line2, undef, sizeof(undef) - 1);
+ cp = line2 + sizeof(undef) - 1;
while(*cp && (*cp == ' ' || *cp == '\t'))
- cp++;
+ cp++;
while(*cp && *cp != ' ' && *cp != '\t' && *cp != '\n')
- cp++;
+ cp++;
*cp++ = '\n'; *cp = '\0';
addstr(line2, &defines);
addstr(line, &defines);
@@ -363,7 +360,8 @@ dodecl(line1, fp)
if (! amiddecls)
addchar('\n', &decls);
q = NULL;
- for (p = line1 + 6 ; *p != '\0' && *p != '=' && *p != '/' && *p != '\n'; p++);
+ for (p = line1 + 6 ; *p && strchr("=/\n", *p) == NULL; p++)
+ continue;
if (*p == '=') { /* eliminate initialization */
for (q = p ; *q && *q != ';' ; q++);
if (*q == '\0')
@@ -485,7 +483,7 @@ ckfopen(file, mode)
}
void *
-ckmalloc(nbytes)
+ckmalloc(nbytes)
int nbytes;
{
register char *p;
diff --git a/bin/sh/mknodes.c b/bin/sh/mknodes.c
index f2fcf36..0d7bf32 100644
--- a/bin/sh/mknodes.c
+++ b/bin/sh/mknodes.c
@@ -33,17 +33,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mknodes.c,v 1.3 1996/09/01 10:20:51 peter Exp $
+ * $Id: mknodes.c,v 1.4 1996/09/03 13:35:11 peter Exp $
*/
#ifndef lint
-static char copyright[] =
+static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)mknodes.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
diff --git a/bin/sh/mksyntax.c b/bin/sh/mksyntax.c
index 5b6a30e..48b630b 100644
--- a/bin/sh/mksyntax.c
+++ b/bin/sh/mksyntax.c
@@ -33,17 +33,17 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mksyntax.c,v 1.5 1996/08/12 22:14:47 ache Exp $
+ * $Id: mksyntax.c,v 1.6 1996/09/01 10:20:56 peter Exp $
*/
#ifndef lint
-static char copyright[] =
+static char const copyright[] =
"@(#) Copyright (c) 1991, 1993\n\
The Regents of the University of California. All rights reserved.\n";
#endif /* not lint */
#ifndef lint
-static char sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)mksyntax.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
@@ -151,7 +151,9 @@ main(argc, argv)
if (d == c)
break;
}
+#if 0
printf("%s %d bit chars\n", sign? "signed" : "unsigned", nbits);
+#endif
if (nbits > 9) {
fputs("Characters can't have more than 9 bits\n", stderr);
exit(2);
@@ -166,8 +168,8 @@ main(argc, argv)
digit_contig = 0;
}
- fputs("#include <ctype.h>\n", hfile);
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);
@@ -354,7 +356,7 @@ static char *macro[] = {
};
static void
-output_type_macros()
+output_type_macros()
{
char **pp;
@@ -375,7 +377,7 @@ output_type_macros()
*/
static void
-digit_convert()
+digit_convert()
{
int maxdigit;
static char digit[] = "0123456789";
diff --git a/bin/sh/myhistedit.h b/bin/sh/myhistedit.h
index 3f69381..f0fa314 100644
--- a/bin/sh/myhistedit.h
+++ b/bin/sh/myhistedit.h
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* @(#)myhistedit.h 8.2 (Berkeley) 5/4/95
- * $Id: myhistedit.h,v 1.2 1994/09/24 02:57:59 davidg Exp $
+ * $Id: myhistedit.h,v 1.3 1996/09/01 10:21:00 peter Exp $
*/
#include <histedit.h>
@@ -41,7 +41,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 ab7ea92..317f9a8 100644
--- a/bin/sh/mystring.c
+++ b/bin/sh/mystring.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: mystring.c,v 1.3 1996/09/01 10:21:03 peter Exp $
+ * $Id: mystring.c,v 1.4 1996/09/03 14:15:55 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)mystring.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
diff --git a/bin/sh/options.c b/bin/sh/options.c
index 627c20c..26c62b5 100644
--- a/bin/sh/options.c
+++ b/bin/sh/options.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: options.c,v 1.7 1996/09/01 10:21:16 peter Exp $
+ * $Id: options.c,v 1.8 1996/10/29 03:12:48 steve Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)options.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
#include <signal.h>
@@ -74,6 +74,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 **));
/*
@@ -108,8 +109,8 @@ procargs(argc, argv)
commandname = arg0 = *argptr++;
setinputfile(commandname, 0);
}
+ /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
if (*argptr && minusc)
- /* Posix.2: first arg after -c cmd is $0, remainder $1... */
arg0 = *argptr++;
shellparam.p = argptr;
/* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
@@ -137,7 +138,7 @@ optschanged()
*/
STATIC void
-options(cmdline)
+options(cmdline)
int cmdline;
{
register char *p;
@@ -312,7 +313,7 @@ freeparam(param)
int
shiftcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
int n;
char **ap1, **ap2;
@@ -344,7 +345,7 @@ shiftcmd(argc, argv)
int
setcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
if (argc == 1)
return showvarscmd(argc, argv);
@@ -359,6 +360,16 @@ setcmd(argc, argv)
}
+void
+getoptsreset(value)
+ const char *value;
+{
+ if (number(value) == 1) {
+ shellparam.optnext = NULL;
+ shellparam.reset = 1;
+ }
+}
+
/*
* The getopts builtin. Shellparam.optnext points to the next argument
* to be processed. Shellparam.optptr points to the next character to
@@ -369,56 +380,122 @@ setcmd(argc, argv)
int
getoptscmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
- register char *p, *q;
- char c;
- char s[10];
+ char **optbase = NULL;
- if (argc != 3)
- error("Usage: getopts optstring var");
- if (shellparam.optnext == NULL) {
- shellparam.optnext = shellparam.p;
+ if (argc < 3)
+ error("Usage: getopts optstring var [arg]");
+ else if (argc == 3)
+ optbase = shellparam.p;
+ else
+ optbase = &argv[3];
+
+ if (shellparam.reset == 1) {
+ shellparam.optnext = optbase;
shellparam.optptr = NULL;
+ shellparam.reset = 0;
}
- 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 */
+ if (*optnext == NULL)
+ return 1;
+ 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 = '?';
+ }
+ goto bad;
}
- setvar("OPTARG", p, 0);
+
+ if (p == **optnext)
+ (*optnext)++;
+ setvarsafe("OPTARG", p, 0);
p = NULL;
}
+ else
+ setvarsafe("OPTARG", "", 0);
+ ind = *optnext - optfirst + 1;
+ 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 140c926..abd0514 100644
--- a/bin/sh/options.h
+++ b/bin/sh/options.h
@@ -34,15 +34,16 @@
* SUCH DAMAGE.
*
* @(#)options.h 8.2 (Berkeley) 5/4/95
- * $Id: options.h,v 1.3 1996/09/01 10:21:20 peter Exp $
+ * $Id: options.h,v 1.4 1996/10/29 03:12:49 steve Exp $
*/
struct shparam {
- int nparam; /* number of positional parameters (without $0) */
- char malloc; /* true if parameter list dynamicly allocated */
+ int nparam; /* # of positional parameters (without $0) */
+ unsigned char malloc; /* if parameter list dynamically allocated */
+ unsigned char reset; /* if getopts has been reset */
char **p; /* parameter list */
- char **optnext; /* next parameter to be processed by getopts */
- char *optptr; /* used by getopts */
+ char **optnext; /* next parameter to be processed by getopts */
+ char *optptr; /* used by getopts */
};
@@ -103,11 +104,12 @@ extern char **argptr; /* argument list for builtin commands */
extern char *optarg; /* set by nextopt */
extern char *optptr; /* used by nextopt */
-void procargs __P((int, char **));
+void procargs __P((int, char **));
void optschanged __P((void));
void setparam __P((char **));
-void freeparam __P((struct shparam *));
+void freeparam __P((struct shparam *));
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 cc0e84d..0575b36 100644
--- a/bin/sh/output.c
+++ b/bin/sh/output.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: output.c,v 1.3 1996/09/01 10:21:23 peter Exp $
+ * $Id: output.c,v 1.4 1996/09/03 14:15:56 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
/*
@@ -51,8 +51,8 @@ static char sccsid[] = "@(#)output.c 8.2 (Berkeley) 5/4/95";
* Our output routines may be smaller than the stdio routines.
*/
+#include <sys/types.h> /* quad_t */
#include <sys/ioctl.h>
-#include <sys/types.h> /* quad_t */
#include <stdio.h> /* defines BUFSIZ */
#include <string.h>
@@ -338,7 +338,7 @@ fmtstr(va_alist)
* Formatted output. This routine handles a subset of the printf formats:
* - Formats supported: d, u, o, X, s, and c.
* - The x format is also accepted but is treated like X.
- * - The l and q modifiers is accepted.
+ * - The l and q modifiers are accepted.
* - The - and # flags are accepted; # only works with the o format.
* - Width and precision may be specified with any format except c.
* - An * may be given for the width or precision.
@@ -349,11 +349,7 @@ fmtstr(va_alist)
#define TEMPSIZE 24
-#ifdef __STDC__
static const char digit[] = "0123456789ABCDEF";
-#else
-static const char digit[17] = "0123456789ABCDEF";
-#endif
void
@@ -427,10 +423,10 @@ doformat(dest, f, ap)
}
switch (*f) {
case 'd':
- if (islong)
- l = va_arg(ap, long);
- else if (isquad)
+ if (isquad)
l = va_arg(ap, quad_t);
+ else if (islong)
+ l = va_arg(ap, long);
else
l = va_arg(ap, int);
sign = 0;
@@ -453,10 +449,10 @@ doformat(dest, f, ap)
base = 16;
uns_number: /* an unsigned number */
sign = 0;
- if (islong)
- num = va_arg(ap, unsigned long);
- else if (isquad)
+ if (isquad)
num = va_arg(ap, u_quad_t);
+ else if (islong)
+ num = va_arg(ap, unsigned long);
else
num = va_arg(ap, unsigned int);
number: /* process a number */
@@ -565,7 +561,7 @@ xwrite(fd, buf, nbytes)
*/
int
-xioctl(fd, request, arg)
+xioctl(fd, request, arg)
int fd;
unsigned long request;
char * arg;
diff --git a/bin/sh/output.h b/bin/sh/output.h
index 92e03b9..7a1957d 100644
--- a/bin/sh/output.h
+++ b/bin/sh/output.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)output.h 8.2 (Berkeley) 5/4/95
- * $Id: output.h,v 1.2 1994/09/24 02:58:08 davidg Exp $
+ * $Id: output.h,v 1.3 1996/09/01 10:21:29 peter Exp $
*/
#ifndef OUTPUT_INCL
@@ -69,7 +69,7 @@ void flushall __P((void));
void flushout __P((struct output *));
void freestdout __P((void));
void outfmt __P((struct output *, char *, ...));
-void out1fmt __P((char *, ...));
+void out1fmt __P((char *, ...));
void dprintf __P((char *, ...));
void fmtstr __P((char *, int, char *, ...));
void doformat __P((struct output *, char *, va_list));
diff --git a/bin/sh/parser.c b/bin/sh/parser.c
index 1874531..e400b45 100644
--- a/bin/sh/parser.c
+++ b/bin/sh/parser.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id$
+ * $Id: parser.c,v 1.16 1996/09/10 02:42:33 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
+static char const sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
#endif /* not lint */
#include <stdlib.h>
@@ -120,7 +120,7 @@ STATIC int readtoken1 __P((int, char const *, char *, int));
STATIC int noexpand __P((char *));
STATIC void synexpect __P((int));
STATIC void synerror __P((char *));
-STATIC void setprompt __P((int));
+STATIC void setprompt __P((int));
/*
@@ -129,7 +129,7 @@ STATIC void setprompt __P((int));
*/
union node *
-parsecmd(interact)
+parsecmd(interact)
int interact;
{
int t;
@@ -151,7 +151,7 @@ parsecmd(interact)
STATIC union node *
-list(nlflag)
+list(nlflag)
int nlflag;
{
union node *n1, *n2, *n3;
@@ -249,16 +249,10 @@ andor() {
STATIC union node *
pipeline() {
- union node *n1, *pipenode, *notnode;
+ union node *n1, *pipenode;
struct nodelist *lp, *prev;
- int negate = 0;
TRACE(("pipeline: entered\n"));
- while (readtoken() == TNOT) {
- TRACE(("pipeline: TNOT recognized\n"));
- negate = !negate;
- }
- tokpushback++;
n1 = command();
if (readtoken() == TPIPE) {
pipenode = (union node *)stalloc(sizeof (struct npipe));
@@ -277,12 +271,6 @@ pipeline() {
n1 = pipenode;
}
tokpushback++;
- if (negate) {
- notnode = (union node *)stalloc(sizeof (struct nnot));
- notnode->type = NNOT;
- notnode->nnot.com = n1;
- n1 = notnode;
- }
return n1;
}
@@ -294,12 +282,13 @@ command() {
union node *ap, **app;
union node *cp, **cpp;
union node *redir, **rpp;
- int t;
+ int t, negate = 0;
checkkwd = 2;
redir = NULL;
n1 = NULL;
rpp = &redir;
+
/* Check for redirection which may precede command */
while (readtoken() == TREDIR) {
*rpp = n2 = redirnode;
@@ -308,6 +297,12 @@ command() {
}
tokpushback++;
+ while (readtoken() == TNOT) {
+ TRACE(("command: TNOT recognized\n"));
+ negate = !negate;
+ }
+ tokpushback++;
+
switch (readtoken()) {
case TIF:
n1 = (union node *)stalloc(sizeof (struct nif));
@@ -473,14 +468,15 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
*/
if (!redir)
synexpect(-1);
- case TAND: /* XXX merge query! */
- case TOR: /* XXX merge query! */
+ case TAND:
+ case TOR:
case TNL:
case TEOF:
case TWORD:
case TRP:
tokpushback++;
- return simplecmd(rpp, redir);
+ n1 = simplecmd(rpp, redir);
+ goto checkneg;
default:
synexpect(-1);
}
@@ -502,7 +498,16 @@ TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
}
n1->nredir.redirect = redir;
}
- return n1;
+
+checkneg:
+ if (negate) {
+ n2 = (union node *)stalloc(sizeof (struct nnot));
+ n2->type = NNOT;
+ n2->nnot.com = n1;
+ return n2;
+ }
+ else
+ return n1;
}
@@ -512,7 +517,8 @@ simplecmd(rpp, redir)
{
union node *args, **app;
union node **orig_rpp = rpp;
- union node *n = NULL;
+ union node *n = NULL, *n2;
+ int negate = 0;
/* If we don't have any redirections already, then we must reset */
/* rpp to be the address of the local redir variable. */
@@ -528,6 +534,12 @@ simplecmd(rpp, redir)
*/
orig_rpp = rpp;
+ while (readtoken() == TNOT) {
+ TRACE(("command: TNOT recognized\n"));
+ negate = !negate;
+ }
+ tokpushback++;
+
for (;;) {
if (readtoken() == TWORD) {
n = (union node *)stalloc(sizeof (struct narg));
@@ -551,7 +563,7 @@ simplecmd(rpp, redir)
#endif
n->type = NDEFUN;
n->narg.next = command();
- return n;
+ goto checkneg;
} else {
tokpushback++;
break;
@@ -564,7 +576,16 @@ simplecmd(rpp, redir)
n->ncmd.backgnd = 0;
n->ncmd.args = args;
n->ncmd.redirect = redir;
- return n;
+
+checkneg:
+ if (negate) {
+ n2 = (union node *)stalloc(sizeof (struct nnot));
+ n2->type = NNOT;
+ n2->nnot.com = n;
+ return n2;
+ }
+ else
+ return n;
}
STATIC union node *
@@ -593,7 +614,7 @@ void fixredir(n, text, err)
else if (text[0] == '-' && text[1] == '\0')
n->ndup.dupfd = -1;
else {
-
+
if (err)
synerror("Bad fd number");
else
@@ -704,12 +725,12 @@ readtoken() {
/*
* check for keywords and aliases
*/
- if (t == TWORD && !quoteflag)
+ if (t == TWORD && !quoteflag)
{
register char * const *pp;
for (pp = (char **)parsekwd; *pp; pp++) {
- if (**pp == *wordtext && equal(*pp, wordtext))
+ if (**pp == *wordtext && equal(*pp, wordtext))
{
lasttoken = t = pp - parsekwd + KWDOFFSET;
TRACE(("keyword %s recognized\n", tokname[t]));
@@ -724,7 +745,7 @@ readtoken() {
}
}
out:
- checkkwd = 0;
+ checkkwd = (t == TNOT) ? savecheckkwd : 0;
}
#ifdef DEBUG
if (!alreadyseen)
@@ -1207,7 +1228,7 @@ badsub: synerror("Bad substitution");
subtype = p - types + VSNORMAL;
break;
case '%':
- case '#':
+ case '#':
{
int cc = c;
subtype = c == '#' ? VSTRIMLEFT :
@@ -1248,6 +1269,11 @@ parsebackq: {
struct jmploc jmploc;
struct jmploc *volatile savehandler;
int savelen;
+ int saveprompt;
+#if __GNUC__
+ /* Avoid longjmp clobbering */
+ (void) &saveprompt;
+#endif
savepbq = parsebackquote;
if (setjmp(jmploc.loc)) {
@@ -1276,20 +1302,53 @@ parsebackq: {
int savelen;
char *str;
+
STARTSTACKSTR(out);
- while ((c = pgetc ()) != '`') {
- if (c == PEOF) {
- startlinno = plinno;
- synerror("EOF in backquote substitution");
- }
- if (c == '\\') {
- c = pgetc ();
+ for (;;) {
+ if (needprompt) {
+ setprompt(2);
+ needprompt = 0;
+ }
+ switch (c = pgetc()) {
+ case '`':
+ goto done;
+
+ case '\\':
+ if ((c = pgetc()) == '\n') {
+ plinno++;
+ if (doprompt)
+ setprompt(2);
+ else
+ setprompt(0);
+ /*
+ * If eating a newline, avoid putting
+ * the newline into the new character
+ * stream (via the STPUTC after the
+ * switch).
+ */
+ continue;
+ }
if (c != '\\' && c != '`' && c != '$'
&& (!dblquote || c != '"'))
STPUTC('\\', out);
- }
- STPUTC(c, out);
+ break;
+
+ case '\n':
+ plinno++;
+ needprompt = doprompt;
+ break;
+
+ case PEOF:
+ startlinno = plinno;
+ synerror("EOF in backquote substitution");
+ break;
+
+ default:
+ break;
+ }
+ STPUTC(c, out);
}
+done:
STPUTC('\0', out);
savelen = out - stackblock();
if (savelen > 0) {
@@ -1304,13 +1363,30 @@ parsebackq: {
*nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
(*nlpp)->next = NULL;
parsebackquote = oldstyle;
+
+ if (oldstyle) {
+ saveprompt = doprompt;
+ doprompt = 0;
+ }
+
n = list(0);
- if (!oldstyle && (readtoken() != TRP))
- synexpect(TRP);
+
+ if (oldstyle)
+ doprompt = saveprompt;
+ else {
+ if (readtoken() != TRP)
+ synexpect(TRP);
+ }
+
(*nlpp)->n = n;
- /* Start reading from old file again. */
- if (oldstyle)
+ if (oldstyle) {
+ /*
+ * Start reading from old file again, ignoring any pushed back
+ * tokens left from the backquote parsing
+ */
popfile();
+ tokpushback = 0;
+ }
while (stackblocksize() <= savelen)
growstackblock();
STARTSTACKSTR(out);
@@ -1416,7 +1492,7 @@ goodname(name)
*/
STATIC void
-synexpect(token)
+synexpect(token)
int token;
{
char msg[64];
diff --git a/bin/sh/parser.h b/bin/sh/parser.h
index 4bc1e9e..4280d58 100644
--- a/bin/sh/parser.h
+++ b/bin/sh/parser.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)parser.h 8.3 (Berkeley) 5/4/95
- * $Id: parser.h,v 1.2 1994/09/24 02:58:09 davidg Exp $
+ * $Id: parser.h,v 1.3 1996/09/01 10:21:34 peter Exp $
*/
/* control characters in argument strings */
@@ -78,4 +78,4 @@ extern int whichprompt; /* 1 == PS1, 2 == PS2 */
union node *parsecmd __P((int));
void fixredir __P((union node *, const char *, int));
int goodname __P((char *));
-char *getprompt __P((void *));
+char *getprompt __P((void *));
diff --git a/bin/sh/redir.c b/bin/sh/redir.c
index ae2d335..89e68d3 100644
--- a/bin/sh/redir.c
+++ b/bin/sh/redir.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: redir.c,v 1.4 1995/10/21 00:47:31 joerg Exp $
+ * $Id: redir.c,v 1.5 1996/09/01 10:21:36 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)redir.c 8.2 (Berkeley) 5/4/95";
#endif /* not lint */
#include <sys/types.h>
@@ -103,7 +103,7 @@ redirect(redir, flags)
struct redirtab *sv = NULL;
int i;
int fd;
- char memory[10]; /* file descriptors to write to memory */
+ char memory[10]; /* file descriptors to write to memory */
for (i = 10 ; --i >= 0 ; )
memory[i] = 0;
@@ -119,7 +119,7 @@ redirect(redir, flags)
fd = n->nfile.fd;
if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
n->ndup.dupfd == fd)
- continue; /* redirect from/to myself */
+ continue; /* redirect from/to same file descriptor */
if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
INTOFF;
if ((i = copyfd(fd, 10)) != EMPTY) {
@@ -335,16 +335,18 @@ clearredir() {
*/
int
-copyfd(from, to)
+copyfd(from, to)
int from;
int to;
{
int newfd;
newfd = fcntl(from, F_DUPFD, to);
- if (newfd < 0 && errno == EMFILE)
- return EMPTY;
- if (newfd < 0)
- error("%d: %s", from, strerror(errno));
+ if (newfd < 0) {
+ if (errno == EMFILE)
+ return EMPTY;
+ else
+ error("%d: %s", from, strerror(errno));
+ }
return newfd;
}
diff --git a/bin/sh/redir.h b/bin/sh/redir.h
index 14acdb6..e6bafda 100644
--- a/bin/sh/redir.h
+++ b/bin/sh/redir.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)redir.h 8.2 (Berkeley) 5/4/95
- * $Id: redir.h,v 1.2 1994/09/24 02:58:11 davidg Exp $
+ * $Id: redir.h,v 1.3 1996/09/01 10:21:37 peter Exp $
*/
/* flags passed to redirect */
@@ -45,6 +45,6 @@ union node;
void redirect __P((union node *, int));
void popredir __P((void));
int fd0_redirected_p __P((void));
-void clearredir __P((void));
+void clearredir __P((void));
int copyfd __P((int, int));
diff --git a/bin/sh/sh.1 b/bin/sh/sh.1
index 3a3843e..265b38a 100644
--- a/bin/sh/sh.1
+++ b/bin/sh/sh.1
@@ -33,7 +33,7 @@
.\" SUCH DAMAGE.
.\"
.\" @(#)sh.1 8.6 (Berkeley) 5/4/95
-.\" $Id: sh.1,v 1.8 1996/09/03 14:15:59 peter Exp $
+.\" $Id: sh.1,v 1.9 1996/10/29 03:12:51 steve Exp $
.\"
.na
.TH SH 1
@@ -200,11 +200,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
@@ -250,7 +250,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
@@ -355,33 +356,33 @@ previously. Following is a list of the possible redirections.
The [n] is an optional number, as in '3' (not '[3]'), that
refers to a file descriptor.
.TP
-[n]> file
+[n]> file
Redirect standard output (or n) to file.
.TP
-[n]>| file
+[n]>| file
Same, but override the -C option.
.TP
-[n]>> file
+[n]>> file
Append standard output (or n) to file.
.TP
-[n]< file
+[n]< file
Redirect standard input (or n) from file.
.TP
-[n1]<&n2
+[n1]<&n2
Duplicate standard input (or n1) from
file descriptor n2.
.TP
-[n]<&-
+[n]<&-
Close standard input (or n).
.TP
-[n1]>&n2
+[n1]>&n2
Duplicate standard output (or n) from
n2.
.TP
-[n]>&-
+[n]>&-
Close standard output (or n).
.TP
-[n]<> file
+[n]<> file
Open file for reading and writing on
standard input (or n).
.LP
@@ -406,11 +407,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,
+builtin 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
@@ -418,37 +421,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
@@ -459,7 +474,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
@@ -484,13 +499,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
@@ -530,6 +546,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
@@ -560,6 +582,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
@@ -567,6 +592,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
@@ -587,7 +615,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
@@ -610,7 +640,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
@@ -624,7 +655,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
@@ -639,6 +672,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
@@ -799,7 +843,7 @@ The $ character is used to introduce parameter expansion, command
substitution, or arithmetic evaluation.
.sp 2
.B Tilde Expansion (substituting a user's home directory)
-.sp
+.sp
.LP
A word beginning with an unquoted tilde character (~) is
subjected to tilde expansion. All the characters up to
@@ -889,13 +933,13 @@ 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
+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,
whereas quoting characters within the braces has this effect.
-(UNIMPLEMENTED IN 4.4alpha)
.TP
${parameter%word}
Remove Smallest Suffix Pattern. The word
@@ -903,7 +947,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
@@ -991,12 +1034,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
@@ -1037,8 +1082,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
@@ -1060,8 +1105,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 builtin command. (This is useful when you
+have a shell function with the same name
as a builtin command.)
.TP
cd [ directory ]
@@ -1071,7 +1116,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
@@ -1085,7 +1131,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
@@ -1183,6 +1230,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
@@ -1192,8 +1247,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
@@ -1261,7 +1316,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
@@ -1341,8 +1397,8 @@ The maximal amount of CPU time to be used by each process, in seconds.
.RE
.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]
diff --git a/bin/sh/shell.h b/bin/sh/shell.h
index 043952d..8416a79 100644
--- a/bin/sh/shell.h
+++ b/bin/sh/shell.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)shell.h 8.2 (Berkeley) 5/4/95
- * $Id: shell.h,v 1.5 1996/09/01 10:27:44 peter Exp $
+ * $Id: shell.h,v 1.6 1996/10/31 07:15:57 ache Exp $
*/
/*
@@ -79,7 +79,7 @@ extern char nullstr[1]; /* null string */
#ifdef DEBUG
-#define TRACE(param) shtrace param
+#define TRACE(param) trace param
#else
#define TRACE(param)
#endif
diff --git a/bin/sh/show.c b/bin/sh/show.c
index 4f5d546..ab05404 100644
--- a/bin/sh/show.c
+++ b/bin/sh/show.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: show.c,v 1.3 1996/09/01 10:21:43 peter Exp $
+ * $Id: show.c,v 1.4 1996/09/03 14:16:00 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)show.c 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include <stdio.h>
@@ -269,8 +269,6 @@ indent(amount, pfx, fp)
putc('\t', fp);
}
}
-#endif
-
/*
@@ -288,27 +286,25 @@ int debug = 0;
void
-trputc(c)
+trputc(c)
int c;
{
-#ifdef DEBUG
if (tracefile == NULL)
return;
putc(c, tracefile);
if (c == '\n')
fflush(tracefile);
-#endif
}
+
void
#if __STDC__
-shtrace(const char *fmt, ...)
+trace(const char *fmt, ...)
#else
-shtrace(va_alist)
+trace(va_alist)
va_dcl
#endif
{
-#ifdef DEBUG
va_list va;
#if __STDC__
va_start(va, fmt);
@@ -323,7 +319,6 @@ shtrace(va_alist)
(void) fflush(tracefile);
}
va_end(va);
-#endif
}
@@ -331,17 +326,14 @@ void
trputs(s)
char *s;
{
-#ifdef DEBUG
if (tracefile == NULL)
return;
fputs(s, tracefile);
if (strchr(s, '\n'))
fflush(tracefile);
-#endif
}
-#ifdef DEBUG
static void
trstring(s)
char *s;
@@ -381,14 +373,12 @@ backslash: putc('\\', tracefile);
}
putc('"', tracefile);
}
-#endif
void
trargs(ap)
char **ap;
{
-#ifdef DEBUG
if (tracefile == NULL)
return;
while (*ap) {
@@ -399,13 +389,11 @@ trargs(ap)
putc('\n', tracefile);
}
fflush(tracefile);
-#endif
}
void
opentrace() {
-#ifdef DEBUG
char s[100];
char *getenv();
#ifdef O_APPEND
@@ -439,5 +427,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 18ffcb6..3625240 100644
--- a/bin/sh/show.h
+++ b/bin/sh/show.h
@@ -31,12 +31,14 @@
* SUCH DAMAGE.
*
* @(#)show.h 1.1 (Berkeley) 5/4/95
- * $Id$
+ * $Id: show.h,v 1.2 1996/09/01 10:21:45 peter Exp $
*/
void showtree __P((union node *));
+#ifdef DEBUG
void trputc __P((int));
-void shtrace __P((const char *, ...));
+void trace __P((const char *, ...));
void trputs __P((char *));
void trargs __P((char **));
void opentrace __P((void));
+#endif
diff --git a/bin/sh/trap.c b/bin/sh/trap.c
index ec905d7..5b99d42 100644
--- a/bin/sh/trap.c
+++ b/bin/sh/trap.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: trap.c,v 1.3 1995/05/30 00:07:23 rgrimes Exp $
+ * $Id: trap.c,v 1.4 1996/09/01 10:21:47 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
+static char const sccsid[] = "@(#)trap.c 8.5 (Berkeley) 6/5/95";
#endif /* not lint */
#include <signal.h>
@@ -88,7 +88,7 @@ static int getsigaction __P((int, sig_t *));
int
trapcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char *action;
char **ap;
@@ -153,7 +153,7 @@ clear_traps() {
*/
long
-setsignal(signo)
+setsignal(signo)
int signo;
{
int action;
@@ -235,7 +235,7 @@ setsignal(signo)
* Return the current setting for sig w/o changing it.
*/
static int
-getsigaction(signo, sigact)
+getsigaction(signo, sigact)
int signo;
sig_t *sigact;
{
@@ -252,7 +252,7 @@ getsigaction(signo, sigact)
*/
void
-ignoresig(signo)
+ignoresig(signo)
int signo;
{
if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
@@ -284,7 +284,7 @@ SHELLPROC {
*/
void
-onsig(signo)
+onsig(signo)
int signo;
{
signal(signo, onsig);
@@ -335,7 +335,7 @@ void
setinteractive(on)
int on;
{
- static int is_interactive;
+ static int is_interactive = 0;
if (on == is_interactive)
return;
@@ -352,7 +352,7 @@ setinteractive(on)
*/
void
-exitshell(status)
+exitshell(status)
int status;
{
struct jmploc loc1, loc2;
diff --git a/bin/sh/trap.h b/bin/sh/trap.h
index f63af1a..e57b6f2 100644
--- a/bin/sh/trap.h
+++ b/bin/sh/trap.h
@@ -34,16 +34,16 @@
* SUCH DAMAGE.
*
* @(#)trap.h 8.3 (Berkeley) 6/5/95
- * $Id: trap.h,v 1.2 1994/09/24 02:58:20 davidg Exp $
+ * $Id: trap.h,v 1.3 1996/09/01 10:21:50 peter Exp $
*/
extern int pendingsigs;
int trapcmd __P((int, char **));
-void clear_traps __P((void));
-long setsignal __P((int));
+void clear_traps __P((void));
+long setsignal __P((int));
void ignoresig __P((int));
void onsig __P((int));
void dotrap __P((void));
void setinteractive __P((int));
-void exitshell __P((int));
+void exitshell __P((int));
diff --git a/bin/sh/var.c b/bin/sh/var.c
index 14de566..8b06645 100644
--- a/bin/sh/var.c
+++ b/bin/sh/var.c
@@ -33,11 +33,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: var.c,v 1.5 1996/08/12 22:14:50 ache Exp $
+ * $Id: var.c,v 1.6 1996/09/01 10:21:52 peter Exp $
*/
#ifndef lint
-static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
+static char const sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
#endif /* not lint */
#include <unistd.h>
@@ -58,11 +58,11 @@ static char sccsid[] = "@(#)var.c 8.3 (Berkeley) 5/4/95";
#include "syntax.h"
#include "options.h"
#include "mail.h"
-#include "parser.h"
#include "var.h"
#include "memalloc.h"
#include "error.h"
#include "mystring.h"
+#include "parser.h"
#ifndef NO_HISTORY
#include "myhistedit.h"
#endif
@@ -75,6 +75,7 @@ struct varinit {
struct var *var;
int flags;
char *text;
+ void (*func) __P((const char *));
};
@@ -94,31 +95,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 *));
STATIC int localevar __P((char *));
@@ -161,6 +173,7 @@ initvar() {
*vpp = vp;
vp->text = ip->text;
vp->flags = ip->flags;
+ vp->func = ip->func;
}
}
/*
@@ -176,6 +189,33 @@ 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 __GNUC__
+ /* Avoid longjmp clobbering */
+ (void) &err;
+#endif
+
+ 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.
*/
@@ -264,23 +304,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
if ((vp->flags & VEXPORT) && localevar(s)) {
putenv(s);
(void) setlocale(LC_ALL, "");
@@ -294,6 +338,7 @@ setvareq(s, flags)
vp->flags = flags;
vp->text = s;
vp->next = *vpp;
+ vp->func = NULL;
INTOFF;
*vpp = vp;
if ((vp->flags & VEXPORT) && localevar(s)) {
@@ -456,7 +501,7 @@ shprocvar() {
int
showvarscmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct var **vpp;
struct var *vp;
@@ -479,7 +524,7 @@ showvarscmd(argc, argv)
int
exportcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
struct var **vpp;
struct var *vp;
@@ -530,7 +575,7 @@ found:;
int
localcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char *name;
@@ -621,7 +666,7 @@ poplocalvars() {
int
setvarcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
if (argc <= 2)
return unsetcmd(argc, argv);
@@ -642,7 +687,7 @@ setvarcmd(argc, argv)
int
unsetcmd(argc, argv)
int argc;
- char **argv;
+ char **argv;
{
char **ap;
int i;
@@ -673,7 +718,7 @@ unsetcmd(argc, argv)
* Unset the specified variable.
*/
-STATIC int
+int
unsetvar(s)
char *s;
{
@@ -692,7 +737,7 @@ unsetvar(s)
unsetenv(s);
setlocale(LC_ALL, "");
}
- vp->flags &=~ VEXPORT;
+ vp->flags &= ~VEXPORT;
vp->flags |= VUNSET;
if ((vp->flags & VSTRFIXED) == 0) {
if ((vp->flags & VTEXTFIXED) == 0)
@@ -720,9 +765,9 @@ hashvar(p)
{
unsigned int hashval;
- hashval = ((unsigned char)*p) << 4;
+ hashval = ((unsigned char) *p) << 4;
while (*p && *p != '=')
- hashval += (unsigned char)*p++;
+ hashval += (unsigned char) *p++;
return &vartab[hashval % VTABSIZE];
}
diff --git a/bin/sh/var.h b/bin/sh/var.h
index c07b22e..3207dc4 100644
--- a/bin/sh/var.h
+++ b/bin/sh/var.h
@@ -34,7 +34,7 @@
* SUCH DAMAGE.
*
* @(#)var.h 8.2 (Berkeley) 5/4/95
- * $Id: var.h,v 1.2 1994/09/24 02:58:23 davidg Exp $
+ * $Id: var.h,v 1.3 1996/09/01 10:21:54 peter Exp $
*/
/*
@@ -42,26 +42,30 @@
*/
/* 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 */
+ 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 */
};
struct localvar {
- struct localvar *next; /* next local variable in list */
- struct var *vp; /* the variable that was made local */
- int flags; /* saved flags */
- char *text; /* saved text */
+ struct localvar *next; /* next local variable in list */
+ struct var *vp; /* the variable that was made local */
+ int flags; /* saved flags */
+ char *text; /* saved text */
};
@@ -79,6 +83,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.
@@ -95,6 +102,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)
@@ -105,7 +116,7 @@ void initvar __P((void));
void setvar __P((char *, char *, int));
void setvareq __P((char *, int));
struct strlist;
-void listsetvar __P((struct strlist *));
+void listsetvar __P((struct strlist *));
char *lookupvar __P((char *));
char *bltinlookup __P((char *, int));
char **environment __P((void));
@@ -113,7 +124,9 @@ void shprocvar __P((void));
int showvarscmd __P((int, char **));
int exportcmd __P((int, char **));
int localcmd __P((int, char **));
-void mklocal __P((char *));
+void mklocal __P((char *));
void poplocalvars __P((void));
int setvarcmd __P((int, char **));
int unsetcmd __P((int, char **));
+int unsetvar __P((char *));
+int setvarsafe __P((char *, char *, int));
OpenPOWER on IntegriCloud