ash: cleanup part 6
This commit is contained in:
parent
5c67e3ed90
commit
a6704933dd
577
shell/ash.c
577
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.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user