summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c577
1 files changed, 283 insertions, 294 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 54fc8ea..69b8ab0 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3664,7 +3664,6 @@ printalias(const struct alias *ap)
#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
#define EV_BACKCMD 04 /* command executing within back quotes */
-
static void evalloop(union node *, int);
static void evalfor(union node *, int);
static void evalcase(union node *, int);
@@ -3677,13 +3676,11 @@ static int evalfun(struct funcnode *, int, char **, int);
static void prehash(union node *);
static int bltincmd(int, char **);
-
static const struct builtincmd bltin = {
"\0\0", bltincmd
};
-
/*
* Evaluate a parse tree. The value is left in the global variable
* exitstatus.
@@ -7277,13 +7274,6 @@ static struct job *curjob;
/* number of presumed living untracked jobs */
static int jobless;
-#if JOBS
-static char *commandtext(union node *);
-static void cmdlist(union node *, int);
-static void cmdtxt(union node *);
-static void cmdputs(const char *);
-#endif
-
static void
set_curjob(struct job *jp, unsigned mode)
{
@@ -7887,10 +7877,8 @@ showjob(FILE *out, struct job *jp, int mode)
col += sizeof("Running") - 1;
} else {
int status = psend[-1].status;
-#if JOBS
if (jp->state == JOBSTOPPED)
status = jp->stopstatus;
-#endif
col += sprint_status(s + col, status, 0);
}
@@ -8143,6 +8131,288 @@ makejob(union node *node, int nprocs)
return jp;
}
+#if JOBS
+/*
+ * Return a string identifying a command (to be printed by the
+ * jobs command).
+ */
+static char *cmdnextc;
+
+static void
+cmdputs(const char *s)
+{
+ const char *p, *str;
+ char c, cc[2] = " ";
+ char *nextc;
+ int subtype = 0;
+ int quoted = 0;
+ static const char vstype[VSTYPE + 1][4] = {
+ "", "}", "-", "+", "?", "=",
+ "%", "%%", "#", "##"
+ };
+
+ nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
+ p = s;
+ while ((c = *p++) != 0) {
+ str = 0;
+ switch (c) {
+ case CTLESC:
+ c = *p++;
+ break;
+ case CTLVAR:
+ subtype = *p++;
+ if ((subtype & VSTYPE) == VSLENGTH)
+ str = "${#";
+ else
+ str = "${";
+ if (!(subtype & VSQUOTE) == !(quoted & 1))
+ goto dostr;
+ quoted ^= 1;
+ c = '"';
+ break;
+ case CTLENDVAR:
+ str = "\"}" + !(quoted & 1);
+ quoted >>= 1;
+ subtype = 0;
+ goto dostr;
+ case CTLBACKQ:
+ str = "$(...)";
+ goto dostr;
+ case CTLBACKQ+CTLQUOTE:
+ str = "\"$(...)\"";
+ goto dostr;
+#if ENABLE_ASH_MATH_SUPPORT
+ case CTLARI:
+ str = "$((";
+ goto dostr;
+ case CTLENDARI:
+ str = "))";
+ goto dostr;
+#endif
+ case CTLQUOTEMARK:
+ quoted ^= 1;
+ c = '"';
+ break;
+ case '=':
+ if (subtype == 0)
+ break;
+ if ((subtype & VSTYPE) != VSNORMAL)
+ quoted <<= 1;
+ str = vstype[subtype & VSTYPE];
+ if (subtype & VSNUL)
+ c = ':';
+ else
+ goto checkstr;
+ break;
+ case '\'':
+ case '\\':
+ case '"':
+ case '$':
+ /* These can only happen inside quotes */
+ cc[0] = c;
+ str = cc;
+ c = '\\';
+ break;
+ default:
+ break;
+ }
+ USTPUTC(c, nextc);
+ checkstr:
+ if (!str)
+ continue;
+ dostr:
+ while ((c = *str++)) {
+ USTPUTC(c, nextc);
+ }
+ }
+ if (quoted & 1) {
+ USTPUTC('"', nextc);
+ }
+ *nextc = 0;
+ cmdnextc = nextc;
+}
+
+/* cmdtxt() and cmdlist() call each other */
+static void cmdtxt(union node *n);
+
+static void
+cmdlist(union node *np, int sep)
+{
+ for (; np; np = np->narg.next) {
+ if (!sep)
+ cmdputs(spcstr);
+ cmdtxt(np);
+ if (sep && np->narg.next)
+ cmdputs(spcstr);
+ }
+}
+
+static void
+cmdtxt(union node *n)
+{
+ union node *np;
+ struct nodelist *lp;
+ const char *p;
+ char s[2];
+
+ if (!n)
+ return;
+ switch (n->type) {
+ default:
+#if DEBUG
+ abort();
+#endif
+ case NPIPE:
+ lp = n->npipe.cmdlist;
+ for (;;) {
+ cmdtxt(lp->n);
+ lp = lp->next;
+ if (!lp)
+ break;
+ cmdputs(" | ");
+ }
+ break;
+ case NSEMI:
+ p = "; ";
+ goto binop;
+ case NAND:
+ p = " && ";
+ goto binop;
+ case NOR:
+ p = " || ";
+ binop:
+ cmdtxt(n->nbinary.ch1);
+ cmdputs(p);
+ n = n->nbinary.ch2;
+ goto donode;
+ case NREDIR:
+ case NBACKGND:
+ n = n->nredir.n;
+ goto donode;
+ case NNOT:
+ cmdputs("!");
+ n = n->nnot.com;
+ donode:
+ cmdtxt(n);
+ break;
+ case NIF:
+ cmdputs("if ");
+ cmdtxt(n->nif.test);
+ cmdputs("; then ");
+ n = n->nif.ifpart;
+ if (n->nif.elsepart) {
+ cmdtxt(n);
+ cmdputs("; else ");
+ n = n->nif.elsepart;
+ }
+ p = "; fi";
+ goto dotail;
+ case NSUBSHELL:
+ cmdputs("(");
+ n = n->nredir.n;
+ p = ")";
+ goto dotail;
+ case NWHILE:
+ p = "while ";
+ goto until;
+ case NUNTIL:
+ p = "until ";
+ until:
+ cmdputs(p);
+ cmdtxt(n->nbinary.ch1);
+ n = n->nbinary.ch2;
+ p = "; done";
+ dodo:
+ cmdputs("; do ");
+ dotail:
+ cmdtxt(n);
+ goto dotail2;
+ case NFOR:
+ cmdputs("for ");
+ cmdputs(n->nfor.var);
+ cmdputs(" in ");
+ cmdlist(n->nfor.args, 1);
+ n = n->nfor.body;
+ p = "; done";
+ goto dodo;
+ case NDEFUN:
+ cmdputs(n->narg.text);
+ p = "() { ... }";
+ goto dotail2;
+ case NCMD:
+ cmdlist(n->ncmd.args, 1);
+ cmdlist(n->ncmd.redirect, 0);
+ break;
+ case NARG:
+ p = n->narg.text;
+ dotail2:
+ cmdputs(p);
+ break;
+ case NHERE:
+ case NXHERE:
+ p = "<<...";
+ goto dotail2;
+ case NCASE:
+ cmdputs("case ");
+ cmdputs(n->ncase.expr->narg.text);
+ cmdputs(" in ");
+ for (np = n->ncase.cases; np; np = np->nclist.next) {
+ cmdtxt(np->nclist.pattern);
+ cmdputs(") ");
+ cmdtxt(np->nclist.body);
+ cmdputs(";; ");
+ }
+ p = "esac";
+ goto dotail2;
+ case NTO:
+ p = ">";
+ goto redir;
+ case NCLOBBER:
+ p = ">|";
+ goto redir;
+ case NAPPEND:
+ p = ">>";
+ goto redir;
+ case NTOFD:
+ p = ">&";
+ goto redir;
+ case NFROM:
+ p = "<";
+ goto redir;
+ case NFROMFD:
+ p = "<&";
+ goto redir;
+ case NFROMTO:
+ p = "<>";
+ redir:
+ s[0] = n->nfile.fd + '0';
+ s[1] = '\0';
+ cmdputs(s);
+ cmdputs(p);
+ if (n->type == NTOFD || n->type == NFROMFD) {
+ s[0] = n->ndup.dupfd + '0';
+ p = s;
+ goto dotail2;
+ }
+ n = n->nfile.fname;
+ goto donode;
+ }
+}
+
+static char *
+commandtext(union node *n)
+{
+ char *name;
+
+ STARTSTACKSTR(cmdnextc);
+ cmdtxt(n);
+ name = stackblock();
+ TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
+ name, cmdnextc, cmdnextc));
+ return ckstrdup(name);
+}
+#endif /* JOBS */
+
/*
* Fork off a subshell. If we are doing job control, give the subshell its
* own process group. Jp is a job structure that the job is to be added to.
@@ -8332,289 +8602,10 @@ stoppedjobs(void)
job_warning = 2;
retval++;
}
-
-out:
+ out:
return retval;
}
-/*
- * Return a string identifying a command (to be printed by the
- * jobs command).
- */
-#if JOBS
-static char *cmdnextc;
-
-static char *
-commandtext(union node *n)
-{
- char *name;
-
- STARTSTACKSTR(cmdnextc);
- cmdtxt(n);
- name = stackblock();
- TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
- name, cmdnextc, cmdnextc));
- return ckstrdup(name);
-}
-
-static void
-cmdtxt(union node *n)
-{
- union node *np;
- struct nodelist *lp;
- const char *p;
- char s[2];
-
- if (!n)
- return;
- switch (n->type) {
- default:
-#if DEBUG
- abort();
-#endif
- case NPIPE:
- lp = n->npipe.cmdlist;
- for (;;) {
- cmdtxt(lp->n);
- lp = lp->next;
- if (!lp)
- break;
- cmdputs(" | ");
- }
- break;
- case NSEMI:
- p = "; ";
- goto binop;
- case NAND:
- p = " && ";
- goto binop;
- case NOR:
- p = " || ";
- binop:
- cmdtxt(n->nbinary.ch1);
- cmdputs(p);
- n = n->nbinary.ch2;
- goto donode;
- case NREDIR:
- case NBACKGND:
- n = n->nredir.n;
- goto donode;
- case NNOT:
- cmdputs("!");
- n = n->nnot.com;
- donode:
- cmdtxt(n);
- break;
- case NIF:
- cmdputs("if ");
- cmdtxt(n->nif.test);
- cmdputs("; then ");
- n = n->nif.ifpart;
- if (n->nif.elsepart) {
- cmdtxt(n);
- cmdputs("; else ");
- n = n->nif.elsepart;
- }
- p = "; fi";
- goto dotail;
- case NSUBSHELL:
- cmdputs("(");
- n = n->nredir.n;
- p = ")";
- goto dotail;
- case NWHILE:
- p = "while ";
- goto until;
- case NUNTIL:
- p = "until ";
- until:
- cmdputs(p);
- cmdtxt(n->nbinary.ch1);
- n = n->nbinary.ch2;
- p = "; done";
- dodo:
- cmdputs("; do ");
- dotail:
- cmdtxt(n);
- goto dotail2;
- case NFOR:
- cmdputs("for ");
- cmdputs(n->nfor.var);
- cmdputs(" in ");
- cmdlist(n->nfor.args, 1);
- n = n->nfor.body;
- p = "; done";
- goto dodo;
- case NDEFUN:
- cmdputs(n->narg.text);
- p = "() { ... }";
- goto dotail2;
- case NCMD:
- cmdlist(n->ncmd.args, 1);
- cmdlist(n->ncmd.redirect, 0);
- break;
- case NARG:
- p = n->narg.text;
- dotail2:
- cmdputs(p);
- break;
- case NHERE:
- case NXHERE:
- p = "<<...";
- goto dotail2;
- case NCASE:
- cmdputs("case ");
- cmdputs(n->ncase.expr->narg.text);
- cmdputs(" in ");
- for (np = n->ncase.cases; np; np = np->nclist.next) {
- cmdtxt(np->nclist.pattern);
- cmdputs(") ");
- cmdtxt(np->nclist.body);
- cmdputs(";; ");
- }
- p = "esac";
- goto dotail2;
- case NTO:
- p = ">";
- goto redir;
- case NCLOBBER:
- p = ">|";
- goto redir;
- case NAPPEND:
- p = ">>";
- goto redir;
- case NTOFD:
- p = ">&";
- goto redir;
- case NFROM:
- p = "<";
- goto redir;
- case NFROMFD:
- p = "<&";
- goto redir;
- case NFROMTO:
- p = "<>";
- redir:
- s[0] = n->nfile.fd + '0';
- s[1] = '\0';
- cmdputs(s);
- cmdputs(p);
- if (n->type == NTOFD || n->type == NFROMFD) {
- s[0] = n->ndup.dupfd + '0';
- p = s;
- goto dotail2;
- }
- n = n->nfile.fname;
- goto donode;
- }
-}
-
-static void
-cmdlist(union node *np, int sep)
-{
- for (; np; np = np->narg.next) {
- if (!sep)
- cmdputs(spcstr);
- cmdtxt(np);
- if (sep && np->narg.next)
- cmdputs(spcstr);
- }
-}
-
-static void
-cmdputs(const char *s)
-{
- const char *p, *str;
- char c, cc[2] = " ";
- char *nextc;
- int subtype = 0;
- int quoted = 0;
- static const char vstype[VSTYPE + 1][4] = {
- "", "}", "-", "+", "?", "=",
- "%", "%%", "#", "##"
- };
-
- nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
- p = s;
- while ((c = *p++) != 0) {
- str = 0;
- switch (c) {
- case CTLESC:
- c = *p++;
- break;
- case CTLVAR:
- subtype = *p++;
- if ((subtype & VSTYPE) == VSLENGTH)
- str = "${#";
- else
- str = "${";
- if (!(subtype & VSQUOTE) == !(quoted & 1))
- goto dostr;
- quoted ^= 1;
- c = '"';
- break;
- case CTLENDVAR:
- str = "\"}" + !(quoted & 1);
- quoted >>= 1;
- subtype = 0;
- goto dostr;
- case CTLBACKQ:
- str = "$(...)";
- goto dostr;
- case CTLBACKQ+CTLQUOTE:
- str = "\"$(...)\"";
- goto dostr;
-#if ENABLE_ASH_MATH_SUPPORT
- case CTLARI:
- str = "$((";
- goto dostr;
- case CTLENDARI:
- str = "))";
- goto dostr;
-#endif
- case CTLQUOTEMARK:
- quoted ^= 1;
- c = '"';
- break;
- case '=':
- if (subtype == 0)
- break;
- if ((subtype & VSTYPE) != VSNORMAL)
- quoted <<= 1;
- str = vstype[subtype & VSTYPE];
- if (subtype & VSNUL)
- c = ':';
- else
- goto checkstr;
- break;
- case '\'':
- case '\\':
- case '"':
- case '$':
- /* These can only happen inside quotes */
- cc[0] = c;
- str = cc;
- c = '\\';
- break;
- default:
- break;
- }
- USTPUTC(c, nextc);
- checkstr:
- if (!str)
- continue;
- dostr:
- while ((c = *str++)) {
- USTPUTC(c, nextc);
- }
- }
- if (quoted & 1) {
- USTPUTC('"', nextc);
- }
- *nextc = 0;
- cmdnextc = nextc;
-}
-#endif /* JOBS */
#if ENABLE_ASH_MAIL
/* mail.c */
@@ -11348,8 +11339,6 @@ redirectsafe(union node *redir, int flags)
/* trap.c */
-
-
/*
* The trap builtin.
*/