[BusyBox] busybox ash upgrade patches
Mark Hatle
fray at mvista.com
Wed Dec 19 06:54:52 UTC 2001
Well.. I ran into a couple of minor annoyances in BB's ASH.. (And
honestly I don't even remember what they are anymore..)
Anyway.. so I read the BB ash.c and saw it was based on Debian's ash
0.3.8-5, and I decided to "upgrade".
Attached to this email are 28 patches that proceed to upgrade BB ash to
"Debian ash 0.3.8-32".
Patch order: expandmeta-diff needs to be one of the last applied as it
gets a rej. The others seem to be failry independent. The clean-diff
should be the last diff applied as it cleans up warnings and extra
functions.
The "argstr-diff" patch gave me a lot of troubles.. if you play with
this in a piecemeal fashion, this is the last one to play with. It
apparently depends on another patch to keep things from going haywire.
I never did figure out which other patch it depended on.. but if you use
only that patch it won't work.
In the _rmescapes function you'll see a #if 0 wrapping a section.
Unfortunatly I do not understand what is being attempted here..
(compared to the "real" ash.) It works in teh real ash, doesn't work in
BB ash. I could not figure out the cause. If anyone has suggestions
please let me know!
Any questions please let me know. (If you are interested in a changelog
type thing just get the debian ash package, look at it's changelog
between 0.3.8-5 and 0.3.8-32 for a pretty complete change list.)
Any problems/suggestions/flames let me know.
(I am not subscribed to the busybox lists, but I do look at them
occasionally.. so I would prefer if you CCed me on any emails.)
Thanx,
Mark
-------------- next part --------------
--- ash.c.orig Mon Dec 10 16:13:22 2001
+++ ash.c Mon Dec 10 16:22:20 2001
@@ -5489,12 +5489,10 @@
static void
addfname(const char *name)
{
- char *p;
struct strlist *sp;
- p = sstrdup(name);
sp = (struct strlist *)stalloc(sizeof *sp);
- sp->text = p;
+ sp->text = sstrdup(name);
*exparg.lastp = sp;
exparg.lastp = &sp->next;
}
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:33:28 2001
+++ ash.c Tue Dec 11 14:36:43 2001
@@ -1137,6 +1137,8 @@
"}"
};
+const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
+#define DOLATSTRLEN 4
static int plinno = 1; /* input line number */
@@ -4737,66 +4739,131 @@
char *p;
int flag;
{
- char c;
+ static const char spclchars[] = {
+ '=',
+ ':',
+ CTLQUOTEMARK,
+ CTLENDVAR,
+ CTLESC,
+ CTLVAR,
+ CTLBACKQ,
+ CTLBACKQ | CTLQUOTE,
+ CTLENDARI,
+ 0
+ };
+ const char *reject = spclchars;
+ int c;
int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
- int firsteq = 1;
+ int breakall = flag & EXP_WORD;
+ int inquotes;
+ size_t length;
+ int startloc;
- if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
+ if (!(flag & EXP_VARTILDE)) {
+ reject += 2;
+ } else if (flag & EXP_VARTILDE2) {
+ reject++;
+ }
+ inquotes = 0;
+ length = 0;
+ if (flag & EXP_TILDE) {
+ flag &= ~EXP_TILDE;
+tilde:
p = exptilde(p, flag);
+ }
+start:
+ startloc = expdest - stackblock();
for (;;) {
- switch (c = *p++) {
+ length += strcspn(p + length, reject);
+ c = p[length];
+ if ((c && !(c & 0x80)) || c == CTLENDARI) {
+ /* c == '=' || c == ':' || c == CTLENDARI */
+ length++;
+ }
+ if (length > 0) {
+ int newloc;
+ /* expdest = stnputs(p, length, expdest); */
+ CHECKSTRSPACE(length, expdest);
+ expdest = mempcpy(expdest, p, length);
+ sstrnleft -= length;
+ newloc = expdest - stackblock();
+ if (breakall && !inquotes && newloc > startloc) {
+ recordregion(startloc, newloc, 0);
+ }
+ startloc = newloc;
+ }
+ p += length + 1;
+ length = 0;
+
+ switch (c) {
case '\0':
+ goto breakloop;
+ case '=':
+ if (flag & EXP_VARTILDE2) {
+ p--;
+ continue;
+ }
+ flag |= EXP_VARTILDE2;
+ reject++;
+ /* fall through */
+ case ':':
+ /*
+ * sort of a hack - expand tildes in variable
+ * assignments (after the first '=' and after ':'s).
+ */
+ if (*--p == '~') {
+ goto tilde;
+ }
+ continue;
+ }
+
+ switch (c) {
case CTLENDVAR: /* ??? */
goto breakloop;
case CTLQUOTEMARK:
/* "$@" syntax adherence hack */
- if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
- break;
- if ((flag & EXP_FULL) != 0)
- STPUTC(c, expdest);
+ if (
+ !inquotes &&
+ !memcmp(p, dolatstr, DOLATSTRLEN) &&
+ (p[4] == CTLQUOTEMARK || (
+ p[4] == CTLENDVAR &&
+ p[5] == CTLQUOTEMARK
+ ))
+ ) {
+ p = evalvar(p + 1, flag) + 1;
+ goto start;
+ }
+ inquotes = !inquotes;
+addquote:
+ if (quotes) {
+ p--;
+ length++;
+ startloc++;
+ }
break;
case CTLESC:
- if (quotes)
- STPUTC(c, expdest);
- c = *p++;
- STPUTC(c, expdest);
- break;
+ startloc++;
+ length++;
+ goto addquote;
case CTLVAR:
p = evalvar(p, flag);
- break;
+ goto start;
case CTLBACKQ:
+ c = 0;
case CTLBACKQ|CTLQUOTE:
- expbackq(argbackq->n, c & CTLQUOTE, flag);
+ expbackq(argbackq->n, c, quotes);
argbackq = argbackq->next;
- break;
-#ifdef ASH_MATH_SUPPORT
+ goto start;
case CTLENDARI:
- expari(flag);
- break;
+#ifdef ASH_MATH_SUPPORT
+ p--;
+ expari(quotes);
+ goto start;
#endif
- case ':':
- case '=':
- /*
- * sort of a hack - expand tildes in variable
- * assignments (after the first '=' and after ':'s).
- */
- STPUTC(c, expdest);
- if (flag & EXP_VARTILDE && *p == '~') {
- if (c == '=') {
- if (firsteq)
- firsteq = 0;
- else
- break;
- }
- p = exptilde(p, flag);
- }
- break;
- default:
- STPUTC(c, expdest);
}
}
-breakloop:;
- return;
+breakloop:
+ ;
}
static char *
@@ -9563,14 +9563,6 @@
n1 = NULL;
rpp = &redir;
- /* Check for redirection which may precede command */
- while (readtoken() == TREDIR) {
- *rpp = n2 = redirnode;
- rpp = &n2->nfile.next;
- parsefname();
- }
- tokpushback++;
-
switch (readtoken()) {
case TIF:
n1 = (union node *)stalloc(sizeof (struct nif));
@@ -9637,11 +9629,9 @@
if (lasttoken != TNL && lasttoken != TSEMI)
synexpect(-1);
} else {
- static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
- '@', '=', '\0'};
n2 = (union node *)stalloc(sizeof (struct narg));
n2->type = NARG;
- n2->narg.text = argvars;
+ n2->narg.text = (char *)dolatstr;
n2->narg.backquote = NULL;
n2->narg.next = NULL;
n1->nfor.args = n2;
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:18:04 2001
+++ ash.c Sat Dec 8 19:18:53 2001
@@ -3209,6 +3209,8 @@
{
int n = argc > 1 ? number(argv[1]) : 1;
+ if (n <= 0)
+ error("Illegal number: %s", argv[1]);
if (n > loopnest)
n = loopnest;
if (n > 0) {
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:52:39 2001
+++ ash.c Tue Dec 11 14:58:04 2001
@@ -1171,8 +1171,6 @@
static void dotrap (void);
static int decode_signal (const char *, int);
-static void shprocvar(void);
-static void deletefuncs(void);
static void setparam (char **);
static void freeparam (volatile struct shparam *);
@@ -1757,7 +1755,6 @@
};
#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
-static const struct builtincmd *DOTCMD = &builtincmds[0];
static struct builtincmd *BLTINCMD;
static struct builtincmd *EXECCMD;
static struct builtincmd *EVALCMD;
@@ -3403,65 +3400,6 @@
}
-static void
-initshellproc(void) {
-
-#ifdef ASH_ALIAS
- /* from alias.c: */
- {
- rmaliases();
- }
-#endif
- /* from eval.c: */
- {
- exitstatus = 0;
- }
-
- /* from exec.c: */
- {
- deletefuncs();
- }
-
- /* from jobs.c: */
- {
- backgndpid = -1;
-#ifdef JOBS
- jobctl = 0;
-#endif
- }
-
- /* from options.c: */
- {
- int i;
-
- for (i = 0; i < NOPTS; i++)
- optent_val(i) = 0;
- optschanged();
-
- }
-
- /* from redir.c: */
- {
- clearredir();
- }
-
- /* from trap.c: */
- {
- char *sm;
-
- clear_traps();
- for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
- if (*sm == S_IGN)
- *sm = S_HARD_IGN;
- }
- }
-
- /* from var.c: */
- {
- shprocvar();
- }
-}
-
static int preadbuffer(void);
static void pushfile (void);
@@ -4150,34 +4088,6 @@
/*
- * Delete all functions.
- */
-
-static void
-deletefuncs(void) {
- struct tblentry **tblp;
- struct tblentry **pp;
- struct tblentry *cmdp;
-
- INTOFF;
- for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
- pp = tblp;
- while ((cmdp = *pp) != NULL) {
- if (cmdp->cmdtype == CMDFUNCTION) {
- *pp = cmdp->next;
- freefunc(cmdp->param.func);
- ckfree(cmdp);
- } else {
- pp = &cmdp->next;
- }
- }
- }
- INTON;
-}
-
-
-
-/*
* Locate a command in the command hash table. If "add" is nonzero,
* add the command to the table if it is not already present. The
* variable "lastcmdentry" is set to point to the address of the link
@@ -11113,7 +11023,7 @@
{
union node *n;
struct redirtab *sv = NULL;
- int i;
+ int i = 0;
int fd;
int newfd;
int try;
@@ -12544,39 +12454,6 @@
*ep = NULL;
return env;
}
-
-
-/*
- * Called when a shell procedure is invoked to clear out nonexported
- * variables. It is also necessary to reallocate variables of with
- * VSTACK set since these are currently allocated on the stack.
- */
-
-static void
-shprocvar(void) {
- struct var **vpp;
- struct var *vp, **prev;
-
- for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
- for (prev = vpp ; (vp = *prev) != NULL ; ) {
- if ((vp->flags & VEXPORT) == 0) {
- *prev = vp->next;
- if ((vp->flags & VTEXTFIXED) == 0)
- ckfree(vp->text);
- if ((vp->flags & VSTRFIXED) == 0)
- ckfree(vp);
- } else {
- if (vp->flags & VSTACK) {
- vp->text = savestr(vp->text);
- vp->flags &=~ VSTACK;
- }
- prev = &vp->next;
- }
- }
- }
- initvar();
-}
-
/*
-------------- next part --------------
--- ash.c.orig Fri Nov 30 12:11:00 2001
+++ ash.c Fri Nov 30 12:12:08 2001
@@ -2198,7 +2198,7 @@
struct errname {
short errcode; /* error number */
- char action; /* operation which encountered the error */
+ short action; /* operation which encountered the error */
};
/*
-------------- next part --------------
--- ash.c.orig Fri Nov 30 12:42:22 2001
+++ ash.c Fri Nov 30 15:03:54 2001
@@ -2451,6 +2451,7 @@
loopnest++;
status = 0;
+ flags &= EV_TESTED;
for (;;) {
evaltree(n->nbinary.ch1, EV_TESTED);
if (evalskip) {
@@ -2469,7 +2470,7 @@
if (exitstatus == 0)
break;
}
- evaltree(n->nbinary.ch2, flags & EV_TESTED);
+ evaltree(n->nbinary.ch2, flags);
status = exitstatus;
if (evalskip)
goto skipping;
@@ -2498,9 +2499,10 @@
exitstatus = 0;
loopnest++;
+ flags &= EV_TESTED;
for (sp = arglist.list ; sp ; sp = sp->next) {
setvar(n->nfor.var, sp->text, 0);
- evaltree(n->nfor.body, flags & EV_TESTED);
+ evaltree(n->nfor.body, flags);
if (evalskip) {
if (evalskip == SKIPCONT && --skipcount <= 0) {
evalskip = 0;
@@ -2550,8 +2552,9 @@
*/
static inline void
-evalpipe(n)
+evalpipe(n, flags)
union node *n;
+ int flags;
{
struct job *jp;
struct nodelist *lp;
@@ -2563,6 +2566,7 @@
pipelen = 0;
for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
pipelen++;
+ flags |= EV_EXIT;
INTOFF;
jp = makejob(n, pipelen);
prevfd = -1;
@@ -2577,38 +2581,29 @@
}
if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
INTON;
+ if (pip[1] >= 0) {
+ close(pip[0]);
+ }
if (prevfd > 0) {
- close(0);
- dup_as_newfd(prevfd, 0);
+ dup2(prevfd, 0);
close(prevfd);
- if (pip[0] == 0) {
- pip[0] = -1;
- }
}
- if (pip[1] >= 0) {
- if (pip[0] >= 0) {
- close(pip[0]);
- }
- if (pip[1] != 1) {
- close(1);
- dup_as_newfd(pip[1], 1);
- close(pip[1]);
- }
+ if (pip[1] > 1) {
+ dup2(pip[1], 1);
+ close(pip[1]);
}
- evaltree(lp->n, EV_EXIT);
+ evaltree(lp->n, flags);
}
if (prevfd >= 0)
close(prevfd);
prevfd = pip[0];
close(pip[1]);
}
- INTON;
if (n->npipe.backgnd == 0) {
- INTOFF;
exitstatus = waitforjob(jp);
TRACE(("evalpipe: job done exit status %d\n", exitstatus));
- INTON;
}
+ INTON;
}
static void find_command (const char *, struct cmdentry *, int, const char *);
-------------- next part --------------
--- ash.c.orig Fri Nov 30 15:07:05 2001
+++ ash.c Sat Dec 8 19:11:26 2001
@@ -2081,6 +2081,7 @@
#define EXERROR 1 /* a generic error */
#define EXSHELLPROC 2 /* execute a shell procedure */
#define EXEXEC 3 /* command execution failed */
+#define EXREDIR 4 /* redirection error */
static struct jmploc *handler;
static int exception;
@@ -2640,7 +2641,7 @@
volatile int e;
char *lastarg;
const char *path;
- const struct builtincmd *firstbltin;
+ int spclbltin;
struct jmploc *volatile savehandler;
struct jmploc jmploc;
#if __GNUC__
@@ -2663,25 +2664,9 @@
for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
expandarg(argp, &varlist, EXP_VARTILDE);
}
- for (
- argp = cmd->ncmd.args; argp && !arglist.list;
- argp = argp->narg.next
- ) {
+ for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
}
- if (argp) {
- struct builtincmd *bcmd;
- int pseudovarflag;
- bcmd = find_builtin(arglist.list->text);
- pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
- for (; argp; argp = argp->narg.next) {
- if (pseudovarflag && isassignment(argp->narg.text)) {
- expandarg(argp, &arglist, EXP_VARTILDE);
- continue;
- }
- expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
- }
- }
*arglist.lastp = NULL;
*varlist.lastp = NULL;
expredir(cmd->ncmd.redirect);
@@ -2711,7 +2696,8 @@
/* Now locate the command. */
if (argc == 0) {
cmdentry.cmdtype = CMDBUILTIN;
- firstbltin = cmdentry.u.cmd = BLTINCMD;
+ cmdentry.u.cmd = BLTINCMD;
+ spclbltin = 1;
} else {
const char *oldpath;
int findflag = DO_ERR;
@@ -2728,7 +2714,7 @@
}
oldpath = path;
oldfindflag = findflag;
- firstbltin = 0;
+ spclbltin = -1;
for(;;) {
find_command(argv[0], &cmdentry, findflag, path);
if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
@@ -2739,8 +2725,12 @@
if (cmdentry.cmdtype != CMDBUILTIN) {
break;
}
- if (!firstbltin) {
- firstbltin = cmdentry.u.cmd;
+ if (spclbltin < 0) {
+ spclbltin =
+ !!(
+ IS_BUILTIN_SPECIAL(cmdentry.u.cmd)
+ ) * 2
+ ;
}
if (cmdentry.u.cmd == BLTINCMD) {
for(;;) {
@@ -2789,14 +2779,21 @@
}
/* Fork off a child process if necessary. */
- if (cmd->ncmd.backgnd
- || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
+ if (
+ cmd->ncmd.backgnd || (
+ cmdentry.cmdtype == CMDNORMAL &&
+ (!(flags & EV_EXIT) || trap[0])
+ )
) {
+ INTOFF;
jp = makejob(cmd, 1);
mode = cmd->ncmd.backgnd;
if (forkshell(jp, cmd, mode) != 0)
goto parent; /* at end of routine */
+ FORCEINTON;
flags |= EV_EXIT;
+ } else {
+ flags &= ~EV_EXIT;
}
/* This is the child process if a fork occurred. */
@@ -2806,7 +2803,6 @@
trputs("Shell function: "); trargs(argv);
#endif
exitstatus = oexitstatus;
- redirect(cmd->ncmd.redirect, REDIR_PUSH);
saveparam = shellparam;
shellparam.malloc = 0;
shellparam.nparam = argc - 1;
@@ -2816,15 +2812,14 @@
localvars = NULL;
INTON;
if (setjmp(jmploc.loc)) {
- if (exception == EXSHELLPROC) {
- freeparam((volatile struct shparam *)
- &saveparam);
- } else {
- saveparam.optind = shellparam.optind;
- saveparam.optoff = shellparam.optoff;
- freeparam(&shellparam);
- shellparam = saveparam;
- }
+ if (exception == EXREDIR) {
+ exitstatus = 2;
+ goto funcdone;
+ }
+ saveparam.optind = shellparam.optind;
+ saveparam.optoff = shellparam.optoff;
+ freeparam(&shellparam);
+ shellparam = saveparam;
poplocalvars();
localvars = savelocalvars;
handler = savehandler;
@@ -2832,11 +2827,12 @@
}
savehandler = handler;
handler = &jmploc;
- for (sp = varlist.list ; sp ; sp = sp->next)
- mklocal(sp->text);
+ redirect(cmd->ncmd.redirect, REDIR_PUSH);
+ listsetvar(varlist.list);
funcnest++;
evaltree(cmdentry.u.func, flags & EV_TESTED);
funcnest--;
+funcdone:
INTOFF;
poplocalvars();
localvars = savelocalvars;
@@ -2851,16 +2847,14 @@
evalskip = 0;
skipcount = 0;
}
- if (flags & EV_EXIT)
- exitshell(exitstatus);
} else if (cmdentry.cmdtype == CMDBUILTIN) {
+ int redir;
#ifdef DEBUG
trputs("builtin command: "); trargs(argv);
#endif
- mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
- redirect(cmd->ncmd.redirect, mode);
+ redir = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
savecmdname = commandname;
- if (IS_BUILTIN_SPECIAL(firstbltin)) {
+ if (spclbltin) {
listsetvar(varlist.list);
} else {
cmdenviron = varlist.list;
@@ -2873,6 +2867,7 @@
}
savehandler = handler;
handler = &jmploc;
+ redirect(cmd->ncmd.redirect, redir);
commandname = argv[0];
argptr = argv + 1;
optptr = NULL; /* initialize nextopt */
@@ -2880,19 +2875,13 @@
flushall();
cmddone:
cmdenviron = NULL;
- if (e != EXSHELLPROC) {
- commandname = savecmdname;
- if (flags & EV_EXIT)
- exitshell(exitstatus);
- }
+ commandname = savecmdname;
handler = savehandler;
if (e != -1) {
- if ((e != EXERROR && e != EXEXEC)
- || cmdentry.u.cmd == BLTINCMD
- || cmdentry.u.cmd == DOTCMD
- || cmdentry.u.cmd == EVALCMD
- || cmdentry.u.cmd == EXECCMD)
- exraise(e);
+ if (e == EXINT || spclbltin & 2) {
+ if (e == EXREDIR)
+ exraise(e);
+ }
FORCEINTON;
}
if (cmdentry.u.cmd != EXECCMD)
@@ -2912,10 +2901,9 @@
parent: /* parent process gets here (if we forked) */
if (mode == 0) { /* argument to fork */
- INTOFF;
exitstatus = waitforjob(jp);
- INTON;
}
+ INTON;
out:
if (lastarg)
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:12:35 2001
+++ ash.c Sat Dec 8 19:17:03 2001
@@ -3041,17 +3041,22 @@
int backgnd = (n->type == NBACKGND);
expredir(n->nredir.redirect);
+ if (!backgnd && flags & EV_EXIT && !trap[0])
+ goto nofork;
+ INTOFF;
jp = makejob(n, 1);
if (forkshell(jp, n, backgnd) == 0) {
+ INTON;
+ flags |= EV_EXIT;
if (backgnd)
flags &=~ EV_TESTED;
+nofork:
redirect(n->nredir.redirect, 0);
- evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
+ evaltreenr(n->nredir.n, flags);
+ /* never returns */
}
if (! backgnd) {
- INTOFF;
exitstatus = waitforjob(jp);
- INTON;
}
}
-------------- next part --------------
--- ash.c.orig Fri Nov 30 12:24:29 2001
+++ ash.c Fri Nov 30 12:40:02 2001
@@ -2311,10 +2311,12 @@
static int exitstatus; /* exit status of last command */
static int oexitstatus; /* saved exit status */
+static int defun (char *, union node *);
static void evalsubshell (const union node *, int);
static void expredir (union node *);
static void prehash (union node *);
static void eprintlist (struct strlist *);
+static void evaltreenr __P((union node *, int)) __attribute__ ((noreturn));
static union node *parsecmd(int);
/*
@@ -2359,7 +2361,7 @@
* Execute a command or commands contained in a string.
*/
-static void evaltree (union node *, int);
+static void evaltree (const union node *, int);
static void setinputstring (char *);
static void popfile (void);
static void setstackmark(struct stackmark *mark);
@@ -2624,7 +2626,7 @@
static void
-evalcommand(union node *cmd, int flags)
+evalcommand(const union node *cmd, int flags)
{
struct stackmark smark;
union node *argp;
@@ -2930,105 +2932,107 @@
* Evaluate a parse tree. The value is left in the global variable
* exitstatus.
*/
+
static void
evaltree(n, flags)
- union node *n;
+ const union node *n;
int flags;
{
int checkexit = 0;
+ void (*evalfn)(const union node *, int);
+ unsigned isor;
+ struct jmploc jmploc;
+ struct jmploc *volatile savehandler;
if (n == NULL) {
TRACE(("evaltree(NULL) called\n"));
goto out;
}
TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
switch (n->type) {
- case NSEMI:
- evaltree(n->nbinary.ch1, flags & EV_TESTED);
- if (evalskip)
- goto out;
- evaltree(n->nbinary.ch2, flags);
- break;
- case NAND:
- evaltree(n->nbinary.ch1, EV_TESTED);
- if (evalskip || exitstatus != 0)
- goto out;
- evaltree(n->nbinary.ch2, flags);
- break;
- case NOR:
- evaltree(n->nbinary.ch1, EV_TESTED);
- if (evalskip || exitstatus == 0)
- goto out;
- evaltree(n->nbinary.ch2, flags);
+ default:
+#ifdef DEBUG
+ printf("Node type = %d\n", n->type);
break;
+#endif
+ case NFOR:
+ evalfn = evalfor;
+ goto calleval;
case NREDIR:
expredir(n->nredir.redirect);
+ if (setjmp(jmploc.loc)) {
+ exitstatus = 2;
+ handler = savehandler;
+ goto redirdone;
+ }
+ savehandler = handler;
+ handler = &jmploc;
redirect(n->nredir.redirect, REDIR_PUSH);
- evaltree(n->nredir.n, flags);
+ handler = savehandler;
+ evaltree(n->nredir.n, flags & EV_TESTED);
+redirdone:
popredir();
break;
- case NSUBSHELL:
- evalsubshell(n, flags);
- break;
- case NBACKGND:
- evalsubshell(n, flags);
- break;
- case NIF: {
- evaltree(n->nif.test, EV_TESTED);
- if (evalskip)
- goto out;
- if (exitstatus == 0)
- evaltree(n->nif.ifpart, flags);
- else if (n->nif.elsepart)
- evaltree(n->nif.elsepart, flags);
- else
- exitstatus = 0;
- break;
- }
case NWHILE:
case NUNTIL:
- evalloop(n, flags);
- break;
- case NFOR:
- evalfor(n, flags);
- break;
+ evalfn = evalloop;
+ goto calleval;
+ case NSUBSHELL:
+ case NBACKGND:
+ evalfn = evalsubshell;
+ goto calleval;
case NCASE:
- evalcase(n, flags);
+ evalfn = evalcase;
+calleval:
+ evalfn(n, flags);
break;
- case NDEFUN: {
- struct builtincmd *bcmd;
- struct cmdentry entry;
- if (
- (bcmd = find_builtin(n->narg.text)) &&
- IS_BUILTIN_SPECIAL(bcmd)
- ) {
- out2fmt("%s is a special built-in\n", n->narg.text);
- exitstatus = 1;
- break;
- }
- entry.cmdtype = CMDFUNCTION;
- entry.u.func = copyfunc(n->narg.next);
- addcmdentry(n->narg.text, &entry);
- exitstatus = 0;
+ case NDEFUN:
+ exitstatus = defun(n->narg.text, n->narg.next);
break;
- }
+ case NPIPE:
+ evalfn = evalpipe;
+ goto checkexit;
+ case NCMD:
+ evalfn = evalcommand;
+checkexit:
+ checkexit = 1;
+ goto calleval;
case NNOT:
evaltree(n->nnot.com, EV_TESTED);
exitstatus = !exitstatus;
break;
-
- case NPIPE:
- evalpipe(n);
- checkexit = 1;
- break;
- case NCMD:
- evalcommand(n, flags);
- checkexit = 1;
+ case NAND:
+ case NOR:
+ case NSEMI:
+#if NAND + 1 != NOR
+#error NAND + 1 != NOR
+#endif
+ isor = n->type - NAND;
+ evaltree(
+ n->nbinary.ch1,
+ (flags | ((isor >> 1) - 1)) & EV_TESTED
+ );
+ if (!exitstatus == isor)
+ break;
+ if (!evalskip) {
+ n = n->nbinary.ch2;
+evaln:
+ evalfn = evaltree;
+ goto calleval;
+ }
break;
-#ifdef DEBUG
- default:
- printf("Node type = %d\n", n->type);
+ case NIF:
+ evaltree(n->nif.test, EV_TESTED);
+ if (evalskip)
+ break;
+ if (exitstatus == 0) {
+ n = n->nif.ifpart;
+ goto evaln;
+ } else if (n->nif.elsepart) {
+ n = n->nif.elsepart;
+ goto evaln;
+ } else
+ exitstatus = 0;
break;
-#endif
}
out:
if (pendingsigs)
@@ -3040,6 +3044,9 @@
exitshell(exitstatus);
}
+
+static void evaltreenr(union node *, int) __attribute__ ((alias("evaltree")));
+
/*
* Kick off a subshell to evaluate a tree.
*/
@@ -4222,7 +4229,29 @@
}
+/*
+ * Define a shell function.
+ */
+static int
+defun(char *name, union node *func)
+{
+ struct cmdentry entry;
+ struct builtincmd *bcmd;
+
+ if (
+ (bcmd = find_builtin(name)) &&
+ IS_BUILTIN_SPECIAL(bcmd)
+ ) {
+ out2fmt("%s is a special built-in\n", name);
+ return 1;
+ }
+
+ entry.cmdtype = CMDFUNCTION;
+ entry.u.func = copyfunc(func);
+ addcmdentry(name, &entry);
+ return 0;
+}
static const short nodesize[26] = {
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:31:07 2001
+++ ash.c Sat Dec 8 19:42:38 2001
@@ -411,7 +411,9 @@
#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
-
+#define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
+#define EXP_WORD 0x80 /* expand word parameter expansion */
+#define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
#define NOPTS 16
@@ -4546,9 +4548,11 @@
int varlen;
int easy;
int quotes = flag & (EXP_FULL | EXP_CASE);
+ int quoted;
varflags = *p++;
subtype = varflags & VSTYPE;
+ quoted = varflags & VSQUOTE;
var = p;
special = 0;
if (! is_name(*p))
@@ -4571,7 +4575,7 @@
if (set && subtype != VSPLUS) {
/* insert the value of the variable */
if (special) {
- varvalue(var, varflags & VSQUOTE, flag);
+ varvalue(var, quoted, flag);
if (subtype == VSLENGTH) {
varlen = expdest - stackblock() - startloc;
STADJUST(-varlen, expdest);
@@ -4582,8 +4586,7 @@
} else {
strtodest(
val,
- varflags & VSQUOTE ?
- DQSYNTAX : BASESYNTAX,
+ quoted ? DQSYNTAX : BASESYNTAX,
quotes
);
}
@@ -4593,27 +4596,29 @@
if (subtype == VSPLUS)
set = ! set;
- easy = ((varflags & VSQUOTE) == 0 ||
+ easy = (!quoted ||
(*var == '@' && shellparam.nparam != 1));
switch (subtype) {
case VSLENGTH:
- expdest = cvtnum(varlen, expdest);
+ cvtnum(varlen, expdest);
goto record;
case VSNORMAL:
if (!easy)
break;
record:
- recordregion(startloc, expdest - stackblock(),
- varflags & VSQUOTE);
+ recordregion(startloc, expdest - stackblock(), quoted);
break;
case VSPLUS:
case VSMINUS:
if (!set) {
- argstr(p, flag);
+ argstr(
+ p, flag | EXP_TILDE |
+ (quoted ? EXP_QWORD : EXP_WORD)
+ );
break;
}
if (easy)
@@ -4645,7 +4650,7 @@
case VSQUESTION:
if (!set) {
if (subevalvar(p, var, 0, subtype, startloc,
- varflags, quotes)) {
+ varflags, 0)) {
varflags &= ~VSNUL;
/*
* Remove any recorded regions beyond
-------------- next part --------------
--- ash.c.orig Mon Dec 10 16:23:32 2001
+++ ash.c Mon Dec 10 16:46:57 2001
@@ -5508,18 +5508,19 @@
struct strlist *str;
int flag;
{
- const char *p;
- glob_t pglob;
/* TODO - EXP_REDIR */
while (str) {
+ const char *p;
+ glob_t pglob;
+
if (fflag)
goto nometa;
p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_GROW);
INTOFF;
- switch (glob(p, 0, 0, &pglob)) {
+ switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) {
case 0:
- if(pglob.gl_pathv[1]==0 && !strcmp(p, pglob.gl_pathv[0]))
+ if (!(pglob.gl_flags & GLOB_MAGCHAR))
goto nometa2;
addglob(&pglob);
globfree(&pglob);
@@ -5567,32 +5568,33 @@
struct strlist *str;
int flag;
{
- char *p;
- struct strlist **savelastp;
- struct strlist *sp;
- char c;
+ static const char metachars[] = {
+ '*', '?', '[', 0
+ };
/* TODO - EXP_REDIR */
while (str) {
+ struct strlist **savelastp;
+ struct strlist *sp;
+ char *p;
+
if (fflag)
goto nometa;
- p = str->text;
- for (;;) { /* fast check for meta chars */
- if ((c = *p++) == '\0')
+ if (!strpbrk(str->text, metachars))
goto nometa;
- if (c == '*' || c == '?' || c == '[' || c == '!')
- break;
- }
savelastp = exparg.lastp;
+
INTOFF;
- if (expdir == NULL) {
+ p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
+ {
int i = strlen(str->text);
expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
}
- expmeta(expdir, str->text);
+ expmeta(expdir, p);
ckfree(expdir);
- expdir = NULL;
+ if (p != str->text)
+ ckfree(p);
INTON;
if (exparg.lastp == savelastp) {
/*
@@ -5625,7 +5627,6 @@
{
char *p;
const char *cp;
- char *q;
char *start;
char *endname;
int metaflag;
@@ -5637,17 +5638,15 @@
metaflag = 0;
start = name;
- for (p = name ; ; p++) {
+ for (p = name; *p; p++) {
if (*p == '*' || *p == '?')
metaflag = 1;
else if (*p == '[') {
- q = p + 1;
+ char *q = p + 1;
if (*q == '!')
q++;
for (;;) {
- while (*q == CTLQUOTEMARK)
- q++;
- if (*q == CTLESC)
+ if (*q == '\\')
q++;
if (*q == '/' || *q == '\0')
break;
@@ -5656,46 +5655,36 @@
break;
}
}
- } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
- metaflag = 1;
- } else if (*p == '\0')
- break;
- else if (*p == CTLQUOTEMARK)
- continue;
- else if (*p == CTLESC)
+ } else if (*p == '\\')
p++;
- if (*p == '/') {
+ else if (*p == '/') {
if (metaflag)
- break;
+ goto out;
start = p + 1;
}
}
+out:
if (metaflag == 0) { /* we've reached the end of the file name */
if (enddir != expdir)
metaflag++;
- for (p = name ; ; p++) {
- if (*p == CTLQUOTEMARK)
- continue;
- if (*p == CTLESC)
+ p = name;
+ do {
+ if (*p == '\\')
p++;
*enddir++ = *p;
- if (*p == '\0')
- break;
- }
+ } while (*p++);
if (metaflag == 0 || lstat(expdir, &statb) >= 0)
addfname(expdir);
return;
}
endname = p;
- if (start != name) {
+ if (name < start) {
p = name;
- while (p < start) {
- while (*p == CTLQUOTEMARK)
- p++;
- if (*p == CTLESC)
+ do {
+ if (*p == '\\')
p++;
*enddir++ = *p++;
- }
+ } while (p < start);
}
if (enddir == expdir) {
cp = ".";
@@ -5717,16 +5706,14 @@
}
matchdot = 0;
p = start;
- while (*p == CTLQUOTEMARK)
- p++;
- if (*p == CTLESC)
+ if (*p == '\\')
p++;
if (*p == '.')
matchdot++;
while (! int_pending() && (dp = readdir(dirp)) != NULL) {
if (dp->d_name[0] == '.' && ! matchdot)
continue;
- if (patmatch(start, dp->d_name, 0)) {
+ if (pmatch(start, dp->d_name)) {
if (atend) {
strcpy(enddir, dp->d_name);
addfname(expdir);
-------------- next part --------------
--- ash.c.orig Mon Dec 10 15:21:29 2001
+++ ash.c Mon Dec 10 15:56:27 2001
@@ -4899,39 +4902,45 @@
* evaluate, place result in (backed up) result, adjust string position.
*/
static void
-expari(int flag)
+expari(quotes)
+ int quotes;
{
char *p, *start;
- int errcode;
- int result;
int begoff;
- int quotes = flag & (EXP_FULL | EXP_CASE);
int quoted;
+ int errcode;
+ int result;
/* ifsfree(); */
/*
* This routine is slightly over-complicated for
- * efficiency. First we make sure there is
- * enough space for the result, which may be bigger
- * than the expression if we add exponentation. Next we
- * scan backwards looking for the start of arithmetic. If the
- * next previous character is a CTLESC character, then we
- * have to rescan starting from the beginning since CTLESC
- * characters have to be processed left to right.
+ * efficiency. Next we scan backwards looking for the
+ * start of arithmetic.
*/
- CHECKSTRSPACE(10, expdest);
- USTPUTC('\0', expdest);
start = stackblock();
p = expdest - 1;
- while (*p != CTLARI && p >= start)
- --p;
- if (*p != CTLARI)
+ *p = '\0';
+ p--;
+ do {
+ int esc;
+
+ while (*p != CTLARI) {
+ p--;
+#ifdef DEBUG
+ if (p < start) {
error("missing CTLARI (shouldn't happen)");
- if (p > start && *(p-1) == CTLESC)
- for (p = start; *p != CTLARI; p++)
- if (*p == CTLESC)
- p++;
+ }
+#endif
+ }
+
+ esc = esclen(start, p);
+ if (!(esc % 2)) {
+ break;
+ }
+
+ p -= esc + 1;
+ } while (1);
if (p[1] == '"')
quoted=1;
@@ -4941,22 +4952,22 @@
removerecordregions(begoff);
if (quotes)
rmescapes(p+2);
- result = arith(p+2, &errcode);
+
+ start = grabstackstr(expdest);
+ result = arith(p + 2, &errcode);
if (errcode < 0) {
if(errcode == -2)
- error("divide by zero");
+ error("arithmetic expression: division by zero: \"%s \"", p+2);
else
- error("syntax error: \"%s\"\n", p+2);
+ error("arith: syntax error: \"%s \"\n", p+2);
}
- snprintf(p, 12, "%d", result);
+ ungrabstackstr(start, p);
+ expdest = p;
- while (*p++)
- ;
+ cvtnum(result);
if (quoted == 0)
- recordregion(begoff, p - 1 - start, 0);
- result = expdest - p + 1;
- STADJUST(-result, expdest);
+ recordregion(begoff, expdest - stackblock(), 0);
}
#endif
-------------- next part --------------
--- ash.c.orig Mon Dec 10 15:59:13 2001
+++ ash.c Mon Dec 10 16:08:07 2001
@@ -4440,7 +4440,8 @@
static void expbackq (union node *, int, int);
static const char *subevalvar (char *, char *, int, int, int, int, int);
static int varisset (char *, int);
-static void strtodest (const char *, const char *, int);
+static void memtodest(const char *, size_t, const char *, int);
+static inline void strtodest (const char *, const char *, int);
static void varvalue (char *, int, int);
static void recordregion (int, int, int);
static void removerecordregions (int);
@@ -4976,99 +4977,71 @@
*/
static void
-expbackq(cmd, quoted, flag)
+expbackq(cmd, quoted, quotes)
union node *cmd;
int quoted;
- int flag;
+ int quotes;
{
- volatile struct backcmd in;
+ struct backcmd in;
int i;
char buf[128];
char *p;
char *dest = expdest;
- volatile struct ifsregion saveifs;
- struct ifsregion *volatile savelastp;
- struct nodelist *volatile saveargbackq;
- char lastc;
+ struct ifsregion saveifs;
+ struct ifsregion *savelastp;
+ struct nodelist *saveargbackq;
int startloc = dest - stackblock();
char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
- volatile int saveherefd;
- int quotes = flag & (EXP_FULL | EXP_CASE);
- struct jmploc jmploc;
- struct jmploc *volatile savehandler;
- int ex;
-
-#if __GNUC__
- /* Avoid longjmp clobbering */
- (void) &dest;
- (void) &syntax;
-#endif
+ int saveherefd;
in.fd = -1;
in.buf = 0;
in.jp = 0;
- INTOFF;
saveifs = ifsfirst;
savelastp = ifslastp;
saveargbackq = argbackq;
saveherefd = herefd;
herefd = -1;
- if ((ex = setjmp(jmploc.loc))) {
- goto err1;
- }
- savehandler = handler;
- handler = &jmploc;
- INTON;
p = grabstackstr(dest);
+
+ INTOFF;
evalbackcmd(cmd, (struct backcmd *) &in);
ungrabstackstr(p, dest);
-err1:
- INTOFF;
ifsfirst = saveifs;
ifslastp = savelastp;
argbackq = saveargbackq;
herefd = saveherefd;
- if (ex) {
- goto err2;
- }
p = in.buf;
- lastc = '\0';
+ i = in.nleft;
+ if (i == 0)
+ goto read;
for (;;) {
- if (--in.nleft < 0) {
+ memtodest(p, i, syntax, quotes);
+read:
if (in.fd < 0)
break;
- i = safe_read(in.fd, buf, sizeof buf);
+ while ((i = safe_read(in.fd, buf, sizeof buf)) < 0 && errno == EINTR);
TRACE(("expbackq: read returns %d\n", i));
if (i <= 0)
break;
p = buf;
- in.nleft = i - 1;
- }
- lastc = *p++;
- if (lastc != '\0') {
- if (quotes && syntax[(int)lastc] == CCTL)
- STPUTC(CTLESC, dest);
- STPUTC(lastc, dest);
- }
}
+ dest = expdest;
+
/* Eat all trailing newlines */
for (; dest > stackblock() && dest[-1] == '\n';)
STUNPUTC(dest);
-err2:
if (in.fd >= 0)
close(in.fd);
if (in.buf)
ckfree(in.buf);
if (in.jp)
exitstatus = waitforjob(in.jp);
- handler = savehandler;
- if (ex) {
- longjmp(handler->loc, 1);
- }
+ INTON;
if (quoted == 0)
recordregion(startloc, dest - stackblock(), 0);
TRACE(("evalbackq: size=%d: \"%.*s\"\n",
@@ -5076,7 +5049,6 @@
(dest - stackblock()) - startloc,
stackblock() + startloc));
expdest = dest;
- INTON;
}
static char *
@@ -5273,16 +5245,31 @@
*/
static void
+memtodest(const char *p, size_t len, const char *syntax, int quotes) {
+ char *q = expdest;
+
+ CHECKSTRSPACE(len * 2, q);
+
+ while (len--) {
+ int c = *p++;
+ if (!c)
+ continue;
+ if (quotes && (syntax[c] == CCTL || syntax[c] == CBACK))
+ USTPUTC(CTLESC, q);
+ USTPUTC(c, q);
+ }
+
+ expdest = q;
+}
+
+
+static inline void
strtodest(p, syntax, quotes)
const char *p;
const char *syntax;
int quotes;
{
- while (*p) {
- if (quotes && syntax[(int) *p] == CCTL)
- STPUTC(CTLESC, expdest);
- STPUTC(*p++, expdest);
- }
+ memtodest(p, strlen(p), syntax, quotes);
}
/*
-------------- next part --------------
--- ash.c.orig Mon Dec 10 15:13:52 2001
+++ ash.c Mon Dec 10 15:18:00 2001
@@ -4793,11 +4801,21 @@
int flag;
{
char c, *startp = p;
+ char *name;
struct passwd *pw;
const char *home;
int quotes = flag & (EXP_FULL | EXP_CASE);
+ int startloc;
- while ((c = *p) != '\0') {
+ if (*p == CTLESC && (flag & EXP_QWORD)) {
+ p++;
+ }
+ if (*p != '~') {
+ return startp;
+ }
+ name = p + 1;
+
+ while ((c = *++p) != '\0') {
switch(c) {
case CTLESC:
return (startp);
@@ -4808,24 +4826,26 @@
goto done;
break;
case '/':
+ case CTLENDVAR:
goto done;
}
- p++;
}
done:
*p = '\0';
- if (*(startp+1) == '\0') {
+ if (*name == '\0') {
if ((home = lookupvar("HOME")) == NULL)
goto lose;
} else {
- if ((pw = getpwnam(startp+1)) == NULL)
+ if ((pw = getpwnam(name)) == NULL)
goto lose;
home = pw->pw_dir;
}
if (*home == '\0')
goto lose;
*p = c;
+ startloc = expdest - stackblock();
strtodest(home, SQSYNTAX, quotes);
+ recordregion(startloc, expdest - stackblock(), 0);
return (p);
lose:
*p = c;
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:41:30 2001
+++ ash.c Tue Dec 11 14:47:25 2001
@@ -6673,9 +6673,7 @@
tcsetpgrp(2, pgrp);
#endif
restartjob(jp);
- INTOFF;
status = waitforjob(jp);
- INTON;
return status;
}
-------------- next part --------------
--- ash.c.orig Mon Dec 10 16:48:30 2001
+++ ash.c Tue Dec 11 13:58:21 2001
@@ -7007,17 +7006,9 @@
setsignal(SIGTSTP);
setsignal(SIGTTOU);
} else if (mode == FORK_BG) {
- ignoresig(SIGINT);
- ignoresig(SIGQUIT);
- if ((jp == NULL || jp->nprocs == 0) &&
- ! fd0_redirected_p ()) {
- close(0);
- if (open(devnull, O_RDONLY) != 0)
- error(nullerr, devnull);
- }
- }
#else
if (mode == FORK_BG) {
+#endif
ignoresig(SIGINT);
ignoresig(SIGQUIT);
if ((jp == NULL || jp->nprocs == 0) &&
@@ -7027,7 +7018,6 @@
error(nullerr, devnull);
}
}
-#endif
for (i = njobs, p = jobtab ; --i >= 0 ; p++)
if (p->used)
freejob(p);
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:19:46 2001
+++ ash.c Sat Dec 8 19:30:34 2001
@@ -3723,7 +3723,7 @@
clearcmdentry(0);
return 0;
} else if (c == 'v' || c == 'V') {
- verbose = c;
+ verbose++;
}
}
if (*argptr == NULL) {
@@ -3737,7 +3737,7 @@
return 0;
}
c = 0;
- while ((name = *argptr++) != NULL) {
+ while ((name = *argptr) != NULL) {
if ((cmdp = cmdlookup(name, 0)) != NULL
&& (cmdp->cmdtype == CMDNORMAL
|| (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
@@ -3745,7 +3745,7 @@
#ifdef ASH_ALIAS
/* Then look at the aliases */
if ((ap = lookupalias(name, 0)) != NULL) {
- if (verbose=='v')
+ if (verbose)
printf("%s is an alias for %s\n", name, ap->val);
else
printalias(ap);
@@ -3754,7 +3754,7 @@
#endif
/* First look at the keywords */
if (findkwd(name)!=0) {
- if (verbose=='v')
+ if (verbose)
printf("%s is a shell keyword\n", name);
else
printf(snlfmt, name);
@@ -3765,9 +3765,10 @@
if (entry.cmdtype == CMDUNKNOWN) c = 1;
else if (verbose) {
cmdp = cmdlookup(name, 0);
- if (cmdp) printentry(cmdp, verbose=='v');
+ if (cmdp) printentry(cmdp, verbose);
flushall();
}
+ argptr++;
}
return c;
}
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:41:30 2001
+++ ash.c Tue Dec 11 14:45:35 2001
@@ -12320,7 +12320,7 @@
* PS1 depends on uid
*/
if ((vps1.flags & VEXPORT) == 0) {
- vpp = hashvar("PS1=");
+ vpp = hashvar("PS1=$ ");
vps1.next = *vpp;
*vpp = &vps1;
vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
-------------- next part --------------
--- ash.c.orig Fri Nov 30 12:13:07 2001
+++ ash.c Fri Nov 30 12:14:43 2001
@@ -291,15 +291,13 @@
#define INTOFF suppressint++
+#ifdef ASH_OPTIMIZE_FOR_SIZE
-#ifndef ASH_OPTIMIZE_FOR_SIZE
-#define INTON { if (--suppressint == 0 && intpending) onint(); }
-#define FORCEINTON {suppressint = 0; if (intpending) onint();}
-#else
static void __inton (void);
-static void forceinton (void);
#define INTON __inton()
-#define FORCEINTON forceinton()
+#else
+#define INTON { if (--suppressint == 0 && intpending) onint(); }
#endif
+#define FORCEINTON {suppressint = 0; if (intpending) onint();}
#define CLEAR_PENDING_INT intpending = 0
#define int_pending() intpending
@@ -2295,11 +2293,6 @@
if (--suppressint == 0 && intpending) {
onint();
}
-}
-static void forceinton (void) {
- suppressint = 0;
- if (intpending)
- onint();
}
#endif
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:00:25 2001
+++ ash.c Tue Dec 11 14:18:19 2001
@@ -1230,7 +1230,7 @@
static void readcmdfile (const char *);
static int number (const char *);
-static int is_number (const char *, int *num);
+static int is_number (const char *);
static char *single_quote (const char *);
static int nextopt (const char *);
@@ -6868,7 +6868,8 @@
if (found)
return found;
}
- } else if (is_number(name, &pid)) {
+ } else if (is_number(name)) {
+ pid = number(name);
for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
if (jp->used && jp->nprocs > 0
&& jp->ps[jp->nprocs - 1].pid == pid)
@@ -8483,19 +8484,12 @@
*/
static int
-is_number(const char *p, int *intptr)
+is_number(const char *p)
{
- int ret = 0;
-
do {
if (! is_digit(*p))
return 0;
- ret *= 10;
- ret += digit_val(*p);
- p++;
- } while (*p != '\0');
-
- *intptr = ret;
+ } while (*++p != '\0');
return 1;
}
@@ -8507,10 +8501,9 @@
static int
number(const char *s)
{
- int i;
- if (! is_number(s, &i))
+ if (! is_number(s))
error("Illegal number: %s", s);
- return i;
+ return atoi(s);
}
/*
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:48:01 2001
+++ ash.c Tue Dec 11 14:51:16 2001
@@ -1626,6 +1626,9 @@
static int histcmd (int, char **);
static int hashcmd (int, char **);
static int helpcmd (int, char **);
+#ifdef JOBS
+static int jobidcmd (int, char **);
+#endif
static int jobscmd (int, char **);
static int localcmd (int, char **);
#ifndef BB_PWD
@@ -1720,6 +1723,9 @@
#endif
{ BUILTIN_NOSPEC "hash", hashcmd },
{ BUILTIN_NOSPEC "help", helpcmd },
+#ifdef JOBS
+ { BUILTIN_REGULAR "jobid", jobidcmd },
+#endif
{ BUILTIN_REGULAR "jobs", jobscmd },
#ifdef JOBS
{ BUILTIN_REGULAR "kill", killcmd },
@@ -6886,6 +6892,28 @@
}
}
+
+#ifdef JOBS
+static int
+jobidcmd(argc, argv)
+ int argc;
+ char **argv;
+{
+ struct job *jp;
+ int i;
+
+ jp = getjob(argv[1]);
+ printf("%s %d %ld\n", argv[1], jp->nprocs, (long)jp->ps[0].pid);
+ for (i = 0 ; i < jp->nprocs ; ) {
+ printf(
+ "%d %ld%c", i, (long)jp->ps[i].pid,
+ i+1 < jp->nprocs? ' ' : '\n'
+ );
+ i++;
+ }
+ return 0;
+}
+#endif
/*
-------------- next part --------------
--- ash.c.orig Mon Dec 10 15:21:29 2001
+++ ash.c Mon Dec 10 15:56:27 2001
@@ -1645,7 +1645,7 @@
static int ulimitcmd (int, char **);
static int timescmd (int, char **);
#ifdef ASH_MATH_SUPPORT
-static int letcmd (int, char **);
+static int expcmd (int, char **);
#endif
static int typecmd (int, char **);
#ifdef ASH_GETOPTS
@@ -1704,6 +1704,9 @@
{ BUILTIN_SPECIAL "eval", evalcmd },
{ BUILTIN_SPECIAL "exec", execcmd },
{ BUILTIN_SPECIAL "exit", exitcmd },
+#ifdef ASH_MATH_SUPPORT
+ { BUILTIN_REGULAR "exp", expcmd },
+#endif
{ BUILTIN_SPEC_ASSG "export", exportcmd },
{ BUILTIN_REGULAR "false", false_main },
{ BUILTIN_REGULAR "fc", histcmd },
@@ -1720,7 +1723,7 @@
{ BUILTIN_REGULAR "kill", killcmd },
#endif
#ifdef ASH_MATH_SUPPORT
- { BUILTIN_REGULAR "let", letcmd },
+ { BUILTIN_REGULAR "let", expcmd },
#endif
{ BUILTIN_ASSIGN "local", localcmd },
#ifndef BB_PWD
@@ -12864,38 +12875,48 @@
}
#ifdef ASH_MATH_SUPPORT
-/* The let builtin. */
-int letcmd(int argc, char **argv)
+/*
+ * The exp/let builtin.
+ */
+int expcmd(int argc, char **argv)
{
+ const char *p;
+ char *concat;
+ char **ap;
int errcode;
- long result=0;
- if (argc == 2) {
- char *tmp, *expression, p[13];
- expression = strchr(argv[1], '=');
- if (!expression) {
- /* Cannot use 'error()' here, or the return code
- * will be incorrect */
- out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
- return 0;
+ long i;
+
+ if (argc > 1) {
+ p = argv[1];
+ if (argc > 2) {
+ /*
+ * concatenate arguments
+ */
+ STARTSTACKSTR(concat);
+ ap = argv + 2;
+ for (;;) {
+ while (*p)
+ STPUTC(*p++, concat);
+ if ((p = *ap++) == NULL)
+ break;
+ STPUTC(' ', concat);
}
- *expression = '\0';
- tmp = ++expression;
- result = arith(tmp, &errcode);
+ STPUTC('\0', concat);
+ p = grabstackstr(concat);
+ }
+ } else
+ p = "";
+
+ i = arith(p, &errcode);
if (errcode < 0) {
- /* Cannot use 'error()' here, or the return code
- * will be incorrect */
- out2fmt("sh: let: ");
if(errcode == -2)
- out2fmt("divide by zero");
+ error("arithmetic expression: division by zero: \"%s\"", p);
else
- out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
- return 0;
+ error("syntax error: \"%s\"\n", p);
}
- snprintf(p, 12, "%ld", result);
- setvar(argv[1], savestr(p), 0);
- } else if (argc >= 3)
- synerror("invalid operand");
- return !result;
+
+ printf("%ld\n", i);
+ return (! i);
}
#endif
-------------- next part --------------
--- ash.c.orig Fri Nov 30 12:04:36 2001
+++ ash.c Fri Nov 30 12:08:34 2001
@@ -2115,10 +2115,8 @@
* Called from trap.c when a SIGINT is received. (If the user specifies
* that SIGINT is to be trapped or ignored using the trap builtin, then
* this routine is not called.) Suppressint is nonzero when interrupts
- * are held using the INTOFF macro. The call to _exit is necessary because
- * there is a short period after a fork before the signal handlers are
- * set to the appropriate value for the child. (The test for iflag is
- * just defensive programming.)
+ * are held using the INTOFF macro. (The test for iflag is just
+ * defensive programming.)
*/
static void
@@ -2132,12 +2130,11 @@
intpending = 0;
sigemptyset(&mysigset);
sigprocmask(SIG_SETMASK, &mysigset, NULL);
- if (rootshell && iflag)
- exraise(EXINT);
- else {
+ if (!(rootshell && iflag)) {
signal(SIGINT, SIG_DFL);
raise(SIGINT);
}
+ exraise(EXINT);
/* NOTREACHED */
}
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:43:52 2001
+++ ash.c Mon Dec 10 15:01:22 2001
@@ -233,10 +233,10 @@
#define VSPLUS 0x3 /* ${var+text} */
#define VSQUESTION 0x4 /* ${var?message} */
#define VSASSIGN 0x5 /* ${var=text} */
-#define VSTRIMLEFT 0x6 /* ${var#pattern} */
-#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
-#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
-#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
+#define VSTRIMRIGHT 0x6 /* ${var%pattern} */
+#define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
+#define VSTRIMLEFT 0x8 /* ${var#pattern} */
+#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
#define VSLENGTH 0xa /* ${#var} */
/* values of checkkwd variable */
@@ -1222,13 +1224,8 @@
};
-#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
#define rmescapes(p) _rmescapes((p), 0)
static char *_rmescapes (char *, int);
-#else
-static void rmescapes (char *);
-#endif
-
static int casematch (union node *, const char *);
static void clearredir(void);
static void popstring(void);
@@ -4406,6 +4403,9 @@
*/
#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
+#define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
+#define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
+#define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
/*
* Structure specifying which parts of the string should be searched
@@ -4429,7 +4429,7 @@
static void argstr (char *, int);
static char *exptilde (char *, int);
static void expbackq (union node *, int, int);
-static int subevalvar (char *, char *, int, int, int, int, int);
+static const char *subevalvar (char *, char *, int, int, int, int, int);
static int varisset (char *, int);
static void strtodest (const char *, const char *, int);
static void varvalue (char *, int, int);
@@ -4439,7 +4439,7 @@
static void ifsfree (void);
static void expandmeta (struct strlist *, int);
#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
-#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
+static inline char * preglob(const char *, int, int);
#if !defined(GLOB_BROKEN)
static void addglob (const glob_t *);
#endif
@@ -4451,14 +4451,38 @@
static struct strlist *expsort (struct strlist *);
static struct strlist *msort (struct strlist *, int);
#endif
-static int patmatch (char *, char *, int);
-#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
-static int patmatch2 (char *, char *, int);
+static inline int patmatch (char *, const char *);
+#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
+static int pmatch (const char *, const char *);
#else
-static int pmatch (char *, char *, int);
-#define patmatch2 patmatch
+#define pmatch(a, b) !fnmatch((a), (b), 0)
#endif
-static char *cvtnum (int, char *);
+static void cvtnum (int);
+
+/*
+ * Prepare a pattern for a glob(3) call.
+ *
+ * Returns an stalloced string.
+ */
+
+static inline char *
+preglob(const char *pattern, int quoted, int flag) {
+ flag |= RMESCAPE_GLOB;
+ if (quoted) {
+ flag |= RMESCAPE_QUOTED;
+ }
+ return _rmescapes((char *)pattern, flag);
+}
+
+static size_t
+esclen(const char *start, const char *p) {
+ size_t esc = 0;
+
+ while (p > start && *--p == CTLESC) {
+ esc++;
+ }
+ return esc;
+}
/*
* Expand shell variables and backquotes inside a here document.
@@ -4602,7 +4626,7 @@
switch (subtype) {
case VSLENGTH:
- cvtnum(varlen, expdest);
+ cvtnum(varlen);
goto record;
case VSNORMAL:
@@ -5026,7 +5115,74 @@
INTON;
}
-static int
+static char *
+scanleft(
+ char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+ int zero
+) {
+ char *loc;
+ char *loc2;
+ char c;
+
+ loc = startp;
+ loc2 = rmesc;
+ do {
+ int match;
+ const char *s = loc2;
+ c = *loc2;
+ if (zero) {
+ *loc2 = '\0';
+ s = rmesc;
+ }
+ match = pmatch(str, s);
+ *loc2 = c;
+ if (match)
+ return loc;
+ if (quotes && *loc == CTLESC)
+ loc++;
+ loc++;
+ loc2++;
+ } while (c);
+ return 0;
+}
+
+
+static char *
+scanright(
+ char *startp, char *rmesc, char *rmescend, char *str, int quotes,
+ int zero
+) {
+ int esc = 0;
+ char *loc;
+ char *loc2;
+
+ for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
+ int match;
+ char c = *loc2;
+ const char *s = loc2;
+ if (zero) {
+ *loc2 = '\0';
+ s = rmesc;
+ }
+ match = pmatch(str, s);
+ *loc2 = c;
+ if (match)
+ return loc;
+ loc--;
+ if (quotes) {
+ if (--esc < 0) {
+ esc = esclen(startp, loc);
+ }
+ if (esc % 2) {
+ esc--;
+ loc--;
+ }
+ }
+ }
+ return 0;
+}
+
+static const char *
subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
char *p;
char *str;
@@ -5037,31 +5193,27 @@
int quotes;
{
char *startp;
- char *loc = NULL;
- char *q;
- int c = 0;
+ char *loc;
int saveherefd = herefd;
struct nodelist *saveargbackq = argbackq;
int amount;
+ char *rmesc, *rmescend;
+ int zero;
+ char *(*scan)(char *, char *, char *, char *, int , int);
herefd = -1;
argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
- STACKSTRNUL(expdest);
+ STPUTC('\0', expdest);
herefd = saveherefd;
argbackq = saveargbackq;
startp = stackblock() + startloc;
- if (str == NULL)
- str = stackblock() + strloc;
switch (subtype) {
case VSASSIGN:
setvar(str, startp, 0);
amount = startp - expdest;
STADJUST(amount, expdest);
- varflags &= ~VSNUL;
- if (c != 0)
- *loc = c;
- return 1;
+ return startp;
case VSQUESTION:
if (*p != CTLENDVAR) {
@@ -5072,84 +5224,45 @@
str, (varflags & VSNUL) ? "null or "
: nullstr);
/* NOTREACHED */
-
- case VSTRIMLEFT:
- for (loc = startp; loc < str; loc++) {
- c = *loc;
- *loc = '\0';
- if (patmatch2(str, startp, quotes))
- goto recordleft;
- *loc = c;
- if (quotes && *loc == CTLESC)
- loc++;
}
- return 0;
-
- case VSTRIMLEFTMAX:
- for (loc = str - 1; loc >= startp;) {
- c = *loc;
- *loc = '\0';
- if (patmatch2(str, startp, quotes))
- goto recordleft;
- *loc = c;
- loc--;
- if (quotes && loc > startp && *(loc - 1) == CTLESC) {
- for (q = startp; q < loc; q++)
- if (*q == CTLESC)
- q++;
- if (q > loc)
- loc--;
- }
- }
- return 0;
-
- case VSTRIMRIGHT:
- for (loc = str - 1; loc >= startp;) {
- if (patmatch2(str, loc, quotes))
- goto recordright;
- loc--;
- if (quotes && loc > startp && *(loc - 1) == CTLESC) {
- for (q = startp; q < loc; q++)
- if (*q == CTLESC)
- q++;
- if (q > loc)
- loc--;
- }
- }
- return 0;
-
- case VSTRIMRIGHTMAX:
- for (loc = startp; loc < str - 1; loc++) {
- if (patmatch2(str, loc, quotes))
- goto recordright;
- if (quotes && *loc == CTLESC)
- loc++;
- }
- return 0;
+ subtype -= VSTRIMRIGHT;
#ifdef DEBUG
- default:
+ if (subtype < 0 || subtype > 3)
abort();
#endif
+
+ rmesc = startp;
+ rmescend = stackblock() + strloc;
+ if (quotes) {
+ rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
+ if (rmesc != startp) {
+ rmescend = expdest;
+ startp = stackblock() + startloc;
+ }
}
+ rmescend--;
+ str = stackblock() + strloc;
+ preglob(str, varflags & VSQUOTE, 0);
-recordleft:
- *loc = c;
- amount = ((str - 1) - (loc - startp)) - expdest;
- STADJUST(amount, expdest);
- while (loc != str - 1)
- *startp++ = *loc++;
- return 1;
+ /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
+ zero = subtype >> 1;
+ /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
+ scan = (subtype & 1) ^ zero ? scanleft : scanright;
-recordright:
+ loc = scan(startp, rmesc, rmescend, str, quotes, zero);
+ if (loc) {
+ if (zero) {
+ memmove(startp, loc, str - loc);
+ loc = startp + (str - loc) - 1;
+ }
+ *loc = '\0';
amount = loc - expdest;
STADJUST(amount, expdest);
- STPUTC('\0', expdest);
- STADJUST(-1, expdest);
- return 1;
+ }
+ return loc;
}
-
/*
* Test whether a specialized variable is set.
*/
@@ -5242,7 +5355,7 @@
case '!':
num = backgndpid;
numvar:
- expdest = cvtnum(num, expdest);
+ cvtnum(num);
break;
case '-':
for (i = 0 ; i < NOPTS ; i++) {
@@ -5453,7 +5566,7 @@
while (str) {
if (fflag)
goto nometa;
- p = preglob(str->text);
+ p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_GROW);
INTOFF;
switch (glob(p, 0, 0, &pglob)) {
case 0:
@@ -5755,44 +5868,17 @@
* Returns true if the pattern matches the string.
*/
-#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
-/* squoted: string might have quote chars */
-static int
-patmatch(char *pattern, char *string, int squoted)
-{
- const char *p;
- char *q;
-
- p = preglob(pattern);
- q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
-
- return !fnmatch(p, q, 0);
-}
-
-
-static int
-patmatch2(char *pattern, char *string, int squoted)
+static inline int
+patmatch(char *pattern, const char *string)
{
- char *p;
- int res;
-
- sstrnleft--;
- p = grabstackstr(expdest);
- res = patmatch(pattern, string, squoted);
- ungrabstackstr(p, expdest);
- return res;
-}
-#else
-static int
-patmatch(char *pattern, char *string, int squoted) {
- return pmatch(pattern, string, squoted);
+ return pmatch(preglob(pattern, 0, 0), string);
}
-
+#if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
static int
pmatch(char *pattern, char *string, int squoted)
{
- char *p, *q;
+ const char *p, *q;
char c;
p = pattern;
@@ -5801,46 +5887,33 @@
switch (c = *p++) {
case '\0':
goto breakloop;
- case CTLESC:
- if (squoted && *q == CTLESC)
- q++;
- if (*q++ != *p++)
- return 0;
- break;
- case CTLQUOTEMARK:
- continue;
+ case '\\':
+ if (*p) {
+ c = *p++;
+ }
+ goto dft;
case '?':
- if (squoted && *q == CTLESC)
- q++;
if (*q++ == '\0')
return 0;
break;
case '*':
c = *p;
- while (c == CTLQUOTEMARK || c == '*')
+ while (c == '*')
c = *++p;
- if (c != CTLESC && c != CTLQUOTEMARK &&
- c != '?' && c != '*' && c != '[') {
+ if (c != '\\' && c != '?' && c != '*' && c != '[') {
while (*q != c) {
- if (squoted && *q == CTLESC &&
- q[1] == c)
- break;
if (*q == '\0')
return 0;
- if (squoted && *q == CTLESC)
- q++;
q++;
}
}
do {
- if (pmatch(p, q, squoted))
+ if (pmatch(p, q))
return 1;
- if (squoted && *q == CTLESC)
- q++;
} while (*q++ != '\0');
return 0;
case '[': {
- char *endp;
+ const char *endp;
int invert, found;
char chr;
@@ -5848,11 +5921,9 @@
if (*endp == '!')
endp++;
for (;;) {
- while (*endp == CTLQUOTEMARK)
- endp++;
if (*endp == '\0')
goto dft; /* no matching ] */
- if (*endp == CTLESC)
+ if (*endp == '\\')
endp++;
if (*++endp == ']')
break;
@@ -5864,21 +5935,15 @@
}
found = 0;
chr = *q++;
- if (squoted && chr == CTLESC)
- chr = *q++;
if (chr == '\0')
return 0;
c = *p++;
do {
- if (c == CTLQUOTEMARK)
- continue;
- if (c == CTLESC)
+ if (c == '\\')
c = *p++;
if (*p == '-' && p[1] != ']') {
p++;
- while (*p == CTLQUOTEMARK)
- p++;
- if (*p == CTLESC)
+ if (*p == '\\')
p++;
if (chr >= c && chr <= *p)
found = 1;
@@ -5893,8 +5958,6 @@
break;
}
dft: default:
- if (squoted && *q == CTLESC)
- q++;
if (*q++ != c)
return 0;
break;
@@ -5913,12 +5976,16 @@
* Remove any CTLESC characters from a string.
*/
-#if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
static char *
-_rmescapes(char *str, int flag)
+_rmescapes(str, flag)
+ char *str;
+ int flag;
{
char *p, *q, *r;
static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
+ unsigned inquotes;
+ int notescaped;
+ int globbing;
p = strpbrk(str, qchars);
if (!p) {
@@ -5928,54 +5995,57 @@
r = str;
if (flag & RMESCAPE_ALLOC) {
size_t len = p - str;
- q = r = stalloc(strlen(p) + len + 1);
+ size_t fulllen = len + strlen(p) + 1;
+
+ r = stalloc(fulllen);
+#if 0
+ /* Why doesn't RMESCAPE_GROW work right? */
+ if (flag & RMESCAPE_GROW) {
+ CHECKSTRSPACE(fulllen, expdest);
+ r = expdest;
+ } else if (flag & RMESCAPE_HEAP) {
+ r = ckmalloc(fulllen);
+ } else {
+ r = stalloc(fulllen);
+ }
+#endif
+ q = r;
if (len > 0) {
memcpy(q, str, len);
q += len;
}
}
+ inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
+ globbing = flag & RMESCAPE_GLOB;
+ notescaped = globbing;
while (*p) {
if (*p == CTLQUOTEMARK) {
+ inquotes = ~inquotes;
p++;
+ notescaped = globbing;
continue;
}
+ if (*p == '\\') {
+ /* naked back slash */
+ notescaped = 0;
+ goto copy;
+ }
if (*p == CTLESC) {
p++;
- if (flag & RMESCAPE_GLOB && *p != '/') {
+ if (notescaped && inquotes && *p != '/') {
*q++ = '\\';
}
}
+ notescaped = globbing;
+copy:
*q++ = *p++;
}
*q = '\0';
- return r;
-}
-#else
-static void
-rmescapes(str)
- char *str;
-{
- char *p, *q;
-
- p = str;
- while (*p != CTLESC && *p != CTLQUOTEMARK) {
- if (*p++ == '\0')
- return;
- }
- q = p;
- while (*p) {
- if (*p == CTLQUOTEMARK) {
- p++;
- continue;
- }
- if (*p == CTLESC)
- p++;
- *q++ = *p++;
+ if (flag & RMESCAPE_GROW) {
+ STADJUST(q - r + 1, expdest);
}
- *q = '\0';
+ return r;
}
-#endif
-
/*
@@ -5996,7 +6066,7 @@
argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
STPUTC('\0', expdest);
p = grabstackstr(expdest);
- result = patmatch(p, (char *)val, 0);
+ result = patmatch(p, (char *)val);
popstackmark(&smark);
return result;
}
@@ -6005,18 +6075,15 @@
* Our own itoa().
*/
-static char *
-cvtnum(num, buf)
- int num;
- char *buf;
- {
+static void
+cvtnum(int num) {
int len;
- CHECKSTRSPACE(32, buf);
- len = sprintf(buf, "%d", num);
- STADJUST(len, buf);
- return buf;
+ CHECKSTRSPACE(32, expdest);
+ len = snprintf(expdest, 32, "%d", num);
+ STADJUST(len, expdest);
}
+
/*
* Editline and history functions (and glue).
*/
@@ -10186,7 +10253,7 @@
loop: { /* for each line, until end of word */
CHECKEND(); /* set c to PEOF if at end of here document */
for (;;) { /* until end of line or end of word */
- CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
+ CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
switch(syntax[c]) {
case CNL: /* '\n' */
if (syntax == BASESYNTAX)
@@ -10203,14 +10270,14 @@
USTPUTC(c, out);
break;
case CCTL:
- if ((eofmark == NULL || dblquote) &&
- dqvarnest == 0)
+ if (eofmark == NULL || dblquote)
USTPUTC(CTLESC, out);
USTPUTC(c, out);
break;
case CBACK: /* backslash */
c = pgetc2();
if (c == PEOF) {
+ USTPUTC(CTLESC, out);
USTPUTC('\\', out);
pungetc();
} else if (c == '\n') {
@@ -10219,42 +10286,45 @@
else
setprompt(0);
} else {
- if (dblquote && c != '\\' && c != '`' && c != '$'
- && (c != '"' || eofmark != NULL))
+ if (
+ dblquote &&
+ c != '\\' && c != '`' &&
+ c != '$' && (
+ c != '"' ||
+ eofmark != NULL
+ )
+ ) {
+ USTPUTC(CTLESC, out);
USTPUTC('\\', out);
+ }
if (SQSYNTAX[c] == CCTL)
USTPUTC(CTLESC, out);
- else if (eofmark == NULL)
- USTPUTC(CTLQUOTEMARK, out);
USTPUTC(c, out);
quotef++;
}
break;
case CSQUOTE:
- if (eofmark == NULL)
- USTPUTC(CTLQUOTEMARK, out);
syntax = SQSYNTAX;
+quotemark:
+ if (eofmark == NULL) {
+ USTPUTC(CTLQUOTEMARK, out);
+ }
break;
case CDQUOTE:
- if (eofmark == NULL)
- USTPUTC(CTLQUOTEMARK, out);
syntax = DQSYNTAX;
dblquote = 1;
- break;
+ goto quotemark;
case CENDQUOTE:
if (eofmark != NULL && arinest == 0 &&
varnest == 0) {
USTPUTC(c, out);
} else {
- if (arinest) {
- syntax = ARISYNTAX;
- dblquote = 0;
- } else if (eofmark == NULL &&
- dqvarnest == 0) {
+ if (dqvarnest == 0) {
syntax = BASESYNTAX;
dblquote = 0;
}
quotef++;
+ goto quotemark;
}
break;
case CVAR: /* '$' */
@@ -10313,10 +10383,10 @@
if (varnest == 0)
goto endword; /* exit outer loop */
#ifdef ASH_ALIAS
- if (c != PEOA)
-#endif
+ if (c != PEOA) {
USTPUTC(c, out);
-
+ }
+#endif
}
c = pgetc_macro();
}
@@ -10551,7 +10621,7 @@
*(stackblock() + typeloc) = subtype | flags;
if (subtype != VSNORMAL) {
varnest++;
- if (dblquote) {
+ if (dblquote || arinest) {
dqvarnest++;
}
}
-------------- next part --------------
--- ash.c.orig Mon Dec 10 16:48:30 2001
+++ ash.c Mon Dec 10 16:49:33 2001
@@ -6099,8 +6099,7 @@
/* from input.c: */
{
- if (exception != EXSHELLPROC)
- parselleft = parsenleft = 0; /* clear input buffer */
+ parselleft = parsenleft = 0; /* clear input buffer */
popallfiles();
}
-------------- next part --------------
--- ash.c.orig Tue Dec 11 14:23:29 2001
+++ ash.c Tue Dec 11 14:24:17 2001
@@ -239,6 +239,11 @@
#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
#define VSLENGTH 0xa /* ${#var} */
+/* values of checkkwd variable */
+#define CHKALIAS 0x1
+#define CHKKWD 0x2
+#define CHKNL 0x4
+
/* flags passed to redirect */
#define REDIR_PUSH 01 /* save previous values of file descriptors */
#define REDIR_BACKQ 02 /* save the command output to pipe */
@@ -6207,7 +6212,7 @@
if (sp->ap) {
if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
if (!checkalias) {
- checkalias = 1;
+ checkalias |= CHKALIAS;
}
}
if (sp->string != sp->ap->val) {
@@ -9411,7 +9416,7 @@
union node *n1, *n2, *n3;
int tok;
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
if (nlflag == 0 && tokendlist[peektoken()])
return NULL;
n1 = NULL;
@@ -9454,7 +9459,7 @@
} else {
tokpushback++;
}
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
if (tokendlist[peektoken()])
return n1;
break;
@@ -9480,7 +9485,7 @@
union node *n1, *n2, *n3;
int t;
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
n1 = pipeline();
for (;;) {
if ((t = readtoken()) == TAND) {
@@ -9491,7 +9496,7 @@
tokpushback++;
return n1;
}
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
n2 = pipeline();
n3 = (union node *)stalloc(sizeof (struct nbinary));
n3->type = t;
@@ -9513,7 +9518,7 @@
TRACE(("pipeline: entered\n"));
if (readtoken() == TNOT) {
negate = !negate;
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
} else
tokpushback++;
n1 = command();
@@ -9527,7 +9532,7 @@
do {
prev = lp;
lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
lp->n = command();
prev->next = lp;
} while (readtoken() == TPIPE);
@@ -9592,7 +9597,7 @@
}
if (readtoken() != TFI)
synexpect(TFI);
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
case TWHILE:
case TUNTIL: {
@@ -9607,7 +9612,7 @@
n1->nbinary.ch2 = list(0);
if (readtoken() != TDONE)
synexpect(TDONE);
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
}
case TFOR:
@@ -9616,7 +9621,7 @@
n1 = (union node *)stalloc(sizeof (struct nfor));
n1->type = NFOR;
n1->nfor.var = wordtext;
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
if (readtoken() == TIN) {
app = ≈
while (readtoken() == TWORD) {
@@ -9647,13 +9652,13 @@
if (lasttoken != TNL && lasttoken != TSEMI)
tokpushback++;
}
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
if (readtoken() != TDO)
synexpect(TDO);
n1->nfor.body = list(0);
if (readtoken() != TDONE)
synexpect(TDONE);
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
case TCASE:
n1 = (union node *)stalloc(sizeof (struct ncase));
@@ -9666,12 +9671,13 @@
n2->narg.backquote = backquotelist;
n2->narg.next = NULL;
do {
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
} while (readtoken() == TNL);
if (lasttoken != TIN)
synerror("expecting \"in\"");
cpp = &n1->ncase.cases;
- checkkwd = 2, readtoken();
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
+ readtoken();
do {
if (lasttoken == TLP)
readtoken();
@@ -9683,7 +9689,8 @@
ap->type = NARG;
ap->narg.text = wordtext;
ap->narg.backquote = backquotelist;
- if (checkkwd = 2, readtoken() != TPIPE)
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
+ if (readtoken() != TPIPE)
break;
app = &ap->narg.next;
readtoken();
@@ -9693,17 +9700,19 @@
synexpect(TRP);
cp->nclist.body = list(0);
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
if ((t = readtoken()) != TESAC) {
if (t != TENDCASE)
synexpect(TENDCASE);
- else
- checkkwd = 2, readtoken();
+ else {
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
+ readtoken();
+ }
}
cpp = &cp->nclist.next;
} while(lasttoken != TESAC);
*cpp = NULL;
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
case TLP:
n1 = (union node *)stalloc(sizeof (struct nredir));
@@ -9712,13 +9721,13 @@
n1->nredir.redirect = NULL;
if (readtoken() != TRP)
synexpect(TRP);
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
case TBEGIN:
n1 = list(0);
if (readtoken() != TEND)
synexpect(TEND);
- checkkwd = 1;
+ checkkwd = CHKKWD | CHKALIAS;
break;
/* Handle an empty command like other simple commands. */
case TSEMI:
@@ -9735,6 +9744,7 @@
if (!redir)
synexpect(-1);
case TWORD:
+ case TREDIR:
tokpushback++;
n1 = simplecmd();
return n1;
@@ -9771,6 +9781,7 @@
union node *n = NULL;
union node *vars, **vpp;
union node **rpp, *redir;
+ int savecheckkwd;
args = NULL;
app = &args;
@@ -9779,27 +9790,28 @@
redir = NULL;
rpp = &redir;
- checkalias = 2;
+ savecheckkwd = CHKALIAS;
for (;;) {
+ checkkwd = savecheckkwd;
switch (readtoken()) {
case TWORD:
- case TASSIGN:
n = (union node *)stalloc(sizeof (struct narg));
n->type = NARG;
n->narg.text = wordtext;
n->narg.backquote = backquotelist;
- if (lasttoken == TWORD) {
- *app = n;
- app = &n->narg.next;
- } else {
+ if (savecheckkwd && isassignment(wordtext)) {
*vpp = n;
vpp = &n->narg.next;
+ } else {
+ *app = n;
+ app = &n->narg.next;
+ savecheckkwd = 0;
}
break;
case TREDIR:
*rpp = n = redirnode;
rpp = &n->nfile.next;
- parsefname(); /* read name of redirection file */
+ parsefname(); /* read name of redirection file */
break;
case TLP:
if (
@@ -9810,7 +9822,7 @@
if (readtoken() != TRP)
synexpect(TRP);
n->type = NDEFUN;
- checkkwd = 2;
+ checkkwd = CHKNL | CHKKWD | CHKALIAS;
n->narg.next = command();
return n;
}
@@ -9941,13 +9953,6 @@
static int
readtoken() {
int t;
-
-#ifdef ASH_ALIAS
- int savecheckalias = checkalias;
- int savecheckkwd = checkkwd;
- struct alias *ap;
-#endif
-
#ifdef DEBUG
int alreadyseen = tokpushback;
#endif
@@ -9955,65 +9960,53 @@
#ifdef ASH_ALIAS
top:
#endif
-
t = xxreadtoken();
-#ifdef ASH_ALIAS
- checkalias = savecheckalias;
-#endif
-
- if (checkkwd) {
- /*
- * eat newlines
- */
- if (checkkwd == 2) {
- checkkwd = 0;
- while (t == TNL) {
- parseheredoc();
- t = xxreadtoken();
- }
+ /*
+ * eat newlines
+ */
+ if (checkkwd & CHKNL) {
+ while (t == TNL) {
+ parseheredoc();
+ t = xxreadtoken();
}
- checkkwd = 0;
- /*
- * check for keywords
- */
- if (t == TWORD && !quoteflag)
- {
- const char *const *pp;
+ }
- if ((pp = findkwd(wordtext))) {
- lasttoken = t = pp - parsekwd + KWDOFFSET;
- TRACE(("keyword %s recognized\n", tokname[t]));
- goto out;
- }
- }
+ if (t != TWORD || quoteflag) {
+ goto out;
}
+ /*
+ * check for keywords
+ */
+ if (checkkwd & CHKKWD) {
+ const char *const *pp;
- if (t != TWORD) {
- if (t != TREDIR) {
- checkalias = 0;
+ if ((pp = findkwd(wordtext))) {
+ lasttoken = t = pp - parsekwd + KWDOFFSET;
+ TRACE(("keyword %s recognized\n", tokname[t]));
+ goto out;
}
- } else if (checkalias == 2 && isassignment(wordtext)) {
- lasttoken = t = TASSIGN;
+ }
+
#ifdef ASH_ALIAS
- } else if (checkalias) {
- if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
+ if (checkkwd & CHKALIAS) {
+ struct alias *ap;
+ if ((ap = lookupalias(wordtext, 1)) != NULL) {
if (*ap->val) {
pushstring(ap->val, strlen(ap->val), ap);
}
- checkkwd = savecheckkwd;
goto top;
}
- checkalias = 0;
-#endif
}
+#endif
out:
+ checkkwd = 0;
#ifdef DEBUG
if (!alreadyseen)
- TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
+ TRACE(("token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
else
- TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
+ TRACE(("reread token %s %s\n", tokname[t], t == TWORD ? wordtext : ""));
#endif
return (t);
}
-------------- next part --------------
--- ash.c.orig Sat Dec 8 19:19:46 2001
+++ ash.c Sat Dec 8 19:25:57 2001
@@ -3597,8 +3597,10 @@
static void
tryexec(char *cmd, char **argv, char **envp)
{
- int e;
+ int repeated = 0;
+repeat:
+ {
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
char *name = cmd;
char** argv_l=argv;
@@ -3614,17 +3616,23 @@
optind = 1;
run_applet_by_name(name, argc_l, argv);
#endif
+ }
execve(cmd, argv, envp);
- e = errno;
- if (e == ENOEXEC) {
- INTOFF;
- initshellproc();
- setinputfile(cmd, 0);
- commandname = arg0 = savestr(argv[0]);
- setparam(argv + 1);
- exraise(EXSHELLPROC);
+ if (repeated++) {
+ ckfree(argv);
+ } else if (errno == ENOEXEC) {
+ char **ap;
+ char **new;
+
+ for (ap = argv; *ap; ap++)
+ ;
+ ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
+ *ap++ = cmd = "/bin/sh";
+ while ((*ap++ = *argv++))
+ ;
+ argv = new;
+ goto repeat;
}
- errno = e;
}
static char *commandtext (const union node *);
-------------- next part --------------
--- ash.c.orig Mon Dec 10 16:13:22 2001
+++ ash.c Mon Dec 10 16:16:14 2001
@@ -5323,7 +5323,7 @@
case '*':
sep = ifsset() ? ifsval()[0] : ' ';
if (quotes) {
- sepq = syntax[(int) sep] == CCTL;
+ sepq = syntax[(int) sep] == CCTL || syntax[(int) sep] == CBACK;
}
param:
for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
More information about the busybox
mailing list