summaryrefslogtreecommitdiff
path: root/bin/ksh/exec.c
diff options
context:
space:
mode:
authorhubertf <hubertf@NetBSD.org>1999-10-20 15:09:58 +0000
committerhubertf <hubertf@NetBSD.org>1999-10-20 15:09:58 +0000
commit48ee8d1290e7e71a30fbdb4dc2d5c33252ce2160 (patch)
treeb66c212567ed912e7e28094e2e597276e8781ae6 /bin/ksh/exec.c
parentb4e3ec7f3d912c8a8a8a339c0b5f001f543441e1 (diff)
resolve conflicts
Diffstat (limited to 'bin/ksh/exec.c')
-rw-r--r--bin/ksh/exec.c196
1 files changed, 110 insertions, 86 deletions
diff --git a/bin/ksh/exec.c b/bin/ksh/exec.c
index 384b7c35251..d4c2d07e70e 100644
--- a/bin/ksh/exec.c
+++ b/bin/ksh/exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: exec.c,v 1.4 1998/07/28 05:31:25 mycroft Exp $ */
+/* $NetBSD: exec.c,v 1.5 1999/10/20 15:09:59 hubertf Exp $ */
/*
* execute command tree
@@ -21,7 +21,7 @@ static int comexec ARGS((struct op *t, struct tbl *volatile tp, char **ap,
static void scriptexec ARGS((struct op *tp, char **ap));
static int call_builtin ARGS((struct tbl *tp, char **wp));
static int iosetup ARGS((struct ioword *iop, struct tbl *tp));
-static int herein ARGS((char *hname, int sub));
+static int herein ARGS((const char *content, int sub));
#ifdef KSH
static char *do_selectargs ARGS((char **ap, bool_t print_menu));
#endif /* KSH */
@@ -96,7 +96,7 @@ execute(t, flags)
}
*/
if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
- return exchild(t, flags, -1); /* run in sub-process */
+ return exchild(t, flags & ~XTIME, -1); /* run in sub-process */
newenv(E_EXEC);
if (trap)
@@ -104,14 +104,19 @@ execute(t, flags)
if (t->type == TCOM) {
/* Clear subst_exstat before argument expansion. Used by
- * null commands (see comexec()) and by c_set().
+ * null commands (see comexec() and c_eval()) and by c_set().
*/
subst_exstat = 0;
+ current_lineno = t->lineno; /* for $LINENO */
+
/* POSIX says expand command words first, then redirections,
* and assignments last..
*/
ap = eval(t->args, t->u.evalflags | DOBLANK | DOGLOB | DOTILDE);
+ if (flags & XTIME)
+ /* Allow option parsing (bizarre, but POSIX) */
+ timex_hook(t, &ap);
if (Flag(FXTRACE) && ap[0]) {
shf_fprintf(shl_out, "%s",
PS4_SUBSTITUTE(str_val(global("PS4"))));
@@ -123,6 +128,7 @@ execute(t, flags)
if (ap[0])
tp = findcom(ap[0], FC_BI|FC_FUNC);
}
+ flags &= ~XTIME;
if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) {
e->savefd = (short *) alloc(sizeofN(short, NUFILE), ATEMP);
@@ -320,30 +326,20 @@ execute(t, flags)
}
rv = 0; /* in case of a continue */
if (t->type == TFOR) {
- struct tbl *vq;
-
while (*ap != NULL) {
- vq = global(t->str);
- if (vq->flag & RDONLY)
- errorf("%s is read only", t->str);
- setstr(vq, *ap++);
+ setstr(global(t->str), *ap++, KSH_UNWIND_ERROR);
rv = execute(t->left, flags & XERROK);
}
}
#ifdef KSH
else { /* TSELECT */
- struct tbl *vq;
-
for (;;) {
if (!(cp = do_selectargs(ap, is_first))) {
rv = 1;
break;
}
is_first = FALSE;
- vq = global(t->str);
- if (vq->flag & RDONLY)
- errorf("%s is read only", t->str);
- setstr(vq, cp);
+ setstr(global(t->str), cp, KSH_UNWIND_ERROR);
rv = execute(t->left, flags & XERROK);
}
}
@@ -403,7 +399,10 @@ execute(t, flags)
break;
case TTIME:
- rv = timex(t, flags);
+ /* Clear XEXEC so nested execute() call doesn't exit
+ * (allows "ls -l | time grep foo").
+ */
+ rv = timex(t, flags & ~XEXEC);
break;
case TEXEC: /* an eval'd TCOM */
@@ -418,7 +417,8 @@ execute(t, flags)
#endif
restoresigs();
cleanup_proc_env();
- ksh_execve(t->str, t->args, ap);
+ /* XINTACT bit is for OS2 */
+ ksh_execve(t->str, t->args, ap, (flags & XINTACT) ? 1 : 0);
if (errno == ENOEXEC)
scriptexec(t, ap);
else
@@ -429,7 +429,7 @@ execute(t, flags)
quitenv(); /* restores IO */
if ((flags&XEXEC)) {
- exit(rv); /* exit child */
+ unwind(LEXIT); /* exit child */
/* NOTREACHED */
}
if (rv != 0 && !(flags & XERROK)) {
@@ -463,16 +463,20 @@ comexec(t, tp, ap, flags)
(void) &rv;
#endif
+#ifdef KSH
/* snag the last argument for $_ XXX not the same as at&t ksh,
* which only seems to set $_ after a newline (but not in
* functions/dot scripts, but in interactive and scipt) -
* perhaps save last arg here and set it in shell()?.
*/
- if (*(lastp = ap)) {
+ if (Flag(FTALKING) && *(lastp = ap)) {
while (*++lastp)
;
- setstr(typeset("_", LOCAL, 0, 0, 0), *--lastp);
+ /* setstr() can't fail here */
+ setstr(typeset("_", LOCAL, 0, INTEGER, 0), *--lastp,
+ KSH_RETURN_ERROR);
}
+#endif /* KSH */
/* Deal with the shell builtins builtin, exec and command since
* they can be followed by other commands. This must be done before
@@ -632,11 +636,20 @@ comexec(t, tp, ap, flags)
old_kshname = kshname;
if (tp->flag & FKSH)
kshname = ap[0];
+ else
+ ap[0] = (char *) kshname;
e->loc->argv = ap;
for (i = 0; *ap++ != NULL; i++)
;
e->loc->argc = i - 1;
- getopts_reset(1);
+ /* ksh-style functions handle getopts sanely,
+ * bourne/posix functions are insane...
+ */
+ if (tp->flag & FKSH) {
+ e->loc->flags |= BF_DOGETOPTS;
+ e->loc->getopts_state = user_opt;
+ getopts_reset(1);
+ }
old_xflag = Flag(FXTRACE);
Flag(FXTRACE) = tp->flag & TRACE ? TRUE : FALSE;
@@ -703,8 +716,12 @@ comexec(t, tp, ap, flags)
break;
}
+#ifdef KSH
/* set $_ to program's full path */
- setstr(typeset("_", LOCAL|EXPORT, 0, 0, 0), tp->val.s);
+ /* setstr() can't fail here */
+ setstr(typeset("_", LOCAL|EXPORT, 0, INTEGER, 0), tp->val.s,
+ KSH_RETURN_ERROR);
+#endif /* KSH */
if (flags&XEXEC) {
j_exit();
@@ -802,8 +819,14 @@ scriptexec(tp, ap)
if (a1)
*tp->args-- = a1;
# ifdef OS2
- if (a0 != a2 && search_access(a0, X_OK, (int *) 0))
- a0 = a2;
+ if (a0 != a2) {
+ char *tmp_a0 = str_nsave(a0,
+ strlen(a0) + 5, ATEMP);
+ if (search_access(tmp_a0, X_OK,
+ (int *) 0))
+ a0 = a2;
+ afree(tmp_a0, ATEMP);
+ }
# endif /* OS2 */
shell = a0;
}
@@ -832,7 +855,7 @@ scriptexec(tp, ap)
#endif /* SHARPBANG */
*tp->args = shell;
- ksh_execve(tp->args[0], tp->args, ap);
+ ksh_execve(tp->args[0], tp->args, ap, 0);
/* report both the program that was run and the bogus shell */
errorf("%s: %s: %s", tp->str, shell, strerror(errno));
@@ -857,8 +880,8 @@ shcomexec(wp)
struct tbl *
findfunc(name, h, create)
const char *name;
- unsigned int h;
- int create;
+ unsigned int h;
+ int create;
{
struct block *l;
struct tbl *tp = (struct tbl *) 0;
@@ -919,7 +942,7 @@ define(name, t)
tp->val.t = tcopy(t->left, tp->areap);
tp->flag |= (ISSET|ALLOC);
if (t->u.ksh_func)
- tp->flag |= FKSH;
+ tp->flag |= FKSH;
return 0;
}
@@ -1069,7 +1092,7 @@ flushcom(all)
tp->flag &= ~(ALLOC|ISSET);
afree(tp->val.s, APERM);
}
- tp->flag = ~ISSET;
+ tp->flag &= ~ISSET;
}
}
@@ -1089,14 +1112,15 @@ search_access(path, mode, errnop)
ret = eaccess(path, mode);
if (ret < 0)
err = errno; /* File exists, but we can't access it */
- else if (mode == X_OK && (!S_ISREG(statb.st_mode)
- /* This 'cause access() says root can execute everything */
- || !(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
+ else if (mode == X_OK
+ && (!S_ISREG(statb.st_mode)
+ /* This 'cause access() says root can execute everything */
+ || !(statb.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH))))
{
ret = -1;
err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
}
- if (err && errnop)
+ if (err && errnop && !*errnop)
*errnop = err;
return ret;
#else /* !OS2 */
@@ -1161,7 +1185,7 @@ search_access1(path, mode, errnop)
ret = -1;
err = S_ISDIR(statb.st_mode) ? EISDIR : EACCES;
}
- if (err && errnop)
+ if (err && errnop && !*errnop)
*errnop = err;
return ret;
}
@@ -1276,7 +1300,7 @@ iosetup(iop, tp)
struct stat statb;
if (iotype != IOHERE)
- cp = evalonestr(cp, DOTILDE|(Flag(FTALKING) ? DOGLOB : 0));
+ cp = evalonestr(cp, DOTILDE|(Flag(FTALKING_I) ? DOGLOB : 0));
/* Used for tracing and error messages to print expanded cp */
iotmp = *iop;
@@ -1299,6 +1323,9 @@ iosetup(iop, tp)
case IOWRITE:
flags = O_WRONLY | O_CREAT | O_TRUNC;
+ /* The stat() is here to allow redirections to
+ * things like /dev/null without error.
+ */
if (Flag(FNOCLOBBER) && !(iop->flag & IOCLOB)
&& (stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
flags |= O_EXCL;
@@ -1311,7 +1338,7 @@ iosetup(iop, tp)
case IOHERE:
do_open = 0;
/* herein() returns -2 if error has been printed */
- u = herein(cp, iop->flag & IOEVAL);
+ u = herein(iop->heredoc, iop->flag & IOEVAL);
/* cp may have wrong name */
break;
@@ -1399,67 +1426,64 @@ iosetup(iop, tp)
* if unquoted here, expand here temp file into second temp file.
*/
static int
-herein(hname, sub)
- char *hname;
+herein(content, sub)
+ const char *content;
int sub;
{
- int fd;
+ volatile int fd = -1;
+ struct source *s, *volatile osource;
+ struct shf *volatile shf;
+ struct temp *h;
+ int i;
/* ksh -c 'cat << EOF' can cause this... */
- if (hname == (char *) 0) {
+ if (content == (char *) 0) {
warningf(TRUE, "here document missing");
return -2; /* special to iosetup(): don't print error */
}
+
+ /* Create temp file to hold content (done before newenv so temp
+ * doesn't get removed too soon).
+ */
+ h = maketemp(ATEMP, TT_HEREDOC_EXP, &e->temps);
+ if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0) {
+ warningf(TRUE, "can't %s temporary file %s: %s",
+ !shf ? "create" : "open",
+ h->name, strerror(errno));
+ if (shf)
+ shf_close(shf);
+ return -2 /* special to iosetup(): don't print error */;
+ }
+
+ osource = source;
+ newenv(E_ERRH);
+ i = ksh_sigsetjmp(e->jbuf, 0);
+ if (i) {
+ source = osource;
+ quitenv();
+ shf_close(shf); /* after quitenv */
+ close(fd);
+ return -2; /* special to iosetup(): don't print error */
+ }
if (sub) {
- char *cp;
- struct source *s, *volatile osource = source;
- struct temp *h;
- struct shf *volatile shf;
- int i;
-
- /* must be before newenv() 'cause shf uses ATEMP */
- shf = shf_open(hname, O_RDONLY, 0, SHF_MAPHI|SHF_CLEXEC);
- if (shf == NULL)
- return -1;
- newenv(E_ERRH);
- i = ksh_sigsetjmp(e->jbuf, 0);
- if (i) {
- if (shf)
- shf_close(shf);
- source = osource;
- quitenv(); /* after shf_close() due to alloc */
- return -2; /* special to iosetup(): don't print error */
- }
- /* set up yylex input from here file */
- s = pushs(SFILE, ATEMP);
- s->u.shf = shf;
+ /* Do substitutions on the content of heredoc */
+ s = pushs(SSTRING, ATEMP);
+ s->start = s->str = content;
source = s;
if (yylex(ONEWORD) != LWORD)
internal_errorf(1, "herein: yylex");
- shf_close(shf);
- shf = (struct shf *) 0;
- cp = evalstr(yylval.cp, 0);
-
- /* write expanded input to another temp file */
- h = maketemp(ATEMP);
- h->next = e->temps; e->temps = h;
- if (!(shf = h->shf) || (fd = open(h->name, O_RDONLY, 0)) < 0)
- /* shf closeed by error handler */
- errorf("%s: %s", h->name, strerror(errno));
- shf_puts(cp, shf);
- if (shf_close(shf) == EOF) {
- close(fd);
- shf = (struct shf *) 0;
- errorf("error writing %s: %s", h->name,
- strerror(errno));
- }
- shf = (struct shf *) 0;
+ source = osource;
+ shf_puts(evalstr(yylval.cp, 0), shf);
+ } else
+ shf_puts(content, shf);
- quitenv();
- } else {
- fd = open(hname, O_RDONLY, 0);
- if (fd < 0)
- return -1;
+ quitenv();
+
+ if (shf_close(shf) == EOF) {
+ close(fd);
+ warningf(TRUE, "error writing %s: %s", h->name,
+ strerror(errno));
+ return -2; /* special to iosetup(): don't print error */
}
return fd;