blob: a2da540b32a945710437964e26aeba50966b4f65 [file] [log] [blame]
Eric Andersenff9eee42001-06-29 04:57:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Minix shell port for busybox
4 *
5 * This version of the Minix shell was adapted for use in busybox
Eric Andersencb81e642003-07-14 21:21:08 +00006 * by Erik Andersen <andersen@codepoet.org>
Eric Andersenff9eee42001-06-29 04:57:14 +00007 *
Eric Andersen737f5fb2003-03-14 16:05:59 +00008 * - backtick expansion did not work properly
9 * Jonas Holmberg <jonas.holmberg@axis.com>
10 * Robert Schwebel <r.schwebel@pengutronix.de>
Eric Andersencb81e642003-07-14 21:21:08 +000011 * Erik Andersen <andersen@codepoet.org>
Eric Andersen737f5fb2003-03-14 16:05:59 +000012 *
Rob Landleyc9c1a412006-07-12 19:17:55 +000013 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenff9eee42001-06-29 04:57:14 +000014 */
15
Eric Andersenff9eee42001-06-29 04:57:14 +000016#include <setjmp.h>
Eric Andersenff9eee42001-06-29 04:57:14 +000017#include <sys/times.h>
Denis Vlasenko00ccf952007-02-01 01:39:24 +000018#include "busybox.h"
Eric Andersenff9eee42001-06-29 04:57:14 +000019
Denis Vlasenko489f93e2007-02-01 01:43:16 +000020extern char **environ;
21
Eric Andersenff9eee42001-06-29 04:57:14 +000022
Mike Frysinger17811882006-05-05 20:33:07 +000023/*#define MSHDEBUG 1*/
Eric Andersen12de6cf2004-08-04 19:19:10 +000024
25#ifdef MSHDEBUG
Mike Frysinger14ff19b2006-06-20 20:37:01 +000026int mshdbg = MSHDEBUG;
Eric Andersen12de6cf2004-08-04 19:19:10 +000027
28#define DBGPRINTF(x) if(mshdbg>0)printf x
29#define DBGPRINTF0(x) if(mshdbg>0)printf x
30#define DBGPRINTF1(x) if(mshdbg>1)printf x
31#define DBGPRINTF2(x) if(mshdbg>2)printf x
32#define DBGPRINTF3(x) if(mshdbg>3)printf x
33#define DBGPRINTF4(x) if(mshdbg>4)printf x
34#define DBGPRINTF5(x) if(mshdbg>5)printf x
35#define DBGPRINTF6(x) if(mshdbg>6)printf x
36#define DBGPRINTF7(x) if(mshdbg>7)printf x
37#define DBGPRINTF8(x) if(mshdbg>8)printf x
38#define DBGPRINTF9(x) if(mshdbg>9)printf x
39
40int mshdbg_rc = 0;
41
42#define RCPRINTF(x) if(mshdbg_rc)printf x
43
44#else
45
46#define DBGPRINTF(x)
Denis Vlasenko00ccf952007-02-01 01:39:24 +000047#define DBGPRINTF0(x) ((void)0)
48#define DBGPRINTF1(x) ((void)0)
49#define DBGPRINTF2(x) ((void)0)
50#define DBGPRINTF3(x) ((void)0)
51#define DBGPRINTF4(x) ((void)0)
52#define DBGPRINTF5(x) ((void)0)
53#define DBGPRINTF6(x) ((void)0)
54#define DBGPRINTF7(x) ((void)0)
55#define DBGPRINTF8(x) ((void)0)
56#define DBGPRINTF9(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +000057
Denis Vlasenko00ccf952007-02-01 01:39:24 +000058#define RCPRINTF(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +000059
60#endif /* MSHDEBUG */
61
62
Denis Vlasenko38f63192007-01-22 09:03:07 +000063#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger2a131752006-06-06 06:26:12 +000064# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
65# define DEFAULT_USER_PROMPT "\\u:\\w$ "
66#else
67# define DEFAULT_ROOT_PROMPT "# "
68# define DEFAULT_USER_PROMPT "$ "
69#endif
70
71
Eric Andersenff9eee42001-06-29 04:57:14 +000072/* -------- sh.h -------- */
73/*
74 * shell
75 */
76
Eric Andersen12de6cf2004-08-04 19:19:10 +000077#define LINELIM 2100
78#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +000079
Eric Andersen392947c2002-12-11 07:42:46 +000080#undef NOFILE
Eric Andersen12de6cf2004-08-04 19:19:10 +000081#define NOFILE 20 /* Number of open files */
82#define NUFILE 10 /* Number of user-accessible files */
83#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +000084
85/*
86 * values returned by wait
87 */
Eric Andersen12de6cf2004-08-04 19:19:10 +000088#define WAITSIG(s) ((s)&0177)
89#define WAITVAL(s) (((s)>>8)&0377)
Eric Andersenff9eee42001-06-29 04:57:14 +000090#define WAITCORE(s) (((s)&0200)!=0)
91
92/*
Eric Andersenaff114c2004-04-14 17:51:38 +000093 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +000094 */
Eric Andersen8401eea2004-08-04 19:16:54 +000095typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +000096
97/*
98 * shell components
99 */
100
101#define QUOTE 0200
102
103#define NOBLOCK ((struct op *)NULL)
104#define NOWORD ((char *)NULL)
105#define NOWORDS ((char **)NULL)
106#define NOPIPE ((int *)NULL)
107
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000108
109/*
110 * redirection
111 */
112struct ioword {
113 short io_unit; /* unit affected */
114 short io_flag; /* action (below) */
115 char *io_name; /* file name */
116};
117
118#define IOREAD 1 /* < */
119#define IOHERE 2 /* << (here file) */
120#define IOWRITE 4 /* > */
121#define IOCAT 8 /* >> */
122#define IOXHERE 16 /* ${}, ` in << */
123#define IODUP 32 /* >&digit */
124#define IOCLOSE 64 /* >&- */
125
126#define IODEFAULT (-1) /* token for default IO unit */
127
128
Eric Andersenff9eee42001-06-29 04:57:14 +0000129/*
130 * Description of a command or an operation on commands.
131 * Might eventually use a union.
132 */
133struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000134 int type; /* operation type, see below */
135 char **words; /* arguments to a command */
136 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000137 struct op *left;
138 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000139 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000140};
141
Eric Andersen8401eea2004-08-04 19:16:54 +0000142#define TCOM 1 /* command */
143#define TPAREN 2 /* (c-list) */
144#define TPIPE 3 /* a | b */
145#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000146#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000147#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000148#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000149#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000150#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000151#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000152#define TWHILE 11
153#define TUNTIL 12
154#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000155#define TPAT 14 /* pattern in case */
156#define TBRACE 15 /* {c-list} */
157#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000158/* Added to support "." file expansion */
159#define TDOT 17
160
161/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000162#ifdef MSHDEBUG
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000163static const char *const T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000164 "PLACEHOLDER",
165 "TCOM",
166 "TPAREN",
167 "TPIPE",
168 "TLIST",
169 "TOR",
170 "TAND",
171 "TFOR",
172 "TDO",
173 "TCASE",
174 "TIF",
175 "TWHILE",
176 "TUNTIL",
177 "TELIF",
178 "TPAT",
179 "TBRACE",
180 "TASYNC",
181 "TDOT",
182};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000183#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000184
185/*
186 * actions determining the environment of a process
187 */
188#define BIT(i) (1<<(i))
Eric Andersen8401eea2004-08-04 19:16:54 +0000189#define FEXEC BIT(0) /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000190
Eric Andersen12de6cf2004-08-04 19:19:10 +0000191#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000192
Eric Andersenff9eee42001-06-29 04:57:14 +0000193/*
194 * flags to control evaluation of words
195 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000196#define DOSUB 1 /* interpret $, `, and quotes */
197#define DOBLANK 2 /* perform blank interpretation */
198#define DOGLOB 4 /* interpret [?* */
199#define DOKEY 8 /* move words with `=' to 2nd arg. list */
200#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000201
202#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
203
Eric Andersenff9eee42001-06-29 04:57:14 +0000204
Eric Andersen12de6cf2004-08-04 19:19:10 +0000205/* PROTOTYPES */
Eric Andersenff9eee42001-06-29 04:57:14 +0000206static int newfile(char *s);
Eric Andersenff9eee42001-06-29 04:57:14 +0000207
208
Eric Andersen8401eea2004-08-04 19:16:54 +0000209struct brkcon {
210 jmp_buf brkpt;
211 struct brkcon *nextlev;
212};
Eric Andersenff9eee42001-06-29 04:57:14 +0000213
Eric Andersen12de6cf2004-08-04 19:19:10 +0000214
Eric Andersenff9eee42001-06-29 04:57:14 +0000215/*
Eric Andersenff9eee42001-06-29 04:57:14 +0000216 * flags:
217 * -e: quit on error
218 * -k: look for name=value everywhere on command line
219 * -n: no execution
220 * -t: exit after reading and executing one command
221 * -v: echo as read
222 * -x: trace
223 * -u: unset variables net diagnostic
224 */
Mike Frysinger3672fe92006-11-15 21:52:10 +0000225static char flags['z' - 'a' + 1];
226/* this looks weird, but is OK ... we index flag with 'a'...'z' */
227static char *flag = flags - 'a';
Eric Andersenff9eee42001-06-29 04:57:14 +0000228
Eric Andersen8401eea2004-08-04 19:16:54 +0000229static char *null; /* null value for variable */
230static int intr; /* interrupt pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000231
Eric Andersen8401eea2004-08-04 19:16:54 +0000232static char *trap[_NSIG + 1];
233static char ourtrap[_NSIG + 1];
234static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000235
Eric Andersen8401eea2004-08-04 19:16:54 +0000236static int heedint; /* heed interrupt signals */
Eric Andersenff9eee42001-06-29 04:57:14 +0000237
Eric Andersen8401eea2004-08-04 19:16:54 +0000238static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000239
Eric Andersen8401eea2004-08-04 19:16:54 +0000240static char line[LINELIM];
241static char *elinep;
Eric Andersenff9eee42001-06-29 04:57:14 +0000242
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000243#if ENABLE_FEATURE_EDITING
244static char *current_prompt;
245static line_input_t *line_input_state;
246#endif
247
248static int areanum; /* current allocation area */
249
Eric Andersen12de6cf2004-08-04 19:19:10 +0000250
Eric Andersenff9eee42001-06-29 04:57:14 +0000251/*
252 * other functions
253 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000254static const char *rexecve(char *c, char **v, char **envp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000255static char *evalstr(char *cp, int f);
256static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000257static char *unquote(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000258static int rlookup(char *n);
259static struct wdblock *glob(char *cp, struct wdblock *wb);
260static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000261static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000262static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000263static char **eval(char **ap, int f);
264static int setstatus(int s);
265static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000266
Eric Andersen8401eea2004-08-04 19:16:54 +0000267static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000268
Eric Andersen8401eea2004-08-04 19:16:54 +0000269static int newenv(int f);
270static void quitenv(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000271static void next(int f);
272static void setdash(void);
273static void onecommand(void);
274static void runtrap(int i);
Eric Andersenff9eee42001-06-29 04:57:14 +0000275
Eric Andersen12de6cf2004-08-04 19:19:10 +0000276
Eric Andersenff9eee42001-06-29 04:57:14 +0000277/* -------- area stuff -------- */
278
Eric Andersen12de6cf2004-08-04 19:19:10 +0000279#define REGSIZE sizeof(struct region)
280#define GROWBY (256)
281/* #define SHRINKBY (64) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000282#undef SHRINKBY
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000283#define FREE (32767)
284#define BUSY (0)
285#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000286
287
288struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000289 struct region *next;
290 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000291};
292
293
Eric Andersenff9eee42001-06-29 04:57:14 +0000294/* -------- grammar stuff -------- */
295typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000296 char *cp;
297 char **wp;
298 int i;
299 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000300} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000301
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000302#define WORD 256
303#define LOGAND 257
304#define LOGOR 258
305#define BREAK 259
306#define IF 260
307#define THEN 261
308#define ELSE 262
309#define ELIF 263
310#define FI 264
311#define CASE 265
312#define ESAC 266
313#define FOR 267
314#define WHILE 268
315#define UNTIL 269
316#define DO 270
317#define DONE 271
318#define IN 272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000319/* Added for "." file expansion */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000320#define DOT 273
Eric Andersen12de6cf2004-08-04 19:19:10 +0000321
Eric Andersenff9eee42001-06-29 04:57:14 +0000322#define YYERRCODE 300
323
324/* flags to yylex */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000325#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000326
Eric Andersen8401eea2004-08-04 19:16:54 +0000327static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000328static struct op *andor(void);
329static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000330static int synio(int cf);
331static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000332static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000333static struct op *nested(int type, int mark);
334static struct op *command(int cf);
335static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000336static struct op *thenpart(void);
337static struct op *elsepart(void);
338static struct op *caselist(void);
339static struct op *casepart(void);
340static char **pattern(void);
341static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000342static struct op *list(struct op *t1, struct op *t2);
343static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000344static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000345static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000346static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000347static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000348static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000349static struct ioword *io(int u, int f, char *cp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000350static int yylex(int cf);
351static int collect(int c, int c1);
352static int dual(int c);
353static void diag(int ec);
354static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000355
356/* -------- var.h -------- */
357
Eric Andersen8401eea2004-08-04 19:16:54 +0000358struct var {
359 char *value;
360 char *name;
361 struct var *next;
362 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000363};
Eric Andersenff9eee42001-06-29 04:57:14 +0000364
Eric Andersen8401eea2004-08-04 19:16:54 +0000365#define COPYV 1 /* flag to setval, suggesting copy */
366#define RONLY 01 /* variable is read-only */
367#define EXPORT 02 /* variable is to be exported */
368#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000369
Eric Andersen8401eea2004-08-04 19:16:54 +0000370static int yyparse(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000371
372static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000373
Eric Andersen12de6cf2004-08-04 19:19:10 +0000374
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000375#define AFID_NOBUF (~0)
376#define AFID_ID 0
377
378
Eric Andersenff9eee42001-06-29 04:57:14 +0000379/* -------- io.h -------- */
380/* io buffer */
381struct iobuf {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000382 unsigned id; /* buffer id */
383 char buf[512]; /* buffer */
384 char *bufp; /* pointer into buffer */
385 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000386};
387
388/* possible arguments to an IO function */
389struct ioarg {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000390 const char *aword;
Eric Andersen8401eea2004-08-04 19:16:54 +0000391 char **awordlist;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000392 int afile; /* file descriptor */
393 unsigned afid; /* buffer id */
394 long afpos; /* file position */
395 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000396};
Eric Andersen8401eea2004-08-04 19:16:54 +0000397
Eric Andersenff9eee42001-06-29 04:57:14 +0000398/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000399struct io {
400 int (*iofn) (struct ioarg *, struct io *);
401 struct ioarg *argp;
402 int peekc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000403 char prev; /* previous character read by readc() */
404 char nlcount; /* for `'s */
405 char xchar; /* for `'s */
406 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000407};
Eric Andersen8401eea2004-08-04 19:16:54 +0000408
Eric Andersen8401eea2004-08-04 19:16:54 +0000409#define XOTHER 0 /* none of the below */
410#define XDOLL 1 /* expanding ${} */
411#define XGRAVE 2 /* expanding `'s */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000412#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000413
414/* in substitution */
415#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
416
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000417static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
418static struct ioarg ioargstack[NPUSH];
419static struct io iostack[NPUSH];
420static struct iobuf sharedbuf = { AFID_NOBUF };
421static struct iobuf mainbuf = { AFID_NOBUF };
422static unsigned bufid = AFID_ID; /* buffer id counter */
423
424#define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen)))
425#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
426
427
428/*
429 * parsing & execution environment
430 */
431static struct env {
432 char *linep;
433 struct io *iobase;
434 struct io *iop;
435 xint *errpt; /* void * */
436 int iofd;
437 struct env *oenv;
438} e;
439
Eric Andersen12de6cf2004-08-04 19:19:10 +0000440
Eric Andersenff9eee42001-06-29 04:57:14 +0000441/*
442 * input generators for IO structure
443 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000444static int nlchar(struct ioarg *ap);
445static int strchar(struct ioarg *ap);
446static int qstrchar(struct ioarg *ap);
447static int filechar(struct ioarg *ap);
448static int herechar(struct ioarg *ap);
449static int linechar(struct ioarg *ap);
450static int gravechar(struct ioarg *ap, struct io *iop);
451static int qgravechar(struct ioarg *ap, struct io *iop);
452static int dolchar(struct ioarg *ap);
453static int wdchar(struct ioarg *ap);
454static void scraphere(void);
455static void freehere(int area);
456static void gethere(void);
457static void markhere(char *s, struct ioword *iop);
458static int herein(char *hname, int xdoll);
459static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000460
Eric Andersen12de6cf2004-08-04 19:19:10 +0000461
Eric Andersen8401eea2004-08-04 19:16:54 +0000462static int eofc(void);
463static int readc(void);
464static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000465static void ioecho(char c);
Eric Andersenff9eee42001-06-29 04:57:14 +0000466
Eric Andersen12de6cf2004-08-04 19:19:10 +0000467
Eric Andersenff9eee42001-06-29 04:57:14 +0000468/*
469 * IO control
470 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000471static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
472static int remap(int fd);
473static int openpipe(int *pv);
474static void closepipe(int *pv);
475static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000476
Eric Andersenff9eee42001-06-29 04:57:14 +0000477/* -------- word.h -------- */
478
Eric Andersen8401eea2004-08-04 19:16:54 +0000479#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000480
Eric Andersen8401eea2004-08-04 19:16:54 +0000481struct wdblock {
482 short w_bsize;
483 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000484 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000485 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000486};
487
Eric Andersen8401eea2004-08-04 19:16:54 +0000488static struct wdblock *addword(char *wd, struct wdblock *wb);
489static struct wdblock *newword(int nw);
490static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000491
Eric Andersenff9eee42001-06-29 04:57:14 +0000492/* -------- misc stuff -------- */
493
Eric Andersen12de6cf2004-08-04 19:19:10 +0000494static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000495static int iosetup(struct ioword *iop, int pipein, int pipeout);
Eric Andersen8401eea2004-08-04 19:16:54 +0000496static void brkset(struct brkcon *bc);
497static int dolabel(struct op *t);
498static int dohelp(struct op *t);
499static int dochdir(struct op *t);
500static int doshift(struct op *t);
501static int dologin(struct op *t);
502static int doumask(struct op *t);
503static int doexec(struct op *t);
504static int dodot(struct op *t);
505static int dowait(struct op *t);
506static int doread(struct op *t);
507static int doeval(struct op *t);
508static int dotrap(struct op *t);
509static int getsig(char *s);
510static void setsig(int n, sighandler_t f);
511static int getn(char *as);
512static int dobreak(struct op *t);
513static int docontinue(struct op *t);
514static int brkcontin(char *cp, int val);
515static int doexit(struct op *t);
516static int doexport(struct op *t);
517static int doreadonly(struct op *t);
518static void rdexp(char **wp, void (*f) (struct var *), int key);
519static void badid(char *s);
520static int doset(struct op *t);
521static void varput(char *s, int out);
522static int dotimes(struct op *t);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000523static int expand(const char *cp, struct wdblock **wbp, int f);
Eric Andersen8401eea2004-08-04 19:16:54 +0000524static char *blank(int f);
525static int dollar(int quoted);
526static int grave(int quoted);
527static void globname(char *we, char *pp);
528static char *generate(char *start1, char *end1, char *middle, char *end);
529static int anyspcl(struct wdblock *wb);
530static int xstrcmp(char *p1, char *p2);
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000531static void glob0(char *a0, unsigned a1, int a2,
Eric Andersen8401eea2004-08-04 19:16:54 +0000532 int (*a3) (char *, char *));
Eric Andersen8401eea2004-08-04 19:16:54 +0000533static void readhere(char **name, char *s, int ec);
534static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
535static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000536
Eric Andersen8401eea2004-08-04 19:16:54 +0000537struct here {
538 char *h_tag;
539 int h_dosub;
540 struct ioword *h_iop;
541 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000542};
543
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000544static const char * const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000545 "Signal 0",
546 "Hangup",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000547 NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000548 "Quit",
549 "Illegal instruction",
550 "Trace/BPT trap",
551 "Abort",
552 "Bus error",
553 "Floating Point Exception",
554 "Killed",
555 "SIGUSR1",
556 "SIGSEGV",
557 "SIGUSR2",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000558 NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000559 "Alarm clock",
560 "Terminated",
561};
Eric Andersen8401eea2004-08-04 19:16:54 +0000562
Eric Andersenff9eee42001-06-29 04:57:14 +0000563#define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
564
565struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000566 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000567 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000568};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000569static const struct res restab[] = {
Eric Andersen8401eea2004-08-04 19:16:54 +0000570 {"for", FOR},
571 {"case", CASE},
572 {"esac", ESAC},
573 {"while", WHILE},
574 {"do", DO},
575 {"done", DONE},
576 {"if", IF},
577 {"in", IN},
578 {"then", THEN},
579 {"else", ELSE},
580 {"elif", ELIF},
581 {"until", UNTIL},
582 {"fi", FI},
Eric Andersen8401eea2004-08-04 19:16:54 +0000583 {";;", BREAK},
584 {"||", LOGOR},
585 {"&&", LOGAND},
586 {"{", '{'},
587 {"}", '}'},
Eric Andersen12de6cf2004-08-04 19:19:10 +0000588 {".", DOT},
Eric Andersen8401eea2004-08-04 19:16:54 +0000589 {0, 0},
Eric Andersenff9eee42001-06-29 04:57:14 +0000590};
591
592
Eric Andersen1c039232001-07-07 00:05:55 +0000593struct builtincmd {
594 const char *name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000595 int (*builtinfunc) (struct op * t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000596};
Eric Andersen8401eea2004-08-04 19:16:54 +0000597static const struct builtincmd builtincmds[] = {
598 {".", dodot},
599 {":", dolabel},
600 {"break", dobreak},
601 {"cd", dochdir},
602 {"continue", docontinue},
603 {"eval", doeval},
604 {"exec", doexec},
605 {"exit", doexit},
606 {"export", doexport},
607 {"help", dohelp},
608 {"login", dologin},
609 {"newgrp", dologin},
610 {"read", doread},
611 {"readonly", doreadonly},
612 {"set", doset},
613 {"shift", doshift},
614 {"times", dotimes},
615 {"trap", dotrap},
616 {"umask", doumask},
617 {"wait", dowait},
618 {0, 0}
Eric Andersenff9eee42001-06-29 04:57:14 +0000619};
620
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000621static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000622static struct op *dowholefile(int, int);
623
Eric Andersen12de6cf2004-08-04 19:19:10 +0000624
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000625/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000626static char **dolv;
627static int dolc;
628static int exstat;
629static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000630static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000631static int execflg;
632static int multiline; /* \n changed to ; */
633static struct op *outtree; /* result from parser */
634static xint *failpt;
635static xint *errpt;
636static struct brkcon *brklist;
637static int isbreak;
638static struct wdblock *wdlist;
639static struct wdblock *iolist;
640static char *trap[_NSIG + 1];
641static char ourtrap[_NSIG + 1];
642static int trapset; /* trap pending */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000643
644#ifdef MSHDEBUG
645static struct var *mshdbg_var;
646#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000647static struct var *vlist; /* dictionary */
648static struct var *homedir; /* home directory */
649static struct var *prompt; /* main prompt */
650static struct var *cprompt; /* continuation prompt */
651static struct var *path; /* search path for commands */
652static struct var *shell; /* shell to interpret command files */
653static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000654
Eric Andersen8401eea2004-08-04 19:16:54 +0000655static int areanum; /* current allocation area */
656static int intr;
657static int inparse;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000658static char *null = (char*)"";
Eric Andersen8401eea2004-08-04 19:16:54 +0000659static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000660static void (*qflag) (int) = SIG_IGN;
661static int startl;
662static int peeksym;
663static int nlseen;
664static int iounit = IODEFAULT;
665static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000666static char *elinep = line + sizeof(line) - 5;
667
Eric Andersen12de6cf2004-08-04 19:19:10 +0000668
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000669static struct here *inhere; /* list of hear docs while parsing */
670static struct here *acthere; /* list of active here documents */
671static struct region *areabot; /* bottom of area */
672static struct region *areatop; /* top of area */
673static struct region *areanxt; /* starting point of scan */
Eric Andersen8401eea2004-08-04 19:16:54 +0000674static void *brktop;
675static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000676
Eric Andersen12de6cf2004-08-04 19:19:10 +0000677static struct env e = {
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000678 line, /* linep: char ptr */
679 iostack, /* iobase: struct io ptr */
680 iostack - 1, /* iop: struct io ptr */
681 (xint *) NULL, /* errpt: void ptr for errors? */
682 FDBASE, /* iofd: file desc */
683 (struct env *) NULL /* oenv: struct env ptr */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000684};
685
686#ifdef MSHDEBUG
687void print_t(struct op *t)
688{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000689 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
690 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000691
692 if (t->words) {
693 DBGPRINTF(("T: W1: %s", t->words[0]));
694 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000695}
696
697void print_tree(struct op *head)
698{
699 if (head == NULL) {
700 DBGPRINTF(("PRINT_TREE: no tree\n"));
701 return;
702 }
703
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000704 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000705 head->right));
706
707 if (head->left)
708 print_tree(head->left);
709
710 if (head->right)
711 print_tree(head->right);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000712}
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000713#endif /* MSHDEBUG */
714
715
716/*
717 * IO functions
718 */
719static void prs(const char *s)
720{
721 if (*s)
722 write(2, s, strlen(s));
723}
724
725static void prn(unsigned u)
726{
727 prs(itoa(u));
728}
729
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000730static void echo(char **wp)
731{
732 int i;
733
734 prs("+");
735 for (i = 0; wp[i]; i++) {
736 if (i)
737 prs(" ");
738 prs(wp[i]);
739 }
740 prs("\n");
741}
742
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000743static void closef(int i)
744{
745 if (i > 2)
746 close(i);
747}
748
749static void closeall(void)
750{
751 int u;
752
753 for (u = NUFILE; u < NOFILE;)
754 close(u++);
755}
Eric Andersen12de6cf2004-08-04 19:19:10 +0000756
Eric Andersenff9eee42001-06-29 04:57:14 +0000757
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000758/* fail but return to process next command */
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000759static void fail(void) ATTRIBUTE_NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000760static void fail(void)
761{
762 longjmp(failpt, 1);
763 /* NOTREACHED */
764}
Eric Andersenff9eee42001-06-29 04:57:14 +0000765
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000766/* abort shell (or fail in subshell) */
767static void leave(void) ATTRIBUTE_NORETURN;
768static void leave(void)
769{
770 DBGPRINTF(("LEAVE: leave called!\n"));
771
772 if (execflg)
773 fail();
774 scraphere();
775 freehere(1);
776 runtrap(0);
777 _exit(exstat);
778 /* NOTREACHED */
779}
780
781static void warn(const char *s)
782{
783 if (*s) {
784 prs(s);
785 exstat = -1;
786 }
787 prs("\n");
788 if (flag['e'])
789 leave();
790}
791
792static void err(const char *s)
793{
794 warn(s);
795 if (flag['n'])
796 return;
797 if (!interactive)
798 leave();
799 if (e.errpt)
800 longjmp(e.errpt, 1);
801 closeall();
802 e.iop = e.iobase = iostack;
803}
804
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000805
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000806/* -------- area.c -------- */
807
Eric Andersenff9eee42001-06-29 04:57:14 +0000808/*
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000809 * All memory between (char *)areabot and (char *)(areatop+1) is
810 * exclusively administered by the area management routines.
811 * It is assumed that sbrk() and brk() manipulate the high end.
Eric Andersenff9eee42001-06-29 04:57:14 +0000812 */
813
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000814#define sbrk(X) ({ \
815 void * __q = (void *)-1; \
816 if (brkaddr + (int)(X) < brktop) { \
817 __q = brkaddr; \
818 brkaddr += (int)(X); \
819 } \
820 __q; \
821})
Eric Andersenff9eee42001-06-29 04:57:14 +0000822
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000823static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000824{
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000825 brkaddr = xmalloc(AREASIZE);
826 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +0000827
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000828 while ((long) sbrk(0) & ALIGN)
829 sbrk(1);
830 areabot = (struct region *) sbrk(REGSIZE);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000831
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000832 areabot->next = areabot;
833 areabot->area = BUSY;
834 areatop = areabot;
835 areanxt = areabot;
Eric Andersenff9eee42001-06-29 04:57:14 +0000836}
837
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000838static char *getcell(unsigned nbytes)
839{
840 int nregio;
841 struct region *p, *q;
842 int i;
843
844 if (nbytes == 0) {
845 puts("getcell(0)");
846 abort();
847 }
848 /* silly and defeats the algorithm */
849 /*
850 * round upwards and add administration area
851 */
852 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
853 p = areanxt;
854 for (;;) {
855 if (p->area > areanum) {
856 /*
857 * merge free cells
858 */
859 while ((q = p->next)->area > areanum && q != areanxt)
860 p->next = q->next;
861 /*
862 * exit loop if cell big enough
863 */
864 if (q >= p + nregio)
865 goto found;
866 }
867 p = p->next;
868 if (p == areanxt)
869 break;
870 }
871 i = nregio >= GROWBY ? nregio : GROWBY;
872 p = (struct region *) sbrk(i * REGSIZE);
873 if (p == (struct region *) -1)
874 return NULL;
875 p--;
876 if (p != areatop) {
877 puts("not contig");
878 abort(); /* allocated areas are contiguous */
879 }
880 q = p + i;
881 p->next = q;
882 p->area = FREE;
883 q->next = areabot;
884 q->area = BUSY;
885 areatop = q;
886 found:
887 /*
888 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
889 */
890 areanxt = p + nregio;
891 if (areanxt < q) {
892 /*
893 * split into requested area and rest
894 */
895 if (areanxt + 1 > q) {
896 puts("OOM");
897 abort(); /* insufficient space left for admin */
898 }
899 areanxt->next = q;
900 areanxt->area = FREE;
901 p->next = areanxt;
902 }
903 p->area = areanum;
904 return (char *) (p + 1);
905}
906
907static void freecell(char *cp)
908{
909 struct region *p;
910
911 p = (struct region *) cp;
912 if (p != NULL) {
913 p--;
914 if (p < areanxt)
915 areanxt = p;
916 p->area = FREE;
917 }
918}
919#define DELETE(obj) freecell((char *)obj)
920
921static void freearea(int a)
922{
923 struct region *p, *top;
924
925 top = areatop;
926 for (p = areabot; p != top; p = p->next)
927 if (p->area >= a)
928 p->area = FREE;
929}
930
931static void setarea(char *cp, int a)
932{
933 struct region *p;
934
935 p = (struct region *) cp;
936 if (p != NULL)
937 (p - 1)->area = a;
938}
939
940static int getarea(char *cp)
941{
942 return ((struct region *) cp - 1)->area;
943}
944
945static void garbage(void)
946{
947 struct region *p, *q, *top;
948
949 top = areatop;
950 for (p = areabot; p != top; p = p->next) {
951 if (p->area > areanum) {
952 while ((q = p->next)->area > areanum)
953 p->next = q->next;
954 areanxt = p;
955 }
956 }
957#ifdef SHRINKBY
958 if (areatop >= q + SHRINKBY && q->area > areanum) {
959 brk((char *) (q + 1));
960 q->next = areabot;
961 q->area = BUSY;
962 areatop = q;
963 }
964#endif
965}
966
967static char *space(int n)
968{
969 char *cp;
970
971 cp = getcell(n);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000972 if (cp == NULL)
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000973 err("out of string space");
974 return cp;
975}
976
977static char *strsave(const char *s, int a)
978{
979 char *cp;
980
981 cp = space(strlen(s) + 1);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000982 if (cp == NULL) {
983// FIXME: I highly doubt this is good.
984 return (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000985 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000986 setarea(cp, a);
987 strcpy(cp, s);
988 return cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000989}
990
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000991
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000992/* -------- var.c -------- */
993
994static int eqname(const char *n1, const char *n2)
995{
996 for (; *n1 != '=' && *n1 != '\0'; n1++)
997 if (*n2++ != *n1)
998 return 0;
999 return *n2 == '\0' || *n2 == '=';
1000}
1001
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001002static const char *findeq(const char *cp)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001003{
1004 while (*cp != '\0' && *cp != '=')
1005 cp++;
1006 return cp;
1007}
1008
1009/*
1010 * Find the given name in the dictionary
1011 * and return its value. If the name was
1012 * not previously there, enter it now and
1013 * return a null value.
1014 */
1015static struct var *lookup(const char *n)
1016{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001017// FIXME: dirty hack
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001018 static struct var dummy;
1019
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001020 struct var *vp;
1021 const char *cp;
1022 char *xp;
1023 int c;
1024
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001025 if (isdigit(*n)) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001026 dummy.name = (char*)n;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001027 for (c = 0; isdigit(*n) && c < 1000; n++)
1028 c = c * 10 + *n - '0';
1029 dummy.status = RONLY;
1030 dummy.value = (c <= dolc ? dolv[c] : null);
1031 return &dummy;
1032 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001033
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001034 for (vp = vlist; vp; vp = vp->next)
1035 if (eqname(vp->name, n))
1036 return vp;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001037
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001038 cp = findeq(n);
1039 vp = (struct var *) space(sizeof(*vp));
1040 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001041 dummy.name = dummy.value = (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001042 return &dummy;
1043 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001044
1045 xp = vp->name;
1046 while ((*xp = *n++) != '\0' && *xp != '=')
1047 xp++;
1048 *xp++ = '=';
1049 *xp = '\0';
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001050 setarea((char *) vp, 0);
1051 setarea((char *) vp->name, 0);
1052 vp->value = null;
1053 vp->next = vlist;
1054 vp->status = GETCELL;
1055 vlist = vp;
1056 return vp;
1057}
1058
1059/*
1060 * if name is not NULL, it must be
1061 * a prefix of the space `val',
1062 * and end with `='.
1063 * this is all so that exporting
1064 * values is reasonably painless.
1065 */
1066static void nameval(struct var *vp, const char *val, const char *name)
1067{
1068 const char *cp;
1069 char *xp;
1070 int fl;
1071
1072 if (vp->status & RONLY) {
1073 xp = vp->name;
1074 while (*xp && *xp != '=')
1075 putc(*xp++, stderr);
1076 err(" is read-only");
1077 return;
1078 }
1079 fl = 0;
1080 if (name == NULL) {
1081 xp = space(strlen(vp->name) + strlen(val) + 2);
1082 if (xp == NULL)
1083 return;
1084 /* make string: name=value */
1085 setarea(xp, 0);
1086 name = xp;
1087 cp = vp->name;
1088 while ((*xp = *cp++) != '\0' && *xp != '=')
1089 xp++;
1090 *xp++ = '=';
1091 strcpy(xp, val);
1092 val = xp;
1093 fl = GETCELL;
1094 }
1095 if (vp->status & GETCELL)
1096 freecell(vp->name); /* form new string `name=value' */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001097 vp->name = (char*)name;
1098 vp->value = (char*)val;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001099 vp->status |= fl;
1100}
1101
1102/*
1103 * give variable at `vp' the value `val'.
1104 */
1105static void setval(struct var *vp, const char *val)
1106{
1107 nameval(vp, val, NULL);
1108}
1109
1110static void export(struct var *vp)
1111{
1112 vp->status |= EXPORT;
1113}
1114
1115static void ronly(struct var *vp)
1116{
1117 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1118 vp->status |= RONLY;
1119}
1120
1121static int isassign(const char *s)
1122{
1123 unsigned char c;
1124 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1125
1126 /* no isalpha() - we shouldn't use locale */
1127 c = *s;
1128 if (c != '_'
1129 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
1130 ) {
1131 return 0;
1132 }
1133 while (1) {
1134 c = *++s;
1135 if (c == '\0')
1136 return 0;
1137 if (c == '=')
1138 return 1;
1139 c |= 0x20; /* lowercase letters, doesn't affect numbers */
1140 if (c != '_'
1141 && (unsigned)(c - '0') > 9 /* not number */
1142 && (unsigned)(c - 'a') > 25 /* not letter */
1143 ) {
1144 return 0;
1145 }
1146 }
1147}
1148
1149static int assign(const char *s, int cf)
1150{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001151 const char *cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001152 struct var *vp;
1153
1154 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1155
1156 if (!isalpha(*s) && *s != '_')
1157 return 0;
1158 for (cp = s; *cp != '='; cp++)
1159 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
1160 return 0;
1161 vp = lookup(s);
1162 nameval(vp, ++cp, cf == COPYV ? NULL : s);
1163 if (cf != COPYV)
1164 vp->status &= ~GETCELL;
1165 return 1;
1166}
1167
1168static int checkname(char *cp)
1169{
1170 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1171
1172 if (!isalpha(*cp++) && *(cp - 1) != '_')
1173 return 0;
1174 while (*cp)
1175 if (!isalnum(*cp++) && *(cp - 1) != '_')
1176 return 0;
1177 return 1;
1178}
1179
1180static void putvlist(int f, int out)
1181{
1182 struct var *vp;
1183
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001184 for (vp = vlist; vp; vp = vp->next) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001185 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1186 if (vp->status & EXPORT)
1187 write(out, "export ", 7);
1188 if (vp->status & RONLY)
1189 write(out, "readonly ", 9);
1190 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
1191 write(out, "\n", 1);
1192 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001193 }
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001194}
1195
1196
1197/*
1198 * trap handling
1199 */
1200static void sig(int i)
1201{
1202 trapset = i;
1203 signal(i, sig);
1204}
1205
1206static void runtrap(int i)
1207{
1208 char *trapstr;
1209
1210 trapstr = trap[i];
1211 if (trapstr == NULL)
1212 return;
1213
1214 if (i == 0)
1215 trap[i] = NULL;
1216
1217 RUN(aword, trapstr, nlchar);
1218}
1219
1220
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001221static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001222{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001223 char *cp;
1224 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001225 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001226
1227 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001228 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001229 if (flag[c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001230 *cp++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001231 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001232 setval(lookup("-"), m);
1233}
1234
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001235static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001236{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001237 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001238
1239 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001240
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001241 f = 0;
Denis Vlasenko9f739442006-12-16 23:49:13 +00001242 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001243 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001244 f = open(s, 0);
1245 if (f < 0) {
1246 prs(s);
1247 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001248 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001249 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001250 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001251
Eric Andersenff9eee42001-06-29 04:57:14 +00001252 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001253 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001254}
1255
Eric Andersen12de6cf2004-08-04 19:19:10 +00001256
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001257struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001258{
1259 struct op *dotnode;
1260
1261 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001262 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001263
1264 if (head->left != NULL) {
1265 dotnode = scantree(head->left);
1266 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001267 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001268 }
1269
1270 if (head->right != NULL) {
1271 dotnode = scantree(head->right);
1272 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001273 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001274 }
1275
1276 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001277 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001278
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001279 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001280
Denis Vlasenkocf787cf2007-02-04 17:11:25 +00001281 if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001282 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001283 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001284 }
1285
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001286 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001287}
1288
1289
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001290static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001291{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001292 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001293 jmp_buf m1;
1294
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001295 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001296
Eric Andersenff9eee42001-06-29 04:57:14 +00001297 while (e.oenv)
1298 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001299
Eric Andersenff9eee42001-06-29 04:57:14 +00001300 areanum = 1;
1301 freehere(areanum);
1302 freearea(areanum);
1303 garbage();
1304 wdlist = 0;
1305 iolist = 0;
1306 e.errpt = 0;
1307 e.linep = line;
1308 yynerrs = 0;
1309 multiline = 0;
1310 inparse = 1;
1311 intr = 0;
1312 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001313
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001314 failpt = m1;
1315 setjmp(failpt); /* Bruce Evans' fix */
1316 failpt = m1;
1317 if (setjmp(failpt) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001318 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1319
Eric Andersenff9eee42001-06-29 04:57:14 +00001320 while (e.oenv)
1321 quitenv();
1322 scraphere();
1323 if (!interactive && intr)
1324 leave();
1325 inparse = 0;
1326 intr = 0;
1327 return;
1328 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001329
Eric Andersenff9eee42001-06-29 04:57:14 +00001330 inparse = 0;
1331 brklist = 0;
1332 intr = 0;
1333 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001334
1335 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001336 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001337 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001338 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001339 }
1340
Eric Andersenff9eee42001-06-29 04:57:14 +00001341 if (!interactive && intr) {
1342 execflg = 0;
1343 leave();
1344 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001345
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001346 i = trapset;
1347 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001348 trapset = 0;
1349 runtrap(i);
1350 }
1351}
1352
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001353static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001354{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001355 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001356
1357 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001358
1359 if (f) {
1360 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001361 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001362 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001363
Eric Andersenff9eee42001-06-29 04:57:14 +00001364 ep = (struct env *) space(sizeof(*ep));
1365 if (ep == NULL) {
1366 while (e.oenv)
1367 quitenv();
1368 fail();
1369 }
1370 *ep = e;
1371 e.oenv = ep;
1372 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001373
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001374 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001375}
1376
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001377static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001378{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001379 struct env *ep;
1380 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001381
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001382 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001383
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001384 ep = e.oenv;
1385 if (ep != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001386 fd = e.iofd;
1387 e = *ep;
1388 /* should close `'d files */
1389 DELETE(ep);
1390 while (--fd >= e.iofd)
1391 close(fd);
1392 }
1393}
1394
1395/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001396 * Is character c in s?
Eric Andersenff9eee42001-06-29 04:57:14 +00001397 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001398static int any(int c, const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001399{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001400 while (*s)
1401 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001402 return 1;
1403 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001404}
1405
1406/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001407 * Is any character from s1 in s2?
Eric Andersenff9eee42001-06-29 04:57:14 +00001408 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001409static int anys(const char *s1, const char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001410{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001411 while (*s1)
1412 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001413 return 1;
1414 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001415}
1416
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001417static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001418{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001419 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001420}
1421
Eric Andersen8401eea2004-08-04 19:16:54 +00001422static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001423{
1424 PUSHIO(afile, f, filechar);
1425}
1426
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001427static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001428{
1429 signal(SIGINT, onintr);
1430 intr = 1;
1431 if (interactive) {
1432 if (inparse) {
1433 prs("\n");
1434 fail();
1435 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001436 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001437 execflg = 0;
1438 leave();
1439 }
1440}
1441
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001442
Eric Andersenff9eee42001-06-29 04:57:14 +00001443/* -------- gmatch.c -------- */
1444/*
1445 * int gmatch(string, pattern)
1446 * char *string, *pattern;
1447 *
1448 * Match a pattern as in sh(1).
1449 */
1450
1451#define CMASK 0377
1452#define QUOTE 0200
1453#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001454#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001455
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001456static const char *cclass(const char *p, int sub)
1457{
1458 int c, d, not, found;
1459
1460 not = (*p == NOT);
1461 if (not != 0)
1462 p++;
1463 found = not;
1464 do {
1465 if (*p == '\0')
1466 return NULL;
1467 c = *p & CMASK;
1468 if (p[1] == '-' && p[2] != ']') {
1469 d = p[2] & CMASK;
1470 p++;
1471 } else
1472 d = c;
1473 if (c == sub || (c <= sub && sub <= d))
1474 found = !not;
1475 } while (*++p != ']');
1476 return found ? p + 1 : NULL;
1477}
1478
1479static int gmatch(const char *s, const char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001480{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001481 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001482
1483 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001484 return 0;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001485
Eric Andersenff9eee42001-06-29 04:57:14 +00001486 while ((pc = *p++ & CMASK) != '\0') {
1487 sc = *s++ & QMASK;
1488 switch (pc) {
1489 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001490 p = cclass(p, sc);
1491 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001492 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001493 break;
1494
1495 case '?':
1496 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001497 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001498 break;
1499
1500 case '*':
1501 s--;
1502 do {
1503 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001504 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001505 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001506 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001507
1508 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001509 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001510 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001511 }
1512 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001513 return *s == '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001514}
1515
Eric Andersenff9eee42001-06-29 04:57:14 +00001516
Eric Andersenff9eee42001-06-29 04:57:14 +00001517/* -------- csyn.c -------- */
1518/*
1519 * shell: syntax (C version)
1520 */
1521
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001522static void yyerror(const char *s) ATTRIBUTE_NORETURN;
1523static void yyerror(const char *s)
1524{
1525 yynerrs++;
1526 if (interactive && e.iop <= iostack) {
1527 multiline = 0;
1528 while (eofc() == 0 && yylex(0) != '\n');
1529 }
1530 err(s);
1531 fail();
1532}
1533
1534static void zzerr(void) ATTRIBUTE_NORETURN;
1535static void zzerr(void)
1536{
1537 yyerror("syntax error");
1538}
1539
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001540int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001541{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001542 DBGPRINTF7(("YYPARSE: enter...\n"));
1543
Eric Andersen8401eea2004-08-04 19:16:54 +00001544 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001545 peeksym = 0;
1546 yynerrs = 0;
1547 outtree = c_list();
1548 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001549 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001550}
1551
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001552static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001553{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001554 struct op *t, *p;
1555 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001556
1557 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001558
1559 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001560
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001561 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001562
Eric Andersenff9eee42001-06-29 04:57:14 +00001563 if (t != NULL) {
1564 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001565 p = command(CONTIN);
1566 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001567 DBGPRINTF8(("PIPELINE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001568 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001569 }
1570
Eric Andersenff9eee42001-06-29 04:57:14 +00001571 if (t->type != TPAREN && t->type != TCOM) {
1572 /* shell statement */
1573 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1574 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001575
Eric Andersenff9eee42001-06-29 04:57:14 +00001576 t = block(TPIPE, t, p, NOWORDS);
1577 }
1578 peeksym = c;
1579 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001580
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001581 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001582 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001583}
1584
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001585static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001586{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001587 struct op *t, *p;
1588 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001589
1590 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001591
1592 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001593
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001594 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001595
Eric Andersenff9eee42001-06-29 04:57:14 +00001596 if (t != NULL) {
1597 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001598 p = pipeline(CONTIN);
1599 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001600 DBGPRINTF8(("ANDOR: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001601 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001602 }
1603
Eric Andersen8401eea2004-08-04 19:16:54 +00001604 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001605 } /* WHILE */
1606
Eric Andersenff9eee42001-06-29 04:57:14 +00001607 peeksym = c;
1608 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001609
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001610 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001611 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001612}
1613
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001614static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001615{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001616 struct op *t, *p;
1617 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001618
1619 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001620
1621 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001622
Eric Andersenff9eee42001-06-29 04:57:14 +00001623 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001624 peeksym = yylex(0);
1625 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001626 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001627
Eric Andersen8401eea2004-08-04 19:16:54 +00001628 while ((c = yylex(0)) == ';' || c == '&'
1629 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001630
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001631 p = andor();
1632 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001633 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001634
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001635 peeksym = yylex(0);
1636 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001637 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001638
Eric Andersenff9eee42001-06-29 04:57:14 +00001639 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001640 } /* WHILE */
1641
Eric Andersenff9eee42001-06-29 04:57:14 +00001642 peeksym = c;
1643 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001644 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001645 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001646 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001647}
1648
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001649static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001650{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001651 struct ioword *iop;
1652 int i;
1653 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001654
1655 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001656
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001657 c = yylex(cf);
1658 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001659 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001660 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001661 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001662
Eric Andersenff9eee42001-06-29 04:57:14 +00001663 i = yylval.i;
1664 musthave(WORD, 0);
1665 iop = io(iounit, i, yylval.cp);
1666 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001667
Eric Andersenff9eee42001-06-29 04:57:14 +00001668 if (i & IOHERE)
1669 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001670
1671 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001672 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001673}
1674
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001675static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001676{
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001677 peeksym = yylex(cf);
1678 if (peeksym != c) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001679 DBGPRINTF7(("MUSTHAVE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001680 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001681 }
1682
Eric Andersenff9eee42001-06-29 04:57:14 +00001683 peeksym = 0;
1684}
1685
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001686static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001687{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001688 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001689
1690 t = NULL;
1691 for (;;) {
1692 switch (peeksym = yylex(0)) {
1693 case '<':
1694 case '>':
1695 (void) synio(0);
1696 break;
1697
1698 case WORD:
1699 if (t == NULL) {
1700 t = newtp();
1701 t->type = TCOM;
1702 }
1703 peeksym = 0;
1704 word(yylval.cp);
1705 break;
1706
1707 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001708 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001709 }
1710 }
1711}
1712
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001713static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001714{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001715 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001716
1717 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001718
1719 multiline++;
1720 t = c_list();
1721 musthave(mark, 0);
1722 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001723 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001724}
1725
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001726static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001727{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001728 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001729 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001730 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001731
1732 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001733
1734 iosave = iolist;
1735 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001736
Eric Andersenff9eee42001-06-29 04:57:14 +00001737 if (multiline)
1738 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001739
Eric Andersenff9eee42001-06-29 04:57:14 +00001740 while (synio(cf))
1741 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001742
1743 c = yylex(cf);
1744
1745 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001746 default:
1747 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001748 t = simple();
1749 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001750 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001751 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001752 t = newtp();
1753 t->type = TCOM;
1754 }
1755 break;
1756
1757 case '(':
1758 t = nested(TPAREN, ')');
1759 break;
1760
1761 case '{':
1762 t = nested(TBRACE, '}');
1763 break;
1764
1765 case FOR:
1766 t = newtp();
1767 t->type = TFOR;
1768 musthave(WORD, 0);
1769 startl = 1;
1770 t->str = yylval.cp;
1771 multiline++;
1772 t->words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001773 c = yylex(0);
1774 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001775 peeksym = c;
1776 t->left = dogroup(0);
1777 multiline--;
1778 break;
1779
1780 case WHILE:
1781 case UNTIL:
1782 multiline++;
1783 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001784 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001785 t->left = c_list();
1786 t->right = dogroup(1);
1787 t->words = NULL;
1788 multiline--;
1789 break;
1790
1791 case CASE:
1792 t = newtp();
1793 t->type = TCASE;
1794 musthave(WORD, 0);
1795 t->str = yylval.cp;
1796 startl++;
1797 multiline++;
1798 musthave(IN, CONTIN);
1799 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001800
Eric Andersenff9eee42001-06-29 04:57:14 +00001801 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001802
Eric Andersenff9eee42001-06-29 04:57:14 +00001803 musthave(ESAC, 0);
1804 multiline--;
1805 break;
1806
1807 case IF:
1808 multiline++;
1809 t = newtp();
1810 t->type = TIF;
1811 t->left = c_list();
1812 t->right = thenpart();
1813 musthave(FI, 0);
1814 multiline--;
1815 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001816
1817 case DOT:
1818 t = newtp();
1819 t->type = TDOT;
1820
1821 musthave(WORD, 0); /* gets name of file */
1822 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1823
1824 word(yylval.cp); /* add word to wdlist */
1825 word(NOWORD); /* terminate wdlist */
1826 t->words = copyw(); /* dup wdlist */
1827 break;
1828
Eric Andersenff9eee42001-06-29 04:57:14 +00001829 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001830
Eric Andersen8401eea2004-08-04 19:16:54 +00001831 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001832
Eric Andersenff9eee42001-06-29 04:57:14 +00001833 t = namelist(t);
1834 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001835
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001836 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001837
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001838 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001839}
1840
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001841static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001842{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001843 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001844
1845 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
1846
1847 multiline++;
1848 t = c_list();
1849 multiline--;
1850 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001851 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001852 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001853}
1854
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001855static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00001856{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001857 int c;
1858 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001859
1860 c = yylex(CONTIN);
1861 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001862 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001863 if (c != DO)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001864 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001865 mylist = c_list();
1866 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001867 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001868}
1869
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001870static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001871{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001872 int c;
1873 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001874
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001875 c = yylex(0);
1876 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001877 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001878 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001879 }
1880 t = newtp();
1881 t->type = 0;
1882 t->left = c_list();
1883 if (t->left == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001884 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001885 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001886 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001887}
1888
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001889static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001890{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001891 int c;
1892 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001893
1894 switch (c = yylex(0)) {
1895 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001896 t = c_list();
1897 if (t == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001898 zzerr();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001899 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001900
1901 case ELIF:
1902 t = newtp();
1903 t->type = TELIF;
1904 t->left = c_list();
1905 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001906 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001907
1908 default:
1909 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001910 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001911 }
1912}
1913
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001914static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001915{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001916 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001917
1918 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001919 while ((peeksym = yylex(CONTIN)) != ESAC) {
1920 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00001921 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00001922 }
1923
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001924 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001925 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001926}
1927
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001928static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001929{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001930 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001931
1932 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001933
1934 t = newtp();
1935 t->type = TPAT;
1936 t->words = pattern();
1937 musthave(')', 0);
1938 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001939 peeksym = yylex(CONTIN);
1940 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00001941 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001942
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001943 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001944
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001945 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001946}
1947
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001948static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001949{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001950 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00001951
1952 cf = CONTIN;
1953 do {
1954 musthave(WORD, cf);
1955 word(yylval.cp);
1956 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001957 c = yylex(0);
1958 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00001959 peeksym = c;
1960 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001961
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001962 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00001963}
1964
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001965static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001966{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001967 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001968
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001969 c = yylex(0);
1970 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001971 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001972 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001973 }
1974 startl = 0;
1975 while ((c = yylex(0)) == WORD)
1976 word(yylval.cp);
1977 word(NOWORD);
1978 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001979 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00001980}
1981
1982/*
1983 * supporting functions
1984 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001985static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001986{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001987 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001988
Eric Andersenff9eee42001-06-29 04:57:14 +00001989 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001990 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00001991 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001992 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001993
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001994 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001995}
1996
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001997static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001998{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001999 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002000
2001 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002002
2003 t = newtp();
2004 t->type = type;
2005 t->left = t1;
2006 t->right = t2;
2007 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002008
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002009 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002010 t2));
2011
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002012 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002013}
2014
Eric Andersen12de6cf2004-08-04 19:19:10 +00002015/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002016static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002017{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002018 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002019
2020 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002021
2022 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002023 if (strcmp(rp->r_name, n) == 0) {
2024 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002025 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002026 }
2027
2028 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002029 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002030}
2031
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002032static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002033{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002034 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002035
Eric Andersen8401eea2004-08-04 19:16:54 +00002036 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002037 t->type = 0;
2038 t->words = NULL;
2039 t->ioact = NULL;
2040 t->left = NULL;
2041 t->right = NULL;
2042 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002043
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002044 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002045
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002046 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002047}
2048
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002049static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002050{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002051
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002052 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002053 T_CMD_NAMES[t->type], iolist));
2054
Eric Andersenff9eee42001-06-29 04:57:14 +00002055 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002056 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002057 t->ioact = copyio();
2058 } else
2059 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002060
Eric Andersenff9eee42001-06-29 04:57:14 +00002061 if (t->type != TCOM) {
2062 if (t->type != TPAREN && t->ioact != NULL) {
2063 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2064 t->ioact = t->left->ioact;
2065 t->left->ioact = NULL;
2066 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002067 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002068 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002069
Eric Andersenff9eee42001-06-29 04:57:14 +00002070 word(NOWORD);
2071 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002072
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002073 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002074}
2075
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002076static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002077{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002078 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002079
2080 wd = getwords(wdlist);
2081 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002082 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002083}
2084
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002085static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002086{
2087 wdlist = addword(cp, wdlist);
2088}
2089
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002090static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002091{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002092 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002093
2094 iop = (struct ioword **) getwords(iolist);
2095 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002096 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002097}
2098
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002099static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002100{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002101 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002102
2103 iop = (struct ioword *) tree(sizeof(*iop));
2104 iop->io_unit = u;
2105 iop->io_flag = f;
2106 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002107 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002108 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002109}
2110
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002111static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002112{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002113 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002114 int atstart;
2115
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002116 c = peeksym;
2117 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002118 peeksym = 0;
2119 if (c == '\n')
2120 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002121 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002122 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002123
Eric Andersenff9eee42001-06-29 04:57:14 +00002124 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002125 atstart = startl;
2126 startl = 0;
2127 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002128 e.linep = line;
2129
2130/* MALAMO */
2131 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002132
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002133 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002134 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2135 ;
2136
Eric Andersenff9eee42001-06-29 04:57:14 +00002137 switch (c) {
2138 default:
2139 if (any(c, "0123456789")) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002140 c1 = my_getc(0);
2141 unget(c1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002142 if (c1 == '<' || c1 == '>') {
2143 iounit = c - '0';
2144 goto loop;
2145 }
2146 *e.linep++ = c;
2147 c = c1;
2148 }
2149 break;
2150
Eric Andersen12de6cf2004-08-04 19:19:10 +00002151 case '#': /* Comment, skip to next newline or End-of-string */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002152 while ((c = my_getc(0)) != '\0' && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002153 unget(c);
2154 goto loop;
2155
2156 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002157 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002158 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002159
2160 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002161 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002162 *e.linep++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002163 c = my_getc(0);
2164 if (c == '{') {
2165 c = collect(c, '}');
2166 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002167 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002168 goto pack;
2169 }
2170 break;
2171
2172 case '`':
2173 case '\'':
2174 case '"':
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002175 c = collect(c, c);
2176 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002177 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002178 goto pack;
2179
2180 case '|':
2181 case '&':
2182 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002183 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002184 /* If more chars process them, else return NULL char */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002185 c1 = dual(c);
2186 if (c1 != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002187 return c1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002188 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002189
Eric Andersenff9eee42001-06-29 04:57:14 +00002190 case '^':
2191 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002192 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002193 case '>':
2194 case '<':
2195 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002196 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002197
2198 case '\n':
2199 nlseen++;
2200 gethere();
2201 startl = 1;
2202 if (multiline || cf & CONTIN) {
2203 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002204#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002205 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002206#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002207 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002208#endif
2209 }
2210 if (cf & CONTIN)
2211 goto loop;
2212 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002213 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002214
2215 case '(':
2216 case ')':
2217 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002218 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002219 }
2220
2221 unget(c);
2222
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002223 pack:
2224 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002225 if (e.linep >= elinep)
2226 err("word too long");
2227 else
2228 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002229 };
2230
Eric Andersenff9eee42001-06-29 04:57:14 +00002231 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002232
Eric Andersen8401eea2004-08-04 19:16:54 +00002233 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002234 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002235
Eric Andersenff9eee42001-06-29 04:57:14 +00002236 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002237
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002238 if (atstart) {
2239 c = rlookup(line);
2240 if (c != 0) {
2241 startl = 1;
2242 return c;
2243 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002244 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002245
Eric Andersenff9eee42001-06-29 04:57:14 +00002246 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002247 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002248}
2249
Eric Andersen12de6cf2004-08-04 19:19:10 +00002250
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002251static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002252{
2253 char s[2];
2254
Eric Andersen12de6cf2004-08-04 19:19:10 +00002255 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2256
Eric Andersenff9eee42001-06-29 04:57:14 +00002257 *e.linep++ = c;
2258 while ((c = my_getc(c1)) != c1) {
2259 if (c == 0) {
2260 unget(c);
2261 s[0] = c1;
2262 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002263 prs("no closing ");
2264 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002265 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002266 }
2267 if (interactive && c == '\n' && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002268#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002269 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002270#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002271 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002272#endif
2273 }
2274 *e.linep++ = c;
2275 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002276
Eric Andersenff9eee42001-06-29 04:57:14 +00002277 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002278
2279 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2280
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002281 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002282}
2283
Eric Andersen12de6cf2004-08-04 19:19:10 +00002284/* "multiline commands" helper func */
2285/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002286static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002287{
2288 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002289 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002290
Eric Andersen12de6cf2004-08-04 19:19:10 +00002291 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2292
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002293 *cp++ = c; /* c is the given "peek" char */
2294 *cp++ = my_getc(0); /* get next char of input */
2295 *cp = '\0'; /* add EOS marker */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002296
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002297 c = rlookup(s); /* see if 2 chars form a shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002298 if (c == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002299 unget(*--cp); /* String is not a shell multiline, put peek char back */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002300
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002301 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002302}
2303
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002304static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002305{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002306 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002307
2308 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002309
2310 c = my_getc(0);
2311 if (c == '>' || c == '<') {
2312 if (c != ec)
2313 zzerr();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002314 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002315 c = my_getc(0);
2316 } else
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002317 yylval.i = (ec == '>' ? IOWRITE : IOREAD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002318 if (c != '&' || yylval.i == IOHERE)
2319 unget(c);
2320 else
2321 yylval.i |= IODUP;
2322}
2323
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002324static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002325{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002326 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002327
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002328 t = getcell(size);
2329 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002330 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002331 prs("command line too complicated\n");
2332 fail();
2333 /* NOTREACHED */
2334 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002335 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002336}
2337
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002338
Eric Andersenff9eee42001-06-29 04:57:14 +00002339/* VARARGS1 */
2340/* ARGSUSED */
2341
2342/* -------- exec.c -------- */
2343
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002344static struct op **find1case(struct op *t, const char *w)
2345{
2346 struct op *t1;
2347 struct op **tp;
2348 char **wp;
2349 char *cp;
2350
2351 if (t == NULL) {
2352 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
2353 return NULL;
2354 }
2355
2356 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
2357 T_CMD_NAMES[t->type]));
2358
2359 if (t->type == TLIST) {
2360 tp = find1case(t->left, w);
2361 if (tp != NULL) {
2362 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
2363 return tp;
2364 }
2365 t1 = t->right; /* TPAT */
2366 } else
2367 t1 = t;
2368
2369 for (wp = t1->words; *wp;) {
2370 cp = evalstr(*wp++, DOSUB);
2371 if (cp && gmatch(w, cp)) {
2372 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
2373 &t1->left));
2374 return &t1->left;
2375 }
2376 }
2377
2378 DBGPRINTF(("FIND1CASE: returning NULL\n"));
2379 return NULL;
2380}
2381
2382static struct op *findcase(struct op *t, const char *w)
2383{
2384 struct op **tp;
2385
2386 tp = find1case(t, w);
2387 return tp != NULL ? *tp : NULL;
2388}
2389
Eric Andersenff9eee42001-06-29 04:57:14 +00002390/*
2391 * execute tree
2392 */
2393
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002394static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002395{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002396 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002397 volatile int i, rv, a;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002398 const char *cp;
2399 char **wp, **wp2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002400 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002401 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002402 struct brkcon bc;
2403
2404#if __GNUC__
2405 /* Avoid longjmp clobbering */
2406 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002407#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002408
Eric Andersen12de6cf2004-08-04 19:19:10 +00002409 if (t == NULL) {
2410 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002411 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002412 }
2413
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002414 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002415 t->type, T_CMD_NAMES[t->type],
2416 ((t->words == NULL) ? "NULL" : t->words[0])));
2417
Eric Andersenff9eee42001-06-29 04:57:14 +00002418 rv = 0;
2419 a = areanum++;
2420 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002421 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2422 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002423
Eric Andersen8401eea2004-08-04 19:16:54 +00002424 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002425 case TDOT:
2426 DBGPRINTF3(("EXECUTE: TDOT\n"));
2427
2428 outtree_save = outtree;
2429
2430 newfile(evalstr(t->words[0], DOALL));
2431
2432 t->left = dowholefile(TLIST, 0);
2433 t->right = NULL;
2434
2435 outtree = outtree_save;
2436
2437 if (t->left)
2438 rv = execute(t->left, pin, pout, 0);
2439 if (t->right)
2440 rv = execute(t->right, pin, pout, 0);
2441 break;
2442
Eric Andersenff9eee42001-06-29 04:57:14 +00002443 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002444 rv = execute(t->left, pin, pout, 0);
2445 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002446
Eric Andersenff9eee42001-06-29 04:57:14 +00002447 case TCOM:
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002448 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002449 break;
2450
2451 case TPIPE:
2452 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002453 int pv[2];
2454
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002455 rv = openpipe(pv);
2456 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002457 break;
2458 pv[0] = remap(pv[0]);
2459 pv[1] = remap(pv[1]);
2460 (void) execute(t->left, pin, pv, 0);
2461 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002462 }
2463 break;
2464
2465 case TLIST:
2466 (void) execute(t->left, pin, pout, 0);
2467 rv = execute(t->right, pin, pout, 0);
2468 break;
2469
2470 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002471 {
2472 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002473
Eric Andersen12de6cf2004-08-04 19:19:10 +00002474 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2475
Eric Andersen8401eea2004-08-04 19:16:54 +00002476 i = vfork();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002477 if (i == 0) { /* child */
Eric Andersen8401eea2004-08-04 19:16:54 +00002478 signal(SIGINT, SIG_IGN);
2479 signal(SIGQUIT, SIG_IGN);
2480 if (interactive)
2481 signal(SIGTERM, SIG_DFL);
2482 interactive = 0;
2483 if (pin == NULL) {
2484 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002485 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002486 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002487 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002488 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002489 interactive = hinteractive;
2490 if (i != -1) {
2491 setval(lookup("!"), putn(i));
2492 if (pin != NULL)
2493 closepipe(pin);
2494 if (interactive) {
2495 prs(putn(i));
2496 prs("\n");
2497 }
2498 } else
2499 rv = -1;
2500 setstatus(rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002501 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002502 break;
2503
2504 case TOR:
2505 case TAND:
2506 rv = execute(t->left, pin, pout, 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002507 t1 = t->right;
2508 if (t1 != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002509 rv = execute(t1, pin, pout, 0);
2510 break;
2511
2512 case TFOR:
2513 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002514 wp = dolv + 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002515 i = dolc;
2516 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002517 i = 0;
2518 } else {
2519 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002520 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002521 }
2522 vp = lookup(t->str);
2523 while (setjmp(bc.brkpt))
2524 if (isbreak)
2525 goto broken;
2526 brkset(&bc);
2527 for (t1 = t->left; i-- && *wp != NULL;) {
2528 setval(vp, *wp++);
2529 rv = execute(t1, pin, pout, 0);
2530 }
2531 brklist = brklist->nextlev;
2532 break;
2533
2534 case TWHILE:
2535 case TUNTIL:
2536 while (setjmp(bc.brkpt))
2537 if (isbreak)
2538 goto broken;
2539 brkset(&bc);
2540 t1 = t->left;
2541 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2542 rv = execute(t->right, pin, pout, 0);
2543 brklist = brklist->nextlev;
2544 break;
2545
2546 case TIF:
2547 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002548 if (t->right != NULL) {
2549 rv = !execute(t->left, pin, pout, 0) ?
2550 execute(t->right->left, pin, pout, 0) :
2551 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002552 }
2553 break;
2554
2555 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002556 cp = evalstr(t->str, DOSUB | DOTRIM);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002557 if (cp == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002558 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002559
2560 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2561 ((t->str == NULL) ? "NULL" : t->str),
2562 ((cp == NULL) ? "NULL" : cp)));
2563
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002564 t1 = findcase(t->left, cp);
2565 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002566 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002567 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002568 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002569 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002570 break;
2571
2572 case TBRACE:
2573/*
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002574 iopp = t->ioact;
2575 if (i)
Eric Andersenff9eee42001-06-29 04:57:14 +00002576 while (*iopp)
2577 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2578 rv = -1;
2579 break;
2580 }
2581*/
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002582 if (rv >= 0) {
2583 t1 = t->left;
2584 if (t1) {
2585 rv = execute(t1, pin, pout, 0);
2586 }
2587 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002588 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002589
2590 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002591
Eric Andersen8401eea2004-08-04 19:16:54 +00002592 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002593 t->words = wp2;
2594 isbreak = 0;
2595 freehere(areanum);
2596 freearea(areanum);
2597 areanum = a;
2598 if (interactive && intr) {
2599 closeall();
2600 fail();
2601 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002602
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002603 i = trapset;
2604 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002605 trapset = 0;
2606 runtrap(i);
2607 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002608
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002609 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002610 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002611}
2612
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002613typedef int (*builtin_func_ptr)(struct op *);
2614
2615static builtin_func_ptr inbuilt(const char *s) {
2616 const struct builtincmd *bp;
2617
2618 for (bp = builtincmds; bp->name != NULL; bp++)
2619 if (strcmp(bp->name, s) == 0)
2620 return bp->builtinfunc;
2621
2622 return NULL;
2623}
2624
2625static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002626{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002627 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002628 int i, rv;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002629 builtin_func_ptr shcom = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002630 int f;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002631 const char *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002632 struct ioword **iopp;
2633 int resetsig;
2634 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002635 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002636
2637 int *hpin = pin;
2638 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002639 char *hwp;
2640 int hinteractive;
2641 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002642 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002643 int hexecflg;
2644
2645#if __GNUC__
2646 /* Avoid longjmp clobbering */
2647 (void) &pin;
2648 (void) &pout;
2649 (void) &wp;
2650 (void) &shcom;
2651 (void) &cp;
2652 (void) &resetsig;
2653 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002654#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002655
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002656 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002657 pout, act));
2658 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2659 ((t->words == NULL) ? "NULL" : t->words[0])));
2660
Eric Andersenff9eee42001-06-29 04:57:14 +00002661 owp = wp;
2662 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002663 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002664 if (t->type == TCOM) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002665 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002666 cp = *wp;
2667
2668 /* strip all initial assignments */
2669 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002670 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002671 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002672 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002673 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002674 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002675
Eric Andersenff9eee42001-06-29 04:57:14 +00002676 if (cp == NULL && t->ioact == NULL) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002677 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2678 /**/;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002679 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002680 return setstatus(0);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002681 }
2682 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002683 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002684 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002685 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002686
Eric Andersenff9eee42001-06-29 04:57:14 +00002687 t->words = wp;
2688 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002689
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002690 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002691 f & FEXEC, owp));
2692
2693 if (shcom == NULL && (f & FEXEC) == 0) {
2694 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002695 hpin = pin;
2696 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002697 hwp = *wp;
2698 hinteractive = interactive;
2699 hintr = intr;
2700 hbrklist = brklist;
2701 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002702
Eric Andersen12de6cf2004-08-04 19:19:10 +00002703 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2704
2705 newpid = vfork();
2706
2707 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002708 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002709 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002710 }
2711
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002712 if (newpid > 0) { /* Parent */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002713 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002714 pin = hpin;
2715 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002716 *wp = hwp;
2717 interactive = hinteractive;
2718 intr = hintr;
2719 brklist = hbrklist;
2720 execflg = hexecflg;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002721/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002722 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002723 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002724*/
Eric Andersenff9eee42001-06-29 04:57:14 +00002725 if (pin != NULL)
2726 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002727
2728 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002729 }
2730
Eric Andersen12de6cf2004-08-04 19:19:10 +00002731 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002732 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002733
Eric Andersenff9eee42001-06-29 04:57:14 +00002734 if (interactive) {
2735 signal(SIGINT, SIG_IGN);
2736 signal(SIGQUIT, SIG_IGN);
2737 resetsig = 1;
2738 }
2739 interactive = 0;
2740 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002741 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002742 brklist = 0;
2743 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002744 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002745
Eric Andersenff9eee42001-06-29 04:57:14 +00002746 if (owp != NULL)
2747 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2748 if (shcom == NULL)
2749 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002750
Eric Andersenff9eee42001-06-29 04:57:14 +00002751#ifdef COMPIPE
2752 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2753 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002754 if (forked)
2755 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002756 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002757 }
2758#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002759
Eric Andersenff9eee42001-06-29 04:57:14 +00002760 if (pin != NULL) {
2761 dup2(pin[0], 0);
2762 closepipe(pin);
2763 }
2764 if (pout != NULL) {
2765 dup2(pout[1], 1);
2766 closepipe(pout);
2767 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002768
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002769 iopp = t->ioact;
2770 if (iopp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002771 if (shcom != NULL && shcom != doexec) {
2772 prs(cp);
2773 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002774 if (forked)
2775 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002776 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002777 }
2778 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002779 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2780 if (forked)
2781 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002782 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002783 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002784 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002785
2786 if (shcom) {
2787 i = setstatus((*shcom) (t));
2788 if (forked)
2789 _exit(i);
2790 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002791 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002792 }
2793
Eric Andersenff9eee42001-06-29 04:57:14 +00002794 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002795 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002796 close(i);
2797 if (resetsig) {
2798 signal(SIGINT, SIG_DFL);
2799 signal(SIGQUIT, SIG_DFL);
2800 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002801
Eric Andersen12de6cf2004-08-04 19:19:10 +00002802 if (t->type == TPAREN)
2803 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2804 if (wp[0] == NULL)
2805 _exit(0);
2806
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002807 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002808 prs(wp[0]);
2809 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002810 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002811 if (!execflg)
2812 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002813
2814 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2815
Eric Andersenff9eee42001-06-29 04:57:14 +00002816 leave();
2817 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002818 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002819}
2820
2821/*
2822 * 0< 1> are ignored as required
2823 * within pipelines.
2824 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002825static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002826{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002827 int u = -1;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002828 char *cp = NULL;
2829 const char *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002830
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002831 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002832 pipein, pipeout));
2833
Eric Andersenff9eee42001-06-29 04:57:14 +00002834 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002835 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002836
Eric Andersenff9eee42001-06-29 04:57:14 +00002837 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002838 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002839
Eric Andersenff9eee42001-06-29 04:57:14 +00002840 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002841 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002842
Eric Andersen8401eea2004-08-04 19:16:54 +00002843 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002844 if ((iop->io_flag & IOHERE) == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002845 cp = iop->io_name; /* huh?? */
2846 cp = evalstr(cp, DOSUB | DOTRIM);
2847 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002848 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002849 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002850
Eric Andersenff9eee42001-06-29 04:57:14 +00002851 if (iop->io_flag & IODUP) {
2852 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2853 prs(cp);
2854 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002855 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002856 }
2857 if (*cp == '-')
2858 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002859 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002860 }
2861 switch (iop->io_flag) {
2862 case IOREAD:
2863 u = open(cp, 0);
2864 break;
2865
2866 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002867 case IOHERE | IOXHERE:
2868 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002869 cp = (char*)"here file";
Eric Andersenff9eee42001-06-29 04:57:14 +00002870 break;
2871
Eric Andersen8401eea2004-08-04 19:16:54 +00002872 case IOWRITE | IOCAT:
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002873 u = open(cp, 1);
2874 if (u >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002875 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002876 break;
2877 }
2878 case IOWRITE:
2879 u = creat(cp, 0666);
2880 break;
2881
2882 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002883 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002884 break;
2885
2886 case IOCLOSE:
2887 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002888 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002889 }
2890 if (u < 0) {
2891 prs(cp);
2892 prs(": cannot ");
2893 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002894 return 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002895 }
2896 if (u != iop->io_unit) {
2897 dup2(u, iop->io_unit);
2898 close(u);
Eric Andersenff9eee42001-06-29 04:57:14 +00002899 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002900 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002901}
2902
Eric Andersenff9eee42001-06-29 04:57:14 +00002903/*
2904 * Enter a new loop level (marked for break/continue).
2905 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002906static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00002907{
2908 bc->nextlev = brklist;
2909 brklist = bc;
2910}
2911
2912/*
2913 * Wait for the last process created.
2914 * Print a message for each process found
2915 * that was killed by a signal.
2916 * Ignore interrupt signals while waiting
2917 * unless `canintr' is true.
2918 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002919static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00002920{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002921 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002922 int s;
2923 int oheedint = heedint;
2924
2925 heedint = 0;
2926 rv = 0;
2927 do {
2928 pid = wait(&s);
2929 if (pid == -1) {
2930 if (errno != EINTR || canintr)
2931 break;
2932 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002933 rv = WAITSIG(s);
2934 if (rv != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002935 if (rv < NSIGNAL) {
2936 if (signame[rv] != NULL) {
2937 if (pid != lastpid) {
2938 prn(pid);
2939 prs(": ");
2940 }
2941 prs(signame[rv]);
2942 }
2943 } else {
2944 if (pid != lastpid) {
2945 prn(pid);
2946 prs(": ");
2947 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002948 prs("Signal ");
2949 prn(rv);
2950 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00002951 }
2952 if (WAITCORE(s))
2953 prs(" - core dumped");
2954 if (rv >= NSIGNAL || signame[rv])
2955 prs("\n");
2956 rv = -1;
2957 } else
2958 rv = WAITVAL(s);
2959 }
2960 } while (pid != lastpid);
2961 heedint = oheedint;
2962 if (intr) {
2963 if (interactive) {
2964 if (canintr)
2965 intr = 0;
2966 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00002967 if (exstat == 0)
2968 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002969 onintr(0);
2970 }
2971 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002972 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002973}
2974
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002975static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00002976{
2977 exstat = s;
2978 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002979 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002980}
2981
2982/*
2983 * PATH-searching interface to execve.
2984 * If getenv("PATH") were kept up-to-date,
2985 * execvp might be used.
2986 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002987static const char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002988{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002989 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002990 const char *sp;
2991 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00002992 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00002993 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002994
Rob Landleya299efb2006-08-10 21:46:43 +00002995 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
2996 optind = 1;
2997 if (find_applet_by_name(name)) {
2998 /* We have to exec here since we vforked. Running
2999 * run_applet_by_name() won't work and bad things
3000 * will happen. */
3001 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
3002 }
Eric Andersen1c039232001-07-07 00:05:55 +00003003 }
Eric Andersen1c039232001-07-07 00:05:55 +00003004
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003005 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003006
Eric Andersen8401eea2004-08-04 19:16:54 +00003007 sp = any('/', c) ? "" : path->value;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003008 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003009 while (asis || *sp != '\0') {
3010 asis = 0;
3011 tp = e.linep;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003012 for (; *sp != '\0'; tp++) {
3013 *tp = *sp++;
3014 if (*tp == ':') {
3015 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003016 break;
3017 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003018 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003019 if (tp != e.linep)
3020 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003021 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003022
Eric Andersen12de6cf2004-08-04 19:19:10 +00003023 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3024
Eric Andersenff9eee42001-06-29 04:57:14 +00003025 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003026
Eric Andersenff9eee42001-06-29 04:57:14 +00003027 switch (errno) {
3028 case ENOEXEC:
3029 *v = e.linep;
3030 tp = *--v;
3031 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003032 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003033 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003034 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003035
3036 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003037 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003038
3039 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003040 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003041
3042 case EACCES:
3043 eacces++;
3044 break;
3045 }
3046 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003047 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003048}
3049
3050/*
3051 * Run the command produced by generator `f'
3052 * applied to stream `arg'.
3053 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003054static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003055{
3056 struct op *otree;
3057 struct wdblock *swdlist;
3058 struct wdblock *siolist;
3059 jmp_buf ev, rt;
3060 xint *ofail;
3061 int rv;
3062
3063#if __GNUC__
3064 /* Avoid longjmp clobbering */
3065 (void) &rv;
3066#endif
3067
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003068 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003069 areanum, outtree, failpt));
3070
Eric Andersenff9eee42001-06-29 04:57:14 +00003071 areanum++;
3072 swdlist = wdlist;
3073 siolist = iolist;
3074 otree = outtree;
3075 ofail = failpt;
3076 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003077
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003078 errpt = ev;
3079 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003080 wdlist = 0;
3081 iolist = 0;
3082 pushio(argp, f);
3083 e.iobase = e.iop;
3084 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003085 failpt = rt;
3086 if (setjmp(failpt) == 0 && yyparse() == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003087 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3088 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003089 } else {
3090 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003091 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003092
Eric Andersenff9eee42001-06-29 04:57:14 +00003093 wdlist = swdlist;
3094 iolist = siolist;
3095 failpt = ofail;
3096 outtree = otree;
3097 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003098
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003099 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003100}
3101
3102/* -------- do.c -------- */
3103
3104/*
3105 * built-in commands: doX
3106 */
3107
Eric Andersen8401eea2004-08-04 19:16:54 +00003108static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003109{
3110 int col;
3111 const struct builtincmd *x;
3112
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003113 puts("\nBuilt-in commands:\n"
3114 "-------------------");
Eric Andersen1c039232001-07-07 00:05:55 +00003115
Eric Andersen8401eea2004-08-04 19:16:54 +00003116 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003117 if (!x->name)
3118 continue;
3119 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3120 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003121 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003122 col = 0;
3123 }
3124 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00003125#if ENABLE_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003126 {
3127 int i;
3128 const struct BB_applet *applet;
Eric Andersen1c039232001-07-07 00:05:55 +00003129
Eric Andersen8401eea2004-08-04 19:16:54 +00003130 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003131 if (!applet->name)
3132 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003133
Eric Andersen8401eea2004-08-04 19:16:54 +00003134 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003135 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003136 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003137 col = 0;
3138 }
3139 }
3140 }
3141#endif
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003142 puts("\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003143 return EXIT_SUCCESS;
3144}
3145
3146
3147
Eric Andersen8401eea2004-08-04 19:16:54 +00003148static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003149{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003150 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003151}
3152
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003153static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003154{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003155 const char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003156
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003157 cp = t->words[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003158 if (cp == NULL) {
3159 cp = homedir->value;
3160 if (cp == NULL)
3161 er = ": no home directory";
3162 } else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003163 er = ": bad directory";
3164 else
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003165 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003166 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003167 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003168 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003169}
3170
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003171static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003172{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003173 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003174
Eric Andersen8401eea2004-08-04 19:16:54 +00003175 n = t->words[1] ? getn(t->words[1]) : 1;
3176 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003177 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003178 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003179 }
3180 dolv[n] = dolv[0];
3181 dolv += n;
3182 dolc -= n;
3183 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003184 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003185}
3186
3187/*
3188 * execute login and newgrp directly
3189 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003190static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003191{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003192 const char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003193
3194 if (interactive) {
3195 signal(SIGINT, SIG_DFL);
3196 signal(SIGQUIT, SIG_DFL);
3197 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003198 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003199 prs(t->words[0]);
3200 prs(": ");
3201 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003202 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003203}
3204
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003205static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003206{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003207 int i, n;
3208 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003209
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003210 cp = t->words[1];
3211 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003212 i = umask(0);
3213 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003214 for (n = 3 * 4; (n -= 3) >= 0;)
3215 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003216 putc('\n', stderr);
3217 } else {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003218/* huh??? '8','9' are not allowed! */
Eric Andersen8401eea2004-08-04 19:16:54 +00003219 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3220 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003221 umask(n);
3222 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003223 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003224}
3225
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003226static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003227{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003228 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003229 jmp_buf ex;
3230 xint *ofail;
3231
3232 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003233 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003234 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003235 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003236 execflg = 1;
3237 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003238 failpt = ex;
3239 if (setjmp(failpt) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003240 execute(t, NOPIPE, NOPIPE, FEXEC);
3241 failpt = ofail;
3242 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003243 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003244}
3245
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003246static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003247{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003248 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003249 const char *sp;
3250 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003251 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003252 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003253
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003254 DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, e.linep is %s\n", t, t->left, t->right, ((e.linep == NULL) ? "NULL" : e.linep)));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003255
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003256 cp = t->words[1];
3257 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003258 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003259 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003260 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003261 DBGPRINTF(("DODOT: cp is %s\n", cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003262
Eric Andersen8401eea2004-08-04 19:16:54 +00003263 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003264
3265 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3266 ((sp == NULL) ? "NULL" : sp),
3267 ((e.linep == NULL) ? "NULL" : e.linep)));
3268
Eric Andersenff9eee42001-06-29 04:57:14 +00003269 while (*sp) {
3270 tp = e.linep;
3271 while (*sp && (*tp = *sp++) != ':')
3272 tp++;
3273 if (tp != e.linep)
3274 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003275
Eric Andersen8401eea2004-08-04 19:16:54 +00003276 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003277
3278 /* Original code */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003279 i = open(e.linep, 0);
3280 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003281 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003282 maltmp = remap(i);
3283 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3284
3285 next(maltmp); /* Basically a PUSHIO */
3286
3287 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3288
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003289 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003290 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003291 } /* while */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003292
Eric Andersenff9eee42001-06-29 04:57:14 +00003293 prs(cp);
3294 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003295
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003296 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003297}
3298
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003299static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003300{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003301 int i;
3302 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003303
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003304 cp = t->words[1];
3305 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003306 i = getn(cp);
3307 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003308 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003309 } else
3310 i = -1;
3311 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003312 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003313}
3314
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003315static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003316{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003317 char *cp, **wp;
3318 int nb = 0;
3319 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003320
3321 if (t->words[1] == NULL) {
3322 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003323 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003324 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003325 for (wp = t->words + 1; *wp; wp++) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003326 for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
3327 nb = read(0, cp, sizeof(*cp));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003328 if (nb != sizeof(*cp))
Eric Andersenff9eee42001-06-29 04:57:14 +00003329 break;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003330 nl = (*cp == '\n');
3331 if (nl || (wp[1] && any(*cp, ifs->value)))
3332 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003333 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003334 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003335 if (nb <= 0)
3336 break;
3337 setval(lookup(*wp), e.linep);
3338 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003339 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003340}
3341
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003342static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003343{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003344 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003345}
3346
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003347static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003348{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003349 int n, i;
3350 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003351
3352 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003353 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003354 if (trap[i]) {
3355 prn(i);
3356 prs(": ");
3357 prs(trap[i]);
3358 prs("\n");
3359 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003360 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003361 }
3362 resetsig = isdigit(*t->words[1]);
3363 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3364 n = getsig(t->words[i]);
3365 freecell(trap[n]);
3366 trap[n] = 0;
3367 if (!resetsig) {
3368 if (*t->words[1] != '\0') {
3369 trap[n] = strsave(t->words[1], 0);
3370 setsig(n, sig);
3371 } else
3372 setsig(n, SIG_IGN);
3373 } else {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003374 if (interactive) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003375 if (n == SIGINT)
3376 setsig(n, onintr);
3377 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003378 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003379 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00003380 setsig(n, SIG_DFL);
3381 }
3382 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003383 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003384}
3385
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003386static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003387{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003388 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003389
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003390 n = getn(s);
3391 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003392 err("trap: bad signal number");
3393 n = 0;
3394 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003395 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003396}
3397
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003398static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003399{
3400 if (n == 0)
3401 return;
3402 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3403 ourtrap[n] = 1;
3404 signal(n, f);
3405 }
3406}
3407
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003408static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003409{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003410 char *s;
3411 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003412
3413 s = as;
3414 m = 1;
3415 if (*s == '-') {
3416 m = -1;
3417 s++;
3418 }
3419 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003420 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003421 if (*s) {
3422 prs(as);
3423 err(": bad number");
3424 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003425 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003426}
3427
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003428static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003429{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003430 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003431}
3432
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003433static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003434{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003435 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003436}
3437
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003438static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003439{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003440 struct brkcon *bc;
3441 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003442
Eric Andersen8401eea2004-08-04 19:16:54 +00003443 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003444 if (nl <= 0)
3445 nl = 999;
3446 do {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003447 bc = brklist;
3448 if (bc == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003449 break;
3450 brklist = bc->nextlev;
3451 } while (--nl);
3452 if (nl) {
3453 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003454 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003455 }
3456 isbreak = val;
3457 longjmp(bc->brkpt, 1);
3458 /* NOTREACHED */
3459}
3460
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003461static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003462{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003463 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003464
3465 execflg = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003466 cp = t->words[1];
3467 if (cp != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003468 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003469
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003470 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003471
Eric Andersenff9eee42001-06-29 04:57:14 +00003472 leave();
3473 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003474 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003475}
3476
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003477static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003478{
Eric Andersen8401eea2004-08-04 19:16:54 +00003479 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003480 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003481}
3482
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003483static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003484{
Eric Andersen8401eea2004-08-04 19:16:54 +00003485 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003486 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003487}
3488
Eric Andersen8401eea2004-08-04 19:16:54 +00003489static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003490{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003491 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003492 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3493
Eric Andersenff9eee42001-06-29 04:57:14 +00003494 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003495 for (; *wp != NULL; wp++) {
3496 if (isassign(*wp)) {
3497 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003498
Matt Kraaif69bfc72001-07-12 19:39:59 +00003499 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003500 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003501 *cp = '\0';
3502 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003503 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003504 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003505 else
3506 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003507 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003508 } else
3509 putvlist(key, 1);
3510}
3511
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003512static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003513{
3514 prs(s);
3515 err(": bad identifier");
3516}
3517
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003518static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003519{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003520 struct var *vp;
3521 char *cp;
3522 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003523
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003524 cp = t->words[1];
3525 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003526 for (vp = vlist; vp; vp = vp->next)
3527 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003528 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003529 }
3530 if (*cp == '-') {
3531 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003532 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003533 if (*++cp == 0)
3534 flag['x'] = flag['v'] = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003535 else {
3536 for (; *cp; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003537 switch (*cp) {
3538 case 'e':
3539 if (!interactive)
3540 flag['e']++;
3541 break;
3542
3543 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003544 if (*cp >= 'a' && *cp <= 'z')
3545 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003546 break;
3547 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003548 }
3549 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003550 setdash();
3551 }
3552 if (t->words[1]) {
3553 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003554 for (n = 1; t->words[n]; n++)
3555 setarea((char *) t->words[n], 0);
3556 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003557 dolv = t->words;
3558 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003559 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003560 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003561 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003562}
3563
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003564static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003565{
Matt Kraai69edfec2001-08-06 14:14:18 +00003566 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003567 write(out, s, strlen(s));
3568 write(out, "\n", 1);
3569 }
3570}
3571
3572
3573/*
3574 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3575 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003576 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003577static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003578{
3579 struct tms buf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003580 long clk_tck = sysconf(_SC_CLK_TCK);
Eric Andersenff9eee42001-06-29 04:57:14 +00003581
3582 times(&buf);
3583 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003584 (int) (buf.tms_utime / clk_tck / 60),
3585 ((double) buf.tms_utime) / clk_tck,
3586 (int) (buf.tms_stime / clk_tck / 60),
3587 ((double) buf.tms_stime) / clk_tck,
3588 (int) (buf.tms_cutime / clk_tck / 60),
3589 ((double) buf.tms_cutime) / clk_tck,
3590 (int) (buf.tms_cstime / clk_tck / 60),
3591 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003592 return 0;
3593}
3594
3595
Eric Andersenff9eee42001-06-29 04:57:14 +00003596/* -------- eval.c -------- */
3597
3598/*
3599 * ${}
3600 * `command`
3601 * blank interpretation
3602 * quoting
3603 * glob
3604 */
3605
Eric Andersen8401eea2004-08-04 19:16:54 +00003606static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003607{
3608 struct wdblock *wb;
3609 char **wp;
3610 char **wf;
3611 jmp_buf ev;
3612
3613#if __GNUC__
3614 /* Avoid longjmp clobbering */
3615 (void) &wp;
3616 (void) &ap;
3617#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003618
3619 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3620
Eric Andersenff9eee42001-06-29 04:57:14 +00003621 wp = NULL;
3622 wb = NULL;
3623 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003624 errpt = ev;
3625 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003626 while (*ap && isassign(*ap))
3627 expand(*ap++, &wb, f & ~DOGLOB);
3628 if (flag['k']) {
3629 for (wf = ap; *wf; wf++) {
3630 if (isassign(*wf))
3631 expand(*wf, &wb, f & ~DOGLOB);
3632 }
3633 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003634 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003635 if (!flag['k'] || !isassign(*ap))
3636 expand(*ap, &wb, f & ~DOKEY);
3637 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003638 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003639 wp = getwords(wb);
3640 quitenv();
3641 } else
3642 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003643
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003644 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003645}
3646
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003647
Eric Andersenff9eee42001-06-29 04:57:14 +00003648/*
3649 * Make the exported environment from the exported
3650 * names in the dictionary. Keyword assignments
3651 * will already have been done.
3652 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003653static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003654{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003655 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003656
3657 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003658
Eric Andersenff9eee42001-06-29 04:57:14 +00003659 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003660 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003661 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003662 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003663 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003664}
3665
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003666static int expand(const char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003667{
3668 jmp_buf ev;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003669 char *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003670
3671#if __GNUC__
3672 /* Avoid longjmp clobbering */
3673 (void) &cp;
3674#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003675
3676 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3677
Eric Andersenff9eee42001-06-29 04:57:14 +00003678 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003679
Eric Andersenff9eee42001-06-29 04:57:14 +00003680 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003681 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003682
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003683 if (!anys("$`'\"", cp) && !anys(ifs->value, cp)
3684 && ((f & DOGLOB) == 0 || !anys("[*?", cp))
3685 ) {
3686 xp = strsave(cp, areanum);
Eric Andersenff9eee42001-06-29 04:57:14 +00003687 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003688 unquote(xp);
3689 *wbp = addword(xp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003690 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003691 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003692 errpt = ev;
3693 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003694 PUSHIO(aword, cp, strchar);
3695 e.iobase = e.iop;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003696 while ((xp = blank(f)) && gflg == 0) {
3697 e.linep = xp;
3698 xp = strsave(xp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003699 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003700 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003701 unquote(xp);
3702 *wbp = addword(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003703 } else
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003704 *wbp = glob(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003705 }
3706 quitenv();
3707 } else
3708 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003709 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003710}
3711
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003712static char *evalstr(char *cp, int f)
3713{
3714 struct wdblock *wb;
3715
3716 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
3717
3718 wb = NULL;
3719 if (expand(cp, &wb, f)) {
3720 if (wb == NULL || wb->w_nword == 0
3721 || (cp = wb->w_words[0]) == NULL
3722 ) {
3723// TODO: I suspect that
3724// char *evalstr(char *cp, int f) is actually
3725// const char *evalstr(const char *cp, int f)!
3726 cp = (char*)"";
3727 }
3728 DELETE(wb);
3729 } else
3730 cp = NULL;
3731 return cp;
3732}
3733
3734
Eric Andersenff9eee42001-06-29 04:57:14 +00003735/*
3736 * Blank interpretation and quoting
3737 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003738static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003739{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003740 int c, c1;
3741 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003742 int scanequals, foundequals;
3743
Eric Andersen12de6cf2004-08-04 19:19:10 +00003744 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3745
Eric Andersenff9eee42001-06-29 04:57:14 +00003746 sp = e.linep;
3747 scanequals = f & DOKEY;
3748 foundequals = 0;
3749
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003750 loop:
3751 c = subgetc('"', foundequals);
3752 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003753 case 0:
3754 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003755 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003756 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003757 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003758
3759 default:
3760 if (f & DOBLANK && any(c, ifs->value))
3761 goto loop;
3762 break;
3763
3764 case '"':
3765 case '\'':
3766 scanequals = 0;
3767 if (INSUB())
3768 break;
3769 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3770 if (c == 0)
3771 break;
3772 if (c == '\'' || !any(c, "$`\""))
3773 c |= QUOTE;
3774 *e.linep++ = c;
3775 }
3776 c = 0;
3777 }
3778 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003779 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003780 scanequals = 0;
3781 for (;;) {
3782 c = subgetc('"', foundequals);
3783 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003784 f & (DOBLANK && any(c, ifs->value)) ||
3785 (!INSUB() && any(c, "\"'"))) {
3786 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003787 unget(c);
3788 if (any(c, "\"'"))
3789 goto loop;
3790 break;
3791 }
3792 if (scanequals) {
3793 if (c == '=') {
3794 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003795 scanequals = 0;
3796 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003797 scanequals = 0;
3798 }
3799 *e.linep++ = c;
3800 }
3801 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003802 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003803}
3804
3805/*
3806 * Get characters, substituting for ` and $
3807 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003808static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003809{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003810 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003811
3812 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003813
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003814 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003815 c = my_getc(ec);
3816 if (!INSUB() && ec != '\'') {
3817 if (c == '`') {
3818 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003819 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003820 e.iop->task = XGRAVE;
3821 goto again;
3822 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003823 if (c == '$') {
3824 c = dollar(quoted);
3825 if (c == 0) {
3826 e.iop->task = XDOLL;
3827 goto again;
3828 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003829 }
3830 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003831 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003832}
3833
3834/*
3835 * Prepare to generate the string returned by ${} substitution.
3836 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003837static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003838{
3839 int otask;
3840 struct io *oiop;
3841 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003842 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003843 struct var *vp;
3844
Eric Andersen12de6cf2004-08-04 19:19:10 +00003845 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3846
Eric Andersenff9eee42001-06-29 04:57:14 +00003847 c = readc();
3848 s = e.linep;
3849 if (c != '{') {
3850 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003851 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003852 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003853 if (e.linep < elinep)
3854 *e.linep++ = c;
3855 unget(c);
3856 }
3857 c = 0;
3858 } else {
3859 oiop = e.iop;
3860 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003861
Eric Andersenff9eee42001-06-29 04:57:14 +00003862 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003863 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003864 if (e.linep < elinep)
3865 *e.linep++ = c;
3866 if (oiop == e.iop)
3867 e.iop->task = otask;
3868 if (c != '}') {
3869 err("unclosed ${");
3870 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003871 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003872 }
3873 }
3874 if (e.linep >= elinep) {
3875 err("string in ${} too long");
3876 gflg++;
3877 e.linep -= 10;
3878 }
3879 *e.linep = 0;
3880 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003881 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003882 if (any(*cp, "=-+?")) {
3883 c = *cp;
3884 *cp++ = 0;
3885 break;
3886 }
3887 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3888 if (dolc > 1) {
3889 /* currently this does not distinguish $* and $@ */
3890 /* should check dollar */
3891 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00003892 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003893 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003894 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00003895 s[0] = '1';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003896 s[1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003897 }
3898 }
3899 vp = lookup(s);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003900 dolp = vp->value;
3901 if (dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003902 switch (c) {
3903 case '=':
3904 if (isdigit(*s)) {
3905 err("cannot use ${...=...} with $n");
3906 gflg++;
3907 break;
3908 }
3909 setval(vp, cp);
3910 dolp = vp->value;
3911 break;
3912
3913 case '-':
3914 dolp = strsave(cp, areanum);
3915 break;
3916
3917 case '?':
3918 if (*cp == 0) {
3919 prs("missing value for ");
3920 err(s);
3921 } else
3922 err(cp);
3923 gflg++;
3924 break;
3925 }
3926 } else if (c == '+')
3927 dolp = strsave(cp, areanum);
3928 if (flag['u'] && dolp == null) {
3929 prs("unset variable: ");
3930 err(s);
3931 gflg++;
3932 }
3933 e.linep = s;
3934 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003935 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003936}
3937
3938/*
3939 * Run the command in `...` and read its output.
3940 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00003941
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003942static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003943{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003944 const char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003945 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00003946 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00003947 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00003948 static char child_cmd[LINELIM];
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003949 const char *src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00003950 char *dest;
3951 int count;
3952 int ignore;
3953 int ignore_once;
3954 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003955 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003956
3957#if __GNUC__
3958 /* Avoid longjmp clobbering */
3959 (void) &cp;
3960#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003961
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003962 for (cp = e.iop->argp->aword; *cp != '`'; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003963 if (*cp == 0) {
3964 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003965 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003966 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003967 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00003968
3969 /* string copy with dollar expansion */
3970 src = e.iop->argp->aword;
3971 dest = child_cmd;
3972 count = 0;
3973 ignore = 0;
3974 ignore_once = 0;
3975 while ((*src != '`') && (count < LINELIM)) {
3976 if (*src == '\'')
3977 ignore = !ignore;
3978 if (*src == '\\')
3979 ignore_once = 1;
3980 if (*src == '$' && !ignore && !ignore_once) {
3981 struct var *vp;
3982 char var_name[LINELIM];
3983 char alt_value[LINELIM];
3984 int var_index = 0;
3985 int alt_index = 0;
3986 char operator = 0;
3987 int braces = 0;
3988 char *value;
3989
3990 src++;
3991 if (*src == '{') {
3992 braces = 1;
3993 src++;
3994 }
3995
3996 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00003997 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00003998 var_name[var_index++] = *src++;
3999 var_name[var_index] = 0;
4000
4001 if (braces) {
4002 switch (*src) {
4003 case '}':
4004 break;
4005 case '-':
4006 case '=':
4007 case '+':
4008 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004009 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004010 break;
4011 default:
4012 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004013 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004014 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004015 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004016 src++;
4017 while (*src && (*src != '}')) {
4018 alt_value[alt_index++] = *src++;
4019 }
4020 alt_value[alt_index] = 0;
4021 if (*src != '}') {
4022 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004023 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004024 }
4025 }
4026 src++;
4027 }
4028
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004029 if (isalpha(*var_name)) {
4030 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004031
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004032 char *namep = var_name;
4033
4034 *dest++ = '$';
4035 if (braces)
4036 *dest++ = '{';
4037 while (*namep)
4038 *dest++ = *namep++;
4039 if (operator) {
4040 char *altp = alt_value;
4041 *dest++ = operator;
4042 while (*altp)
4043 *dest++ = *altp++;
4044 }
4045 if (braces)
4046 *dest++ = '}';
4047
4048 wb = addword(lookup(var_name)->name, wb);
4049 } else {
4050 /* expand */
4051
4052 vp = lookup(var_name);
4053 if (vp->value != null)
4054 value = (operator == '+') ?
4055 alt_value : vp->value;
4056 else if (operator == '?') {
4057 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004058 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004059 } else if (alt_index && (operator != '+')) {
4060 value = alt_value;
4061 if (operator == '=')
4062 setval(vp, value);
4063 } else
4064 continue;
4065
4066 while (*value && (count < LINELIM)) {
4067 *dest++ = *value++;
4068 count++;
4069 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004070 }
4071 } else {
4072 *dest++ = *src++;
4073 count++;
4074 ignore_once = 0;
4075 }
4076 }
4077 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004078
Eric Andersenff9eee42001-06-29 04:57:14 +00004079 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004080 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004081
Eric Andersen8401eea2004-08-04 19:16:54 +00004082 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004083
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004084 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004085
Eric Andersen737f5fb2003-03-14 16:05:59 +00004086 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004087 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004088 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004089 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004090 }
4091 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004092 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004093 e.iop->argp->aword = ++cp;
4094 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004095 PUSHIO(afile, remap(pf[0]),
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004096 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004097 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004098 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004099 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004100 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004101 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004102 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4103 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004104
Eric Andersenff9eee42001-06-29 04:57:14 +00004105 dup2(pf[1], 1);
4106 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004107
Eric Andersen8401eea2004-08-04 19:16:54 +00004108 argument_list[0] = (char *) DEFAULT_SHELL;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004109 argument_list[1] = (char *) "-c";
Eric Andersen737f5fb2003-03-14 16:05:59 +00004110 argument_list[2] = child_cmd;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004111 argument_list[3] = NULL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004112
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004113 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004114 prs(argument_list[0]);
4115 prs(": ");
4116 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004117 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004118}
4119
Eric Andersen737f5fb2003-03-14 16:05:59 +00004120
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004121static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004122{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004123 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004124
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004125 s = as;
4126 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004127 while (*s)
4128 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004129 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004130}
4131
4132/* -------- glob.c -------- */
4133
4134/*
4135 * glob
4136 */
4137
4138#define scopy(x) strsave((x), areanum)
4139#define BLKSIZ 512
4140#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4141
Eric Andersen8401eea2004-08-04 19:16:54 +00004142static struct wdblock *cl, *nl;
4143static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004144
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004145static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004146{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004147 int i;
4148 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004149
4150 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004151 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004152 i = 0;
4153 for (pp = cp; *pp; pp++)
4154 if (any(*pp, spcl))
4155 i++;
4156 else if (!any(*pp & ~QUOTE, spcl))
4157 *pp &= ~QUOTE;
4158 if (i != 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004159 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004160 nl = newword(cl->w_nword * 2);
4161 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004162 for (pp = cl->w_words[i]; *pp; pp++)
4163 if (any(*pp, spcl)) {
4164 globname(cl->w_words[i], pp);
4165 break;
4166 }
4167 if (*pp == '\0')
4168 nl = addword(scopy(cl->w_words[i]), nl);
4169 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004170 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004171 DELETE(cl->w_words[i]);
4172 DELETE(cl);
4173 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004174 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004175 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004176 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004177 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004178 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004179 wb = addword(cl->w_words[i], wb);
4180 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004181 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004182 }
4183 }
4184 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004185 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004186}
4187
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004188static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004189{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004190 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004191 char *name, *gp, *dp;
4192 int k;
4193 DIR *dirp;
4194 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004195 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004196 struct stat dbuf;
4197
4198 for (np = we; np != pp; pp--)
4199 if (pp[-1] == '/')
4200 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004201 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004202 *cp++ = *np++;
4203 *cp++ = '.';
4204 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004205 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004206 *cp++ = *np++;
4207 *cp = '\0';
4208 dirp = opendir(dp);
4209 if (dirp == 0) {
4210 DELETE(dp);
4211 DELETE(gp);
4212 return;
4213 }
4214 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004215 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004216 /* XXX Hmmm... What this could be? (abial) */
4217 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004218 if (ent[j].d_ino == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004219 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004220 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004221 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004222 if (dname[0] == '.')
4223 if (*gp != '.')
4224 continue;
4225 for (k = 0; k < NAME_MAX; k++)
4226 if (any(dname[k], spcl))
4227 dname[k] |= QUOTE;
4228 if (gmatch(dname, gp)) {
4229 name = generate(we, pp, dname, np);
4230 if (*np && !anys(np, spcl)) {
4231 if (stat(name, &dbuf)) {
4232 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004233 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004234 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004235 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004236 nl = addword(name, nl);
4237 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004238 }
4239 closedir(dirp);
4240 DELETE(dp);
4241 DELETE(gp);
4242}
4243
4244/*
4245 * generate a pathname as below.
4246 * start..end1 / middle end
4247 * the slashes come for free
4248 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004249static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004250{
4251 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004252 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004253
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004254 p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004255 for (xp = start1; xp != end1;)
4256 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004257 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004258 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004259 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004260 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004261}
4262
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004263static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004264{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004265 int i;
4266 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004267
4268 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004269 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004270 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004271 return 1;
4272 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004273}
4274
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004275static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004276{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004277 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004278}
4279
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004280
Eric Andersenff9eee42001-06-29 04:57:14 +00004281/* -------- word.c -------- */
4282
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004283static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004284{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004285 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004286
Eric Andersen8401eea2004-08-04 19:16:54 +00004287 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004288 wb->w_bsize = nw;
4289 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004290 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004291}
4292
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004293static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004294{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004295 struct wdblock *wb2;
4296 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004297
4298 if (wb == NULL)
4299 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004300 nw = wb->w_nword;
4301 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004302 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004303 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4304 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004305 wb2->w_nword = nw;
4306 DELETE(wb);
4307 wb = wb2;
4308 }
4309 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004310 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004311}
Eric Andersen8401eea2004-08-04 19:16:54 +00004312
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004313static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004314char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004315{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004316 char **wd;
4317 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004318
4319 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004320 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004321 if (wb->w_nword == 0) {
4322 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004323 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004324 }
4325 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004326 memcpy((char *) wd, (char *) wb->w_words, nb);
4327 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004328 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004329}
4330
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004331static int (*func) (char *, char *);
4332static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004333
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004334static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004335{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004336 char *index1, *index2, *index3;
4337 int c;
4338 int m;
4339
4340 m = globv;
4341 index1 = i;
4342 index2 = j;
4343 index3 = k;
4344 do {
4345 c = *index1;
4346 *index1++ = *index3;
4347 *index3++ = *index2;
4348 *index2++ = c;
4349 } while (--m);
4350}
4351
4352static void glob2(char *i, char *j)
4353{
4354 char *index1, *index2, c;
4355 int m;
4356
4357 m = globv;
4358 index1 = i;
4359 index2 = j;
4360 do {
4361 c = *index1;
4362 *index1++ = *index2;
4363 *index2++ = c;
4364 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004365}
4366
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004367static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004368{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004369 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004370 int v2;
4371 char *lptr, *hptr;
4372 int c;
4373 unsigned n;
4374
Eric Andersenff9eee42001-06-29 04:57:14 +00004375 v2 = globv;
4376
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004377 top:
4378 n = (int) (lim - base);
4379 if (n <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004380 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004381 n = v2 * (n / (2 * v2));
4382 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004383 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004384 j = lim - v2;
4385 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004386 if (i < lptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004387 c = (*func) (i, lptr);
4388 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004389 lptr -= v2;
4390 glob2(i, lptr);
Eric Andersenff9eee42001-06-29 04:57:14 +00004391 continue;
4392 }
4393 if (c < 0) {
4394 i += v2;
4395 continue;
4396 }
4397 }
4398
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004399 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004400 if (j > hptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004401 c = (*func) (hptr, j);
4402 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004403 hptr += v2;
4404 glob2(hptr, j);
Eric Andersenff9eee42001-06-29 04:57:14 +00004405 goto begin;
4406 }
4407 if (c > 0) {
4408 if (i == lptr) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004409 hptr += v2;
4410 glob3(i, hptr, j);
4411 i = (lptr += v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004412 goto begin;
4413 }
4414 glob2(i, j);
4415 j -= v2;
4416 i += v2;
4417 continue;
4418 }
4419 j -= v2;
4420 goto begin;
4421 }
4422
4423
4424 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004425 if (lptr - base >= lim - hptr) {
4426 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004427 lim = lptr;
4428 } else {
4429 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004430 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004431 }
4432 goto top;
4433 }
4434
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004435 lptr -= v2;
4436 glob3(j, lptr, i);
4437 j = (hptr -= v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004438 }
4439}
4440
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004441static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004442{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004443 func = a3;
4444 globv = a2;
4445 glob1(a0, a0 + a1 * a2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004446}
4447
Eric Andersenff9eee42001-06-29 04:57:14 +00004448
4449/* -------- io.c -------- */
4450
4451/*
4452 * shell IO
4453 */
4454
Eric Andersen8401eea2004-08-04 19:16:54 +00004455static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004456{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004457 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004458
Eric Andersen8401eea2004-08-04 19:16:54 +00004459 if (e.linep > elinep) {
4460 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004461 err("input line too long");
4462 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004463 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004464 }
4465 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004466 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004467 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004468 c = readc();
4469 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004470 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004471 c |= QUOTE;
4472 }
4473 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004474 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004475}
4476
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004477static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004478{
4479 if (e.iop >= e.iobase)
4480 e.iop->peekc = c;
4481}
4482
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004483static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004484{
Eric Andersen8401eea2004-08-04 19:16:54 +00004485 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004486}
4487
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004488static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004489{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004490 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004491
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004492 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004493
4494 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004495 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004496 c = e.iop->peekc;
4497 if (c != '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004498 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004499 return c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004500 }
4501 if (e.iop->prev != 0) {
4502 c = (*e.iop->iofn)(e.iop->argp, e.iop);
4503 if (c != '\0') {
4504 if (c == -1) {
4505 e.iop++;
4506 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004507 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004508 if (e.iop == iostack)
4509 ioecho(c);
4510 e.iop->prev = c;
4511 return e.iop->prev;
Eric Andersenff9eee42001-06-29 04:57:14 +00004512 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004513 if (e.iop->task == XIO && e.iop->prev != '\n') {
4514 e.iop->prev = 0;
4515 if (e.iop == iostack)
4516 ioecho('\n');
4517 return '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004518 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004519 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004520 if (e.iop->task == XIO) {
4521 if (multiline) {
4522 e.iop->prev = 0;
4523 return e.iop->prev;
4524 }
4525 if (interactive && e.iop == iostack + 1) {
4526#if ENABLE_FEATURE_EDITING
4527 current_prompt = prompt->value;
4528#else
4529 prs(prompt->value);
4530#endif
4531 }
4532 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004533 } /* FOR */
4534
4535 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004536 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004537 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004538 }
4539
4540 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004541 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004542
Eric Andersenff9eee42001-06-29 04:57:14 +00004543 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004544 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004545}
4546
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004547static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004548{
4549 if (flag['v'])
4550 write(2, &c, sizeof c);
4551}
4552
Eric Andersen12de6cf2004-08-04 19:19:10 +00004553
Eric Andersen8401eea2004-08-04 19:16:54 +00004554static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004555{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004556 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004557 argp->afid, e.iop));
4558
4559 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004560 if (++e.iop >= &iostack[NPUSH]) {
4561 e.iop--;
4562 err("Shell input nested too deeply");
4563 gflg++;
4564 return;
4565 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004566
4567 /* We did not overflow the NPUSH array spots so setup data structs */
4568
4569 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004570
4571 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004572 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004573 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004574
4575 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4576 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4577
4578 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4579
4580 if (e.iop == &iostack[0])
4581 e.iop->argp->afbuf = &mainbuf;
4582 else
4583 e.iop->argp->afbuf = &sharedbuf;
4584
4585 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4586 /* This line appears to be active when running scripts from command line */
4587 if ((isatty(e.iop->argp->afile) == 0)
4588 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004589 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004590 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4591 bufid = AFID_ID; /* AFID_ID = 0 */
4592
4593 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004594 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004595
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004596 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004597 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004598 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004599 &mainbuf, &sharedbuf, bufid, e.iop));
4600
Eric Andersenff9eee42001-06-29 04:57:14 +00004601 }
4602
Eric Andersen8401eea2004-08-04 19:16:54 +00004603 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004604 e.iop->peekc = 0;
4605 e.iop->xchar = 0;
4606 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004607
Eric Andersenff9eee42001-06-29 04:57:14 +00004608 if (fn == filechar || fn == linechar)
4609 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004610 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004611 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004612 e.iop->task = XGRAVE;
4613 else
4614 e.iop->task = XOTHER;
4615}
4616
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004617static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004618{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004619 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004620
4621 xp = e.iobase;
4622 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004623 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004624}
4625
4626/*
4627 * Input generating functions
4628 */
4629
4630/*
4631 * Produce the characters of a string, then a newline, then EOF.
4632 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004633static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004634{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004635 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004636
4637 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004638 return 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004639 c = *ap->aword++;
4640 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004641 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004642 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004643 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004644 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004645}
4646
4647/*
4648 * Given a list of words, produce the characters
4649 * in them, with a space after each word.
4650 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004651static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004652{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004653 char c;
4654 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004655
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004656 wl = ap->awordlist;
4657 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004658 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004659 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004660 c = *(*wl)++;
4661 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004662 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004663 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004664 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004665 }
4666 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004667 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004668}
4669
4670/*
4671 * Return the characters of a list of words,
4672 * producing a space between them.
4673 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004674static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004675{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004676 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004677
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004678 wp = *ap->awordlist++;
4679 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004680 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004681 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004682 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004683 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004684}
4685
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004686static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004687{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004688 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004689
4690 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004691 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004692 c = *ap->aword++;
4693 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004694 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004695 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004696 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004697 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004698}
4699
4700/*
4701 * Produce the characters from a single word (string).
4702 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004703static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004704{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004705 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004706 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004707 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004708}
4709
4710/*
4711 * Produce quoted characters from a single word (string).
4712 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004713static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004714{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004715 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004716
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004717 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004718 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004719 c = *ap->aword++;
4720 if (c)
4721 c |= QUOTE;
4722 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004723}
4724
4725/*
4726 * Return the characters from a file.
4727 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004728static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004729{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004730 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004731 char c;
4732 struct iobuf *bp = ap->afbuf;
4733
4734 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004735 i = (ap->afid != bp->id);
4736 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004737 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004738 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004739
Eric Andersen8401eea2004-08-04 19:16:54 +00004740 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4741 if (i <= 0) {
4742 closef(ap->afile);
4743 return 0;
4744 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004745
Eric Andersen8401eea2004-08-04 19:16:54 +00004746 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004747 bp->bufp = bp->buf;
4748 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004749 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004750
Eric Andersen8401eea2004-08-04 19:16:54 +00004751 ap->afpos++;
4752 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004753 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00004754#if ENABLE_FEATURE_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004755 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004756 static char mycommand[BUFSIZ];
4757 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004758
Eric Andersen8401eea2004-08-04 19:16:54 +00004759 while (size == 0 || position >= size) {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00004760 read_line_input(current_prompt, mycommand, BUFSIZ, line_input_state);
Eric Andersen8401eea2004-08-04 19:16:54 +00004761 size = strlen(mycommand);
4762 position = 0;
4763 }
4764 c = mycommand[position];
4765 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004766 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004767 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004768#endif
4769 i = safe_read(ap->afile, &c, sizeof(c));
4770 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004771}
4772
4773/*
4774 * Return the characters from a here temp file.
4775 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004776static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004777{
4778 char c;
4779
Eric Andersenff9eee42001-06-29 04:57:14 +00004780 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4781 close(ap->afile);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004782 c = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00004783 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004784 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004785}
4786
4787/*
4788 * Return the characters produced by a process (`...`).
4789 * Quote them if required, and remove any trailing newline characters.
4790 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004791static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004792{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004793 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004794
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004795 c = qgravechar(ap, iop) & ~QUOTE;
4796 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004797 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004798 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004799}
4800
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004801static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004802{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004803 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004804
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004805 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004806
4807 if (iop->xchar) {
4808 if (iop->nlcount) {
4809 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004810 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004811 }
4812 c = iop->xchar;
4813 iop->xchar = 0;
4814 } else if ((c = filechar(ap)) == '\n') {
4815 iop->nlcount = 1;
4816 while ((c = filechar(ap)) == '\n')
4817 iop->nlcount++;
4818 iop->xchar = c;
4819 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004820 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004821 iop->nlcount--;
4822 c = '\n';
4823 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004824 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004825}
4826
4827/*
4828 * Return a single command (usually the first line) from a file.
4829 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004830static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004831{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004832 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004833
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004834 c = filechar(ap);
4835 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004836 if (!multiline) {
4837 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004838 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004839 }
4840 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004841 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004842}
4843
Eric Andersenff9eee42001-06-29 04:57:14 +00004844/*
4845 * remap fd into Shell's fd space
4846 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004847static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004848{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004849 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004850 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004851 int newfd;
4852
Eric Andersen12de6cf2004-08-04 19:19:10 +00004853 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004854
4855 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004856 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004857 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004858
Eric Andersenff9eee42001-06-29 04:57:14 +00004859 do {
4860 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004861 newfd = dup(fd);
4862 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004863 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004864
Eric Andersen8401eea2004-08-04 19:16:54 +00004865 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004866 if (map[i])
4867 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004868
Eric Andersenff9eee42001-06-29 04:57:14 +00004869 if (fd < 0)
4870 err("too many files open in shell");
4871 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004872
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004873 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004874}
4875
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004876static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004877{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004878 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004879
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004880 i = pipe(pv);
4881 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004882 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004883 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004884}
4885
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004886static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004887{
4888 if (pv != NULL) {
4889 close(*pv++);
4890 close(*pv);
4891 }
4892}
4893
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004894
Eric Andersenff9eee42001-06-29 04:57:14 +00004895/* -------- here.c -------- */
4896
4897/*
4898 * here documents
4899 */
4900
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004901static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004902{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004903 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004904
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004905 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00004906
4907 h = (struct here *) space(sizeof(struct here));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004908 if (h == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004909 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004910
Eric Andersenff9eee42001-06-29 04:57:14 +00004911 h->h_tag = evalstr(s, DOSUB);
4912 if (h->h_tag == 0)
4913 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004914
Eric Andersenff9eee42001-06-29 04:57:14 +00004915 h->h_iop = iop;
4916 iop->io_name = 0;
4917 h->h_next = NULL;
4918 if (inhere == 0)
4919 inhere = h;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004920 else {
4921 for (lh = inhere; lh != NULL; lh = lh->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004922 if (lh->h_next == 0) {
4923 lh->h_next = h;
4924 break;
4925 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004926 }
4927 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004928 iop->io_flag |= IOHERE | IOXHERE;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004929 for (s = h->h_tag; *s; s++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004930 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004931 iop->io_flag &= ~IOXHERE;
4932 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004933 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004934 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004935 h->h_dosub = iop->io_flag & IOXHERE;
4936}
4937
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004938static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004939{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004940 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004941
4942 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004943
4944 /* Scan here files first leaving inhere list in place */
4945 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00004946 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00004947
4948 /* Make inhere list active - keep list intact for scraphere */
4949 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004950 hp->h_next = acthere;
4951 acthere = inhere;
4952 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004953 }
4954}
4955
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004956static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004957{
4958 int tf;
4959 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004960 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004961 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00004962 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004963 char *thenext;
4964
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004965 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004966
Eric Andersenff9eee42001-06-29 04:57:14 +00004967 tf = mkstemp(tname);
4968 if (tf < 0)
4969 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004970
Eric Andersenff9eee42001-06-29 04:57:14 +00004971 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004972 errpt = ev;
4973 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004974 unlink(tname);
4975 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00004976 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00004977 e.iobase = e.iop;
4978 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004979 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00004980#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00004981 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00004982#else
Eric Andersen8401eea2004-08-04 19:16:54 +00004983 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00004984#endif
4985 }
4986 thenext = myline;
4987 while ((c = my_getc(ec)) != '\n' && c) {
4988 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00004989 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004990 if (thenext >= &myline[LINELIM]) {
4991 c = 0;
4992 break;
4993 }
4994 *thenext++ = c;
4995 }
4996 *thenext = 0;
4997 if (strcmp(s, myline) == 0 || c == 0)
4998 break;
4999 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005000 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005001 }
5002 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005003 prs("here document `");
5004 prs(s);
5005 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005006 }
5007 quitenv();
5008 }
5009 close(tf);
5010}
5011
5012/*
5013 * open here temp file.
5014 * if unquoted here, expand here temp file into second temp file.
5015 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005016static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005017{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005018 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005019 int tf;
5020
5021#if __GNUC__
5022 /* Avoid longjmp clobbering */
5023 (void) &tf;
5024#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005025 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005026 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005027
5028 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5029
Eric Andersenff9eee42001-06-29 04:57:14 +00005030 hf = open(hname, 0);
5031 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005032 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005033
Eric Andersenff9eee42001-06-29 04:57:14 +00005034 if (xdoll) {
5035 char c;
5036 char tname[30] = ".msh_XXXXXX";
5037 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005038
Eric Andersenff9eee42001-06-29 04:57:14 +00005039 tf = mkstemp(tname);
5040 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005041 return -1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005042 errpt = ev;
5043 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005044 PUSHIO(afile, hf, herechar);
5045 setbase(e.iop);
5046 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005047 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005048 write(tf, &c, sizeof c);
5049 }
5050 quitenv();
5051 } else
5052 unlink(tname);
5053 close(tf);
5054 tf = open(tname, 0);
5055 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005056 return tf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005057 }
5058 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005059}
5060
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005061static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005062{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005063 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005064
5065 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005066
5067 for (h = inhere; h != NULL; h = h->h_next) {
5068 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005069 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005070 }
5071 inhere = NULL;
5072}
5073
5074/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005075static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005076{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005077 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005078
5079 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005080
5081 hl = NULL;
5082 for (h = acthere; h != NULL; h = h->h_next)
5083 if (getarea((char *) h) >= area) {
5084 if (h->h_iop->io_name != NULL)
5085 unlink(h->h_iop->io_name);
5086 if (hl == NULL)
5087 acthere = h->h_next;
5088 else
5089 hl->h_next = h->h_next;
5090 } else
5091 hl = h;
5092}
5093
5094
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005095/* -------- sh.c -------- */
5096/*
5097 * shell
5098 */
5099
Denis Vlasenko06af2162007-02-03 17:28:39 +00005100int msh_main(int argc, char **argv);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005101int msh_main(int argc, char **argv)
5102{
5103 int f;
5104 char *s;
5105 int cflag;
5106 char *name, **ap;
5107 int (*iof) (struct ioarg *);
5108
5109#if ENABLE_FEATURE_EDITING
5110 line_input_state = new_line_input_t(FOR_SHELL);
5111#endif
5112
5113 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
5114
5115 initarea();
5116 ap = environ;
5117 if (ap != NULL) {
5118 while (*ap)
5119 assign(*ap++, !COPYV);
5120 for (ap = environ; *ap;)
5121 export(lookup(*ap++));
5122 }
5123 closeall();
5124 areanum = 1;
5125
5126 shell = lookup("SHELL");
5127 if (shell->value == null)
5128 setval(shell, (char *)DEFAULT_SHELL);
5129 export(shell);
5130
5131 homedir = lookup("HOME");
5132 if (homedir->value == null)
5133 setval(homedir, "/");
5134 export(homedir);
5135
5136 setval(lookup("$"), putn(getpid()));
5137
5138 path = lookup("PATH");
5139 if (path->value == null) {
5140 if (geteuid() == 0)
5141 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
5142 else
5143 setval(path, "/bin:/usr/bin");
5144 }
5145 export(path);
5146
5147 ifs = lookup("IFS");
5148 if (ifs->value == null)
5149 setval(ifs, " \t\n");
5150
5151#ifdef MSHDEBUG
5152 mshdbg_var = lookup("MSHDEBUG");
5153 if (mshdbg_var->value == null)
5154 setval(mshdbg_var, "0");
5155#endif
5156
5157 prompt = lookup("PS1");
5158#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5159 if (prompt->value == null)
5160#endif
5161 setval(prompt, DEFAULT_USER_PROMPT);
5162 if (geteuid() == 0) {
5163 setval(prompt, DEFAULT_ROOT_PROMPT);
5164 prompt->status &= ~EXPORT;
5165 }
5166 cprompt = lookup("PS2");
5167#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5168 if (cprompt->value == null)
5169#endif
5170 setval(cprompt, "> ");
5171
5172 iof = filechar;
5173 cflag = 0;
5174 name = *argv++;
5175 if (--argc >= 1) {
5176 if (argv[0][0] == '-' && argv[0][1] != '\0') {
5177 for (s = argv[0] + 1; *s; s++)
5178 switch (*s) {
5179 case 'c':
5180 prompt->status &= ~EXPORT;
5181 cprompt->status &= ~EXPORT;
5182 setval(prompt, "");
5183 setval(cprompt, "");
5184 cflag = 1;
5185 if (--argc > 0)
5186 PUSHIO(aword, *++argv, iof = nlchar);
5187 break;
5188
5189 case 'q':
5190 qflag = SIG_DFL;
5191 break;
5192
5193 case 's':
5194 /* standard input */
5195 break;
5196
5197 case 't':
5198 prompt->status &= ~EXPORT;
5199 setval(prompt, "");
5200 iof = linechar;
5201 break;
5202
5203 case 'i':
5204 interactive++;
5205 default:
5206 if (*s >= 'a' && *s <= 'z')
5207 flag[(int) *s]++;
5208 }
5209 } else {
5210 argv--;
5211 argc++;
5212 }
5213
5214 if (iof == filechar && --argc > 0) {
5215 setval(prompt, "");
5216 setval(cprompt, "");
5217 prompt->status &= ~EXPORT;
5218 cprompt->status &= ~EXPORT;
5219
5220/* Shell is non-interactive, activate printf-based debug */
5221#ifdef MSHDEBUG
5222 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
5223 if (mshdbg < 0)
5224 mshdbg = 0;
5225#endif
5226 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
5227
5228 name = *++argv;
5229 if (newfile(name))
5230 exit(1); /* Exit on error */
5231 }
5232 }
5233
5234 setdash();
5235
5236 /* This won't be true if PUSHIO has been called, say from newfile() above */
5237 if (e.iop < iostack) {
5238 PUSHIO(afile, 0, iof);
5239 if (isatty(0) && isatty(1) && !cflag) {
5240 interactive++;
5241#if !ENABLE_FEATURE_SH_EXTRA_QUIET
5242#ifdef MSHDEBUG
5243 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
5244#else
5245 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
5246#endif
5247 printf("Enter 'help' for a list of built-in commands.\n\n");
5248#endif
5249 }
5250 }
5251
5252 signal(SIGQUIT, qflag);
5253 if (name && name[0] == '-') {
5254 interactive++;
5255 f = open(".profile", 0);
5256 if (f >= 0)
5257 next(remap(f));
5258 f = open("/etc/profile", 0);
5259 if (f >= 0)
5260 next(remap(f));
5261 }
5262 if (interactive)
5263 signal(SIGTERM, sig);
5264
5265 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
5266 signal(SIGINT, onintr);
5267 dolv = argv;
5268 dolc = argc;
5269 dolv[0] = name;
5270 if (dolc > 1) {
5271 for (ap = ++argv; --argc > 0;) {
5272 *ap = *argv++;
5273 if (assign(*ap, !COPYV)) {
5274 dolc--; /* keyword */
5275 } else {
5276 ap++;
5277 }
5278 }
5279 }
5280 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
5281
5282 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
5283
5284 for (;;) {
5285 if (interactive && e.iop <= iostack) {
5286#if ENABLE_FEATURE_EDITING
5287 current_prompt = prompt->value;
5288#else
5289 prs(prompt->value);
5290#endif
5291 }
5292 onecommand();
5293 /* Ensure that getenv("PATH") stays current */
5294 setenv("PATH", path->value, 1);
5295 }
5296
5297 DBGPRINTF(("MSH_MAIN: returning.\n"));
5298}
5299
5300
Eric Andersenff9eee42001-06-29 04:57:14 +00005301/*
5302 * Copyright (c) 1987,1997, Prentice Hall
5303 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005304 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005305 * Redistribution and use of the MINIX operating system in source and
5306 * binary forms, with or without modification, are permitted provided
5307 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005308 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005309 * Redistributions of source code must retain the above copyright
5310 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005311 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005312 * Redistributions in binary form must reproduce the above
5313 * copyright notice, this list of conditions and the following
5314 * disclaimer in the documentation and/or other materials provided
5315 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005316 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005317 * Neither the name of Prentice Hall nor the names of the software
5318 * authors or contributors may be used to endorse or promote
5319 * products derived from this software without specific prior
5320 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005321 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005322 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5323 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5324 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5325 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5326 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5327 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5328 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5329 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5330 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5331 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5332 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5333 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5334 *
5335 */