blob: 754a6fc2542d63b5afa31c62aefeb3153009f3a2 [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
108/*
109 * Description of a command or an operation on commands.
110 * Might eventually use a union.
111 */
112struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000113 int type; /* operation type, see below */
114 char **words; /* arguments to a command */
115 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000116 struct op *left;
117 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000118 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000119};
120
Eric Andersen8401eea2004-08-04 19:16:54 +0000121#define TCOM 1 /* command */
122#define TPAREN 2 /* (c-list) */
123#define TPIPE 3 /* a | b */
124#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000125#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000126#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000127#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000128#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000129#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000130#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000131#define TWHILE 11
132#define TUNTIL 12
133#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000134#define TPAT 14 /* pattern in case */
135#define TBRACE 15 /* {c-list} */
136#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000137/* Added to support "." file expansion */
138#define TDOT 17
139
140/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000141#ifdef MSHDEBUG
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000142static const char *const T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000143 "PLACEHOLDER",
144 "TCOM",
145 "TPAREN",
146 "TPIPE",
147 "TLIST",
148 "TOR",
149 "TAND",
150 "TFOR",
151 "TDO",
152 "TCASE",
153 "TIF",
154 "TWHILE",
155 "TUNTIL",
156 "TELIF",
157 "TPAT",
158 "TBRACE",
159 "TASYNC",
160 "TDOT",
161};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000162#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000163
164/*
165 * actions determining the environment of a process
166 */
167#define BIT(i) (1<<(i))
Eric Andersen8401eea2004-08-04 19:16:54 +0000168#define FEXEC BIT(0) /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000169
Eric Andersen12de6cf2004-08-04 19:19:10 +0000170#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000171
Eric Andersenff9eee42001-06-29 04:57:14 +0000172/*
173 * flags to control evaluation of words
174 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000175#define DOSUB 1 /* interpret $, `, and quotes */
176#define DOBLANK 2 /* perform blank interpretation */
177#define DOGLOB 4 /* interpret [?* */
178#define DOKEY 8 /* move words with `=' to 2nd arg. list */
179#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000180
181#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
182
Eric Andersenff9eee42001-06-29 04:57:14 +0000183
Eric Andersen12de6cf2004-08-04 19:19:10 +0000184/* PROTOTYPES */
Eric Andersenff9eee42001-06-29 04:57:14 +0000185static int newfile(char *s);
Eric Andersenff9eee42001-06-29 04:57:14 +0000186static char *cclass(char *p, int sub);
Eric Andersenff9eee42001-06-29 04:57:14 +0000187
188
Eric Andersen8401eea2004-08-04 19:16:54 +0000189struct brkcon {
190 jmp_buf brkpt;
191 struct brkcon *nextlev;
192};
Eric Andersenff9eee42001-06-29 04:57:14 +0000193
Eric Andersen12de6cf2004-08-04 19:19:10 +0000194
Eric Andersenff9eee42001-06-29 04:57:14 +0000195/*
196 * redirection
197 */
198struct ioword {
Eric Andersen8401eea2004-08-04 19:16:54 +0000199 short io_unit; /* unit affected */
200 short io_flag; /* action (below) */
201 char *io_name; /* file name */
Eric Andersenff9eee42001-06-29 04:57:14 +0000202};
Eric Andersenff9eee42001-06-29 04:57:14 +0000203
Eric Andersen12de6cf2004-08-04 19:19:10 +0000204#define IOREAD 1 /* < */
205#define IOHERE 2 /* << (here file) */
206#define IOWRITE 4 /* > */
207#define IOCAT 8 /* >> */
208#define IOXHERE 16 /* ${}, ` in << */
209#define IODUP 32 /* >&digit */
210#define IOCLOSE 64 /* >&- */
Eric Andersenff9eee42001-06-29 04:57:14 +0000211
Eric Andersen8401eea2004-08-04 19:16:54 +0000212#define IODEFAULT (-1) /* token for default IO unit */
213
Eric Andersen12de6cf2004-08-04 19:19:10 +0000214
Eric Andersenff9eee42001-06-29 04:57:14 +0000215
216/*
217 * parsing & execution environment
218 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000219static struct env {
220 char *linep;
221 struct io *iobase;
222 struct io *iop;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000223 xint *errpt; /* void * */
Eric Andersen8401eea2004-08-04 19:16:54 +0000224 int iofd;
225 struct env *oenv;
Eric Andersenff9eee42001-06-29 04:57:14 +0000226} e;
227
228/*
229 * flags:
230 * -e: quit on error
231 * -k: look for name=value everywhere on command line
232 * -n: no execution
233 * -t: exit after reading and executing one command
234 * -v: echo as read
235 * -x: trace
236 * -u: unset variables net diagnostic
237 */
Mike Frysinger3672fe92006-11-15 21:52:10 +0000238static char flags['z' - 'a' + 1];
239/* this looks weird, but is OK ... we index flag with 'a'...'z' */
240static char *flag = flags - 'a';
Eric Andersenff9eee42001-06-29 04:57:14 +0000241
Eric Andersen8401eea2004-08-04 19:16:54 +0000242static char *null; /* null value for variable */
243static int intr; /* interrupt pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000244
Eric Andersen8401eea2004-08-04 19:16:54 +0000245static char *trap[_NSIG + 1];
246static char ourtrap[_NSIG + 1];
247static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000248
Eric Andersen8401eea2004-08-04 19:16:54 +0000249static int heedint; /* heed interrupt signals */
Eric Andersenff9eee42001-06-29 04:57:14 +0000250
Eric Andersen8401eea2004-08-04 19:16:54 +0000251static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000252
Eric Andersen8401eea2004-08-04 19:16:54 +0000253static char line[LINELIM];
254static char *elinep;
Eric Andersenff9eee42001-06-29 04:57:14 +0000255
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000256#if ENABLE_FEATURE_EDITING
257static char *current_prompt;
258static line_input_t *line_input_state;
259#endif
260
261static int areanum; /* current allocation area */
262
Eric Andersen12de6cf2004-08-04 19:19:10 +0000263
Eric Andersenff9eee42001-06-29 04:57:14 +0000264/*
265 * other functions
266 */
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000267typedef int (*builtin_func_ptr)(struct op *);
268static builtin_func_ptr inbuilt(char *s);
Eric Andersen392947c2002-12-11 07:42:46 +0000269
Eric Andersen8401eea2004-08-04 19:16:54 +0000270static char *rexecve(char *c, char **v, char **envp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000271static char *evalstr(char *cp, int f);
272static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000273static char *unquote(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000274static int rlookup(char *n);
275static struct wdblock *glob(char *cp, struct wdblock *wb);
276static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000277static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000278static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000279static char **eval(char **ap, int f);
280static int setstatus(int s);
281static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000282
Eric Andersen8401eea2004-08-04 19:16:54 +0000283static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000284
Eric Andersen8401eea2004-08-04 19:16:54 +0000285static int newenv(int f);
286static void quitenv(void);
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +0000287static int anys(const char *s1, const char *s2);
288static int any(int c, const char *s);
Eric Andersen8401eea2004-08-04 19:16:54 +0000289static void next(int f);
290static void setdash(void);
291static void onecommand(void);
292static void runtrap(int i);
293static int gmatch(char *s, char *p);
Eric Andersenff9eee42001-06-29 04:57:14 +0000294
Eric Andersen12de6cf2004-08-04 19:19:10 +0000295
Eric Andersenff9eee42001-06-29 04:57:14 +0000296/* -------- area stuff -------- */
297
Eric Andersen12de6cf2004-08-04 19:19:10 +0000298#define REGSIZE sizeof(struct region)
299#define GROWBY (256)
300/* #define SHRINKBY (64) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000301#undef SHRINKBY
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000302#define FREE (32767)
303#define BUSY (0)
304#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000305
306
307struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000308 struct region *next;
309 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000310};
311
312
Eric Andersenff9eee42001-06-29 04:57:14 +0000313/* -------- grammar stuff -------- */
314typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000315 char *cp;
316 char **wp;
317 int i;
318 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000319} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000320
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000321#define WORD 256
322#define LOGAND 257
323#define LOGOR 258
324#define BREAK 259
325#define IF 260
326#define THEN 261
327#define ELSE 262
328#define ELIF 263
329#define FI 264
330#define CASE 265
331#define ESAC 266
332#define FOR 267
333#define WHILE 268
334#define UNTIL 269
335#define DO 270
336#define DONE 271
337#define IN 272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000338/* Added for "." file expansion */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000339#define DOT 273
Eric Andersen12de6cf2004-08-04 19:19:10 +0000340
Eric Andersenff9eee42001-06-29 04:57:14 +0000341#define YYERRCODE 300
342
343/* flags to yylex */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000344#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000345
Eric Andersen8401eea2004-08-04 19:16:54 +0000346static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000347static struct op *andor(void);
348static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000349static int synio(int cf);
350static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000351static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000352static struct op *nested(int type, int mark);
353static struct op *command(int cf);
354static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000355static struct op *thenpart(void);
356static struct op *elsepart(void);
357static struct op *caselist(void);
358static struct op *casepart(void);
359static char **pattern(void);
360static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000361static struct op *list(struct op *t1, struct op *t2);
362static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000363static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000364static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000365static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000366static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000367static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000368static struct ioword *io(int u, int f, char *cp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000369static int yylex(int cf);
370static int collect(int c, int c1);
371static int dual(int c);
372static void diag(int ec);
373static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000374
375/* -------- var.h -------- */
376
Eric Andersen8401eea2004-08-04 19:16:54 +0000377struct var {
378 char *value;
379 char *name;
380 struct var *next;
381 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000382};
Eric Andersenff9eee42001-06-29 04:57:14 +0000383
Eric Andersen8401eea2004-08-04 19:16:54 +0000384#define COPYV 1 /* flag to setval, suggesting copy */
385#define RONLY 01 /* variable is read-only */
386#define EXPORT 02 /* variable is to be exported */
387#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000388
Eric Andersen8401eea2004-08-04 19:16:54 +0000389static int yyparse(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000390
391static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000392
Eric Andersen12de6cf2004-08-04 19:19:10 +0000393
Eric Andersenff9eee42001-06-29 04:57:14 +0000394/* -------- io.h -------- */
395/* io buffer */
396struct iobuf {
Eric Andersen8401eea2004-08-04 19:16:54 +0000397 unsigned id; /* buffer id */
398 char buf[512]; /* buffer */
399 char *bufp; /* pointer into buffer */
400 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000401};
402
403/* possible arguments to an IO function */
404struct ioarg {
Eric Andersen8401eea2004-08-04 19:16:54 +0000405 char *aword;
406 char **awordlist;
407 int afile; /* file descriptor */
408 unsigned afid; /* buffer id */
409 long afpos; /* file position */
410 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000411};
Eric Andersen8401eea2004-08-04 19:16:54 +0000412
Eric Andersenff9eee42001-06-29 04:57:14 +0000413//static struct ioarg ioargstack[NPUSH];
414#define AFID_NOBUF (~0)
415#define AFID_ID 0
416
417/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000418struct io {
419 int (*iofn) (struct ioarg *, struct io *);
420 struct ioarg *argp;
421 int peekc;
422 char prev; /* previous character read by readc() */
423 char nlcount; /* for `'s */
424 char xchar; /* for `'s */
425 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000426};
Eric Andersen8401eea2004-08-04 19:16:54 +0000427
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000428//static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000429#define XOTHER 0 /* none of the below */
430#define XDOLL 1 /* expanding ${} */
431#define XGRAVE 2 /* expanding `'s */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000432#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000433
434/* in substitution */
435#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
436
Eric Andersen12de6cf2004-08-04 19:19:10 +0000437
Eric Andersenff9eee42001-06-29 04:57:14 +0000438/*
439 * input generators for IO structure
440 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000441static int nlchar(struct ioarg *ap);
442static int strchar(struct ioarg *ap);
443static int qstrchar(struct ioarg *ap);
444static int filechar(struct ioarg *ap);
445static int herechar(struct ioarg *ap);
446static int linechar(struct ioarg *ap);
447static int gravechar(struct ioarg *ap, struct io *iop);
448static int qgravechar(struct ioarg *ap, struct io *iop);
449static int dolchar(struct ioarg *ap);
450static int wdchar(struct ioarg *ap);
451static void scraphere(void);
452static void freehere(int area);
453static void gethere(void);
454static void markhere(char *s, struct ioword *iop);
455static int herein(char *hname, int xdoll);
456static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000457
Eric Andersen12de6cf2004-08-04 19:19:10 +0000458
Eric Andersen8401eea2004-08-04 19:16:54 +0000459static int eofc(void);
460static int readc(void);
461static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000462static void ioecho(char c);
Eric Andersenff9eee42001-06-29 04:57:14 +0000463
Eric Andersen12de6cf2004-08-04 19:19:10 +0000464
Eric Andersenff9eee42001-06-29 04:57:14 +0000465/*
466 * IO control
467 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000468static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
469static int remap(int fd);
470static int openpipe(int *pv);
471static void closepipe(int *pv);
472static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000473
Eric Andersenff9eee42001-06-29 04:57:14 +0000474#define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
475#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
476
477/* -------- 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);
496static void echo(char **wp);
497static struct op **find1case(struct op *t, char *w);
498static struct op *findcase(struct op *t, char *w);
499static void brkset(struct brkcon *bc);
500static int dolabel(struct op *t);
501static int dohelp(struct op *t);
502static int dochdir(struct op *t);
503static int doshift(struct op *t);
504static int dologin(struct op *t);
505static int doumask(struct op *t);
506static int doexec(struct op *t);
507static int dodot(struct op *t);
508static int dowait(struct op *t);
509static int doread(struct op *t);
510static int doeval(struct op *t);
511static int dotrap(struct op *t);
512static int getsig(char *s);
513static void setsig(int n, sighandler_t f);
514static int getn(char *as);
515static int dobreak(struct op *t);
516static int docontinue(struct op *t);
517static int brkcontin(char *cp, int val);
518static int doexit(struct op *t);
519static int doexport(struct op *t);
520static int doreadonly(struct op *t);
521static void rdexp(char **wp, void (*f) (struct var *), int key);
522static void badid(char *s);
523static int doset(struct op *t);
524static void varput(char *s, int out);
525static int dotimes(struct op *t);
526static int expand(char *cp, struct wdblock **wbp, int f);
527static char *blank(int f);
528static int dollar(int quoted);
529static int grave(int quoted);
530static void globname(char *we, char *pp);
531static char *generate(char *start1, char *end1, char *middle, char *end);
532static int anyspcl(struct wdblock *wb);
533static int xstrcmp(char *p1, char *p2);
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000534static void glob0(char *a0, unsigned a1, int a2,
Eric Andersen8401eea2004-08-04 19:16:54 +0000535 int (*a3) (char *, char *));
536static void glob1(char *base, char *lim);
537static void glob2(char *i, char *j);
538static void glob3(char *i, char *j, char *k);
539static void readhere(char **name, char *s, int ec);
540static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
541static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000542
Eric Andersen8401eea2004-08-04 19:16:54 +0000543struct here {
544 char *h_tag;
545 int h_dosub;
546 struct ioword *h_iop;
547 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000548};
549
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000550static const char * const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000551 "Signal 0",
552 "Hangup",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000553 NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000554 "Quit",
555 "Illegal instruction",
556 "Trace/BPT trap",
557 "Abort",
558 "Bus error",
559 "Floating Point Exception",
560 "Killed",
561 "SIGUSR1",
562 "SIGSEGV",
563 "SIGUSR2",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000564 NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000565 "Alarm clock",
566 "Terminated",
567};
Eric Andersen8401eea2004-08-04 19:16:54 +0000568
Eric Andersenff9eee42001-06-29 04:57:14 +0000569#define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
570
571struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000572 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000573 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000574};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000575static const struct res restab[] = {
Eric Andersen8401eea2004-08-04 19:16:54 +0000576 {"for", FOR},
577 {"case", CASE},
578 {"esac", ESAC},
579 {"while", WHILE},
580 {"do", DO},
581 {"done", DONE},
582 {"if", IF},
583 {"in", IN},
584 {"then", THEN},
585 {"else", ELSE},
586 {"elif", ELIF},
587 {"until", UNTIL},
588 {"fi", FI},
Eric Andersen8401eea2004-08-04 19:16:54 +0000589 {";;", BREAK},
590 {"||", LOGOR},
591 {"&&", LOGAND},
592 {"{", '{'},
593 {"}", '}'},
Eric Andersen12de6cf2004-08-04 19:19:10 +0000594 {".", DOT},
Eric Andersen8401eea2004-08-04 19:16:54 +0000595 {0, 0},
Eric Andersenff9eee42001-06-29 04:57:14 +0000596};
597
598
Eric Andersen1c039232001-07-07 00:05:55 +0000599struct builtincmd {
600 const char *name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000601 int (*builtinfunc) (struct op * t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000602};
Eric Andersen8401eea2004-08-04 19:16:54 +0000603static const struct builtincmd builtincmds[] = {
604 {".", dodot},
605 {":", dolabel},
606 {"break", dobreak},
607 {"cd", dochdir},
608 {"continue", docontinue},
609 {"eval", doeval},
610 {"exec", doexec},
611 {"exit", doexit},
612 {"export", doexport},
613 {"help", dohelp},
614 {"login", dologin},
615 {"newgrp", dologin},
616 {"read", doread},
617 {"readonly", doreadonly},
618 {"set", doset},
619 {"shift", doshift},
620 {"times", dotimes},
621 {"trap", dotrap},
622 {"umask", doumask},
623 {"wait", dowait},
624 {0, 0}
Eric Andersenff9eee42001-06-29 04:57:14 +0000625};
626
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000627static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000628static struct op *dowholefile(int, int);
629
Eric Andersen12de6cf2004-08-04 19:19:10 +0000630
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000631/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000632static char **dolv;
633static int dolc;
634static int exstat;
635static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000636static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000637static int execflg;
638static int multiline; /* \n changed to ; */
639static struct op *outtree; /* result from parser */
640static xint *failpt;
641static xint *errpt;
642static struct brkcon *brklist;
643static int isbreak;
644static struct wdblock *wdlist;
645static struct wdblock *iolist;
646static char *trap[_NSIG + 1];
647static char ourtrap[_NSIG + 1];
648static int trapset; /* trap pending */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000649
650#ifdef MSHDEBUG
651static struct var *mshdbg_var;
652#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000653static struct var *vlist; /* dictionary */
654static struct var *homedir; /* home directory */
655static struct var *prompt; /* main prompt */
656static struct var *cprompt; /* continuation prompt */
657static struct var *path; /* search path for commands */
658static struct var *shell; /* shell to interpret command files */
659static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000660
Eric Andersen8401eea2004-08-04 19:16:54 +0000661static int areanum; /* current allocation area */
662static int intr;
663static int inparse;
Eric Andersen8401eea2004-08-04 19:16:54 +0000664static char *null = "";
665static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000666static void (*qflag) (int) = SIG_IGN;
667static int startl;
668static int peeksym;
669static int nlseen;
670static int iounit = IODEFAULT;
671static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000672static char *elinep = line + sizeof(line) - 5;
673
674static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
675static struct ioarg ioargstack[NPUSH];
676static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000677static struct iobuf sharedbuf = { AFID_NOBUF };
678static struct iobuf mainbuf = { AFID_NOBUF };
Eric Andersenff9eee42001-06-29 04:57:14 +0000679static unsigned bufid = AFID_ID; /* buffer id counter */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000680
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000681static struct here *inhere; /* list of hear docs while parsing */
682static struct here *acthere; /* list of active here documents */
683static struct region *areabot; /* bottom of area */
684static struct region *areatop; /* top of area */
685static struct region *areanxt; /* starting point of scan */
Eric Andersen8401eea2004-08-04 19:16:54 +0000686static void *brktop;
687static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000688
Eric Andersen12de6cf2004-08-04 19:19:10 +0000689static struct env e = {
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000690 line, /* linep: char ptr */
691 iostack, /* iobase: struct io ptr */
692 iostack - 1, /* iop: struct io ptr */
693 (xint *) NULL, /* errpt: void ptr for errors? */
694 FDBASE, /* iofd: file desc */
695 (struct env *) NULL /* oenv: struct env ptr */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000696};
697
698#ifdef MSHDEBUG
699void print_t(struct op *t)
700{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000701 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
702 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000703
704 if (t->words) {
705 DBGPRINTF(("T: W1: %s", t->words[0]));
706 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000707}
708
709void print_tree(struct op *head)
710{
711 if (head == NULL) {
712 DBGPRINTF(("PRINT_TREE: no tree\n"));
713 return;
714 }
715
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000716 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000717 head->right));
718
719 if (head->left)
720 print_tree(head->left);
721
722 if (head->right)
723 print_tree(head->right);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000724}
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000725#endif /* MSHDEBUG */
726
727
728/*
729 * IO functions
730 */
731static void prs(const char *s)
732{
733 if (*s)
734 write(2, s, strlen(s));
735}
736
737static void prn(unsigned u)
738{
739 prs(itoa(u));
740}
741
742static void closef(int i)
743{
744 if (i > 2)
745 close(i);
746}
747
748static void closeall(void)
749{
750 int u;
751
752 for (u = NUFILE; u < NOFILE;)
753 close(u++);
754}
Eric Andersen12de6cf2004-08-04 19:19:10 +0000755
Eric Andersenff9eee42001-06-29 04:57:14 +0000756
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000757/* fail but return to process next command */
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000758static void fail(void) ATTRIBUTE_NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000759static void fail(void)
760{
761 longjmp(failpt, 1);
762 /* NOTREACHED */
763}
Eric Andersenff9eee42001-06-29 04:57:14 +0000764
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000765/* abort shell (or fail in subshell) */
766static void leave(void) ATTRIBUTE_NORETURN;
767static void leave(void)
768{
769 DBGPRINTF(("LEAVE: leave called!\n"));
770
771 if (execflg)
772 fail();
773 scraphere();
774 freehere(1);
775 runtrap(0);
776 _exit(exstat);
777 /* NOTREACHED */
778}
779
780static void warn(const char *s)
781{
782 if (*s) {
783 prs(s);
784 exstat = -1;
785 }
786 prs("\n");
787 if (flag['e'])
788 leave();
789}
790
791static void err(const char *s)
792{
793 warn(s);
794 if (flag['n'])
795 return;
796 if (!interactive)
797 leave();
798 if (e.errpt)
799 longjmp(e.errpt, 1);
800 closeall();
801 e.iop = e.iobase = iostack;
802}
803
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000804
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000805/* -------- area.c -------- */
806
Eric Andersenff9eee42001-06-29 04:57:14 +0000807/*
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000808 * All memory between (char *)areabot and (char *)(areatop+1) is
809 * exclusively administered by the area management routines.
810 * It is assumed that sbrk() and brk() manipulate the high end.
Eric Andersenff9eee42001-06-29 04:57:14 +0000811 */
812
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000813#define sbrk(X) ({ \
814 void * __q = (void *)-1; \
815 if (brkaddr + (int)(X) < brktop) { \
816 __q = brkaddr; \
817 brkaddr += (int)(X); \
818 } \
819 __q; \
820})
Eric Andersenff9eee42001-06-29 04:57:14 +0000821
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000822static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000823{
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000824 brkaddr = xmalloc(AREASIZE);
825 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +0000826
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000827 while ((long) sbrk(0) & ALIGN)
828 sbrk(1);
829 areabot = (struct region *) sbrk(REGSIZE);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000830
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000831 areabot->next = areabot;
832 areabot->area = BUSY;
833 areatop = areabot;
834 areanxt = areabot;
Eric Andersenff9eee42001-06-29 04:57:14 +0000835}
836
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000837static char *getcell(unsigned nbytes)
838{
839 int nregio;
840 struct region *p, *q;
841 int i;
842
843 if (nbytes == 0) {
844 puts("getcell(0)");
845 abort();
846 }
847 /* silly and defeats the algorithm */
848 /*
849 * round upwards and add administration area
850 */
851 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
852 p = areanxt;
853 for (;;) {
854 if (p->area > areanum) {
855 /*
856 * merge free cells
857 */
858 while ((q = p->next)->area > areanum && q != areanxt)
859 p->next = q->next;
860 /*
861 * exit loop if cell big enough
862 */
863 if (q >= p + nregio)
864 goto found;
865 }
866 p = p->next;
867 if (p == areanxt)
868 break;
869 }
870 i = nregio >= GROWBY ? nregio : GROWBY;
871 p = (struct region *) sbrk(i * REGSIZE);
872 if (p == (struct region *) -1)
873 return NULL;
874 p--;
875 if (p != areatop) {
876 puts("not contig");
877 abort(); /* allocated areas are contiguous */
878 }
879 q = p + i;
880 p->next = q;
881 p->area = FREE;
882 q->next = areabot;
883 q->area = BUSY;
884 areatop = q;
885 found:
886 /*
887 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
888 */
889 areanxt = p + nregio;
890 if (areanxt < q) {
891 /*
892 * split into requested area and rest
893 */
894 if (areanxt + 1 > q) {
895 puts("OOM");
896 abort(); /* insufficient space left for admin */
897 }
898 areanxt->next = q;
899 areanxt->area = FREE;
900 p->next = areanxt;
901 }
902 p->area = areanum;
903 return (char *) (p + 1);
904}
905
906static void freecell(char *cp)
907{
908 struct region *p;
909
910 p = (struct region *) cp;
911 if (p != NULL) {
912 p--;
913 if (p < areanxt)
914 areanxt = p;
915 p->area = FREE;
916 }
917}
918#define DELETE(obj) freecell((char *)obj)
919
920static void freearea(int a)
921{
922 struct region *p, *top;
923
924 top = areatop;
925 for (p = areabot; p != top; p = p->next)
926 if (p->area >= a)
927 p->area = FREE;
928}
929
930static void setarea(char *cp, int a)
931{
932 struct region *p;
933
934 p = (struct region *) cp;
935 if (p != NULL)
936 (p - 1)->area = a;
937}
938
939static int getarea(char *cp)
940{
941 return ((struct region *) cp - 1)->area;
942}
943
944static void garbage(void)
945{
946 struct region *p, *q, *top;
947
948 top = areatop;
949 for (p = areabot; p != top; p = p->next) {
950 if (p->area > areanum) {
951 while ((q = p->next)->area > areanum)
952 p->next = q->next;
953 areanxt = p;
954 }
955 }
956#ifdef SHRINKBY
957 if (areatop >= q + SHRINKBY && q->area > areanum) {
958 brk((char *) (q + 1));
959 q->next = areabot;
960 q->area = BUSY;
961 areatop = q;
962 }
963#endif
964}
965
966static char *space(int n)
967{
968 char *cp;
969
970 cp = getcell(n);
971 if (cp == '\0')
972 err("out of string space");
973 return cp;
974}
975
976static char *strsave(const char *s, int a)
977{
978 char *cp;
979
980 cp = space(strlen(s) + 1);
981 if (cp != NULL) {
982 setarea(cp, a);
983 strcpy(cp, s);
984 return cp;
985 }
986 return "";
987}
988
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000989
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000990/* -------- var.c -------- */
991
992static int eqname(const char *n1, const char *n2)
993{
994 for (; *n1 != '=' && *n1 != '\0'; n1++)
995 if (*n2++ != *n1)
996 return 0;
997 return *n2 == '\0' || *n2 == '=';
998}
999
1000static char *findeq(const char *cp)
1001{
1002 while (*cp != '\0' && *cp != '=')
1003 cp++;
1004 return cp;
1005}
1006
1007/*
1008 * Find the given name in the dictionary
1009 * and return its value. If the name was
1010 * not previously there, enter it now and
1011 * return a null value.
1012 */
1013static struct var *lookup(const char *n)
1014{
1015 struct var *vp;
1016 char *cp;
1017 int c;
1018 static struct var dummy;
1019
1020 if (isdigit(*n)) {
1021 dummy.name = n;
1022 for (c = 0; isdigit(*n) && c < 1000; n++)
1023 c = c * 10 + *n - '0';
1024 dummy.status = RONLY;
1025 dummy.value = (c <= dolc ? dolv[c] : null);
1026 return &dummy;
1027 }
1028 for (vp = vlist; vp; vp = vp->next)
1029 if (eqname(vp->name, n))
1030 return vp;
1031 cp = findeq(n);
1032 vp = (struct var *) space(sizeof(*vp));
1033 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
1034 dummy.name = dummy.value = "";
1035 return &dummy;
1036 }
1037 for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
1038 if (*cp == '\0')
1039 *cp = '=';
1040 *++cp = '\0';
1041 setarea((char *) vp, 0);
1042 setarea((char *) vp->name, 0);
1043 vp->value = null;
1044 vp->next = vlist;
1045 vp->status = GETCELL;
1046 vlist = vp;
1047 return vp;
1048}
1049
1050/*
1051 * if name is not NULL, it must be
1052 * a prefix of the space `val',
1053 * and end with `='.
1054 * this is all so that exporting
1055 * values is reasonably painless.
1056 */
1057static void nameval(struct var *vp, const char *val, const char *name)
1058{
1059 const char *cp;
1060 char *xp;
1061 int fl;
1062
1063 if (vp->status & RONLY) {
1064 xp = vp->name;
1065 while (*xp && *xp != '=')
1066 putc(*xp++, stderr);
1067 err(" is read-only");
1068 return;
1069 }
1070 fl = 0;
1071 if (name == NULL) {
1072 xp = space(strlen(vp->name) + strlen(val) + 2);
1073 if (xp == NULL)
1074 return;
1075 /* make string: name=value */
1076 setarea(xp, 0);
1077 name = xp;
1078 cp = vp->name;
1079 while ((*xp = *cp++) != '\0' && *xp != '=')
1080 xp++;
1081 *xp++ = '=';
1082 strcpy(xp, val);
1083 val = xp;
1084 fl = GETCELL;
1085 }
1086 if (vp->status & GETCELL)
1087 freecell(vp->name); /* form new string `name=value' */
1088 vp->name = name;
1089 vp->value = val;
1090 vp->status |= fl;
1091}
1092
1093/*
1094 * give variable at `vp' the value `val'.
1095 */
1096static void setval(struct var *vp, const char *val)
1097{
1098 nameval(vp, val, NULL);
1099}
1100
1101static void export(struct var *vp)
1102{
1103 vp->status |= EXPORT;
1104}
1105
1106static void ronly(struct var *vp)
1107{
1108 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1109 vp->status |= RONLY;
1110}
1111
1112static int isassign(const char *s)
1113{
1114 unsigned char c;
1115 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1116
1117 /* no isalpha() - we shouldn't use locale */
1118 c = *s;
1119 if (c != '_'
1120 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
1121 ) {
1122 return 0;
1123 }
1124 while (1) {
1125 c = *++s;
1126 if (c == '\0')
1127 return 0;
1128 if (c == '=')
1129 return 1;
1130 c |= 0x20; /* lowercase letters, doesn't affect numbers */
1131 if (c != '_'
1132 && (unsigned)(c - '0') > 9 /* not number */
1133 && (unsigned)(c - 'a') > 25 /* not letter */
1134 ) {
1135 return 0;
1136 }
1137 }
1138}
1139
1140static int assign(const char *s, int cf)
1141{
1142 char *cp;
1143 struct var *vp;
1144
1145 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1146
1147 if (!isalpha(*s) && *s != '_')
1148 return 0;
1149 for (cp = s; *cp != '='; cp++)
1150 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
1151 return 0;
1152 vp = lookup(s);
1153 nameval(vp, ++cp, cf == COPYV ? NULL : s);
1154 if (cf != COPYV)
1155 vp->status &= ~GETCELL;
1156 return 1;
1157}
1158
1159static int checkname(char *cp)
1160{
1161 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1162
1163 if (!isalpha(*cp++) && *(cp - 1) != '_')
1164 return 0;
1165 while (*cp)
1166 if (!isalnum(*cp++) && *(cp - 1) != '_')
1167 return 0;
1168 return 1;
1169}
1170
1171static void putvlist(int f, int out)
1172{
1173 struct var *vp;
1174
1175 for (vp = vlist; vp; vp = vp->next)
1176 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1177 if (vp->status & EXPORT)
1178 write(out, "export ", 7);
1179 if (vp->status & RONLY)
1180 write(out, "readonly ", 9);
1181 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
1182 write(out, "\n", 1);
1183 }
1184}
1185
1186
1187/*
1188 * trap handling
1189 */
1190static void sig(int i)
1191{
1192 trapset = i;
1193 signal(i, sig);
1194}
1195
1196static void runtrap(int i)
1197{
1198 char *trapstr;
1199
1200 trapstr = trap[i];
1201 if (trapstr == NULL)
1202 return;
1203
1204 if (i == 0)
1205 trap[i] = NULL;
1206
1207 RUN(aword, trapstr, nlchar);
1208}
1209
1210
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001211static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001212{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001213 char *cp;
1214 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001215 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001216
1217 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001218 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001219 if (flag[c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001220 *cp++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001221 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001222 setval(lookup("-"), m);
1223}
1224
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001225static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001226{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001227 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001228
1229 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001230
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001231 f = 0;
Denis Vlasenko9f739442006-12-16 23:49:13 +00001232 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001233 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001234 f = open(s, 0);
1235 if (f < 0) {
1236 prs(s);
1237 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001238 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001239 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001240 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001241
Eric Andersenff9eee42001-06-29 04:57:14 +00001242 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001243 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001244}
1245
Eric Andersen12de6cf2004-08-04 19:19:10 +00001246
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001247struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001248{
1249 struct op *dotnode;
1250
1251 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001252 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001253
1254 if (head->left != NULL) {
1255 dotnode = scantree(head->left);
1256 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001257 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001258 }
1259
1260 if (head->right != NULL) {
1261 dotnode = scantree(head->right);
1262 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001263 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001264 }
1265
1266 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001267 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001268
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001269 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001270
1271 if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001272 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001273 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001274 }
1275
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001276 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001277}
1278
1279
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001280static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001281{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001282 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001283 jmp_buf m1;
1284
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001285 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001286
Eric Andersenff9eee42001-06-29 04:57:14 +00001287 while (e.oenv)
1288 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001289
Eric Andersenff9eee42001-06-29 04:57:14 +00001290 areanum = 1;
1291 freehere(areanum);
1292 freearea(areanum);
1293 garbage();
1294 wdlist = 0;
1295 iolist = 0;
1296 e.errpt = 0;
1297 e.linep = line;
1298 yynerrs = 0;
1299 multiline = 0;
1300 inparse = 1;
1301 intr = 0;
1302 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001303
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001304 failpt = m1;
1305 setjmp(failpt); /* Bruce Evans' fix */
1306 failpt = m1;
1307 if (setjmp(failpt) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001308 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1309
Eric Andersenff9eee42001-06-29 04:57:14 +00001310 while (e.oenv)
1311 quitenv();
1312 scraphere();
1313 if (!interactive && intr)
1314 leave();
1315 inparse = 0;
1316 intr = 0;
1317 return;
1318 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001319
Eric Andersenff9eee42001-06-29 04:57:14 +00001320 inparse = 0;
1321 brklist = 0;
1322 intr = 0;
1323 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001324
1325 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001326 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001327 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001328 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001329 }
1330
Eric Andersenff9eee42001-06-29 04:57:14 +00001331 if (!interactive && intr) {
1332 execflg = 0;
1333 leave();
1334 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001335
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001336 i = trapset;
1337 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001338 trapset = 0;
1339 runtrap(i);
1340 }
1341}
1342
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001343static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001344{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001345 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001346
1347 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001348
1349 if (f) {
1350 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001351 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001352 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001353
Eric Andersenff9eee42001-06-29 04:57:14 +00001354 ep = (struct env *) space(sizeof(*ep));
1355 if (ep == NULL) {
1356 while (e.oenv)
1357 quitenv();
1358 fail();
1359 }
1360 *ep = e;
1361 e.oenv = ep;
1362 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001363
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001364 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001365}
1366
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001367static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001368{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001369 struct env *ep;
1370 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001371
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001372 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001373
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001374 ep = e.oenv;
1375 if (ep != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001376 fd = e.iofd;
1377 e = *ep;
1378 /* should close `'d files */
1379 DELETE(ep);
1380 while (--fd >= e.iofd)
1381 close(fd);
1382 }
1383}
1384
1385/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001386 * Is character c in s?
Eric Andersenff9eee42001-06-29 04:57:14 +00001387 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001388static int any(int c, const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001389{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001390 while (*s)
1391 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001392 return 1;
1393 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001394}
1395
1396/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001397 * Is any character from s1 in s2?
Eric Andersenff9eee42001-06-29 04:57:14 +00001398 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001399static int anys(const char *s1, const char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001400{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001401 while (*s1)
1402 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001403 return 1;
1404 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001405}
1406
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001407static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001408{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001409 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001410}
1411
Eric Andersen8401eea2004-08-04 19:16:54 +00001412static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001413{
1414 PUSHIO(afile, f, filechar);
1415}
1416
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001417static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001418{
1419 signal(SIGINT, onintr);
1420 intr = 1;
1421 if (interactive) {
1422 if (inparse) {
1423 prs("\n");
1424 fail();
1425 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001426 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001427 execflg = 0;
1428 leave();
1429 }
1430}
1431
Eric Andersenff9eee42001-06-29 04:57:14 +00001432/* -------- gmatch.c -------- */
1433/*
1434 * int gmatch(string, pattern)
1435 * char *string, *pattern;
1436 *
1437 * Match a pattern as in sh(1).
1438 */
1439
1440#define CMASK 0377
1441#define QUOTE 0200
1442#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001443#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001444
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001445static int gmatch(char *s, char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001446{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001447 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001448
1449 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001450 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001451 while ((pc = *p++ & CMASK) != '\0') {
1452 sc = *s++ & QMASK;
1453 switch (pc) {
1454 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001455 p = cclass(p, sc);
1456 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001457 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001458 break;
1459
1460 case '?':
1461 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001462 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001463 break;
1464
1465 case '*':
1466 s--;
1467 do {
1468 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001469 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001470 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001471 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001472
1473 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001474 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001475 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001476 }
1477 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001478 return *s == '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001479}
1480
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001481static char *cclass(char *p, int sub)
Eric Andersenff9eee42001-06-29 04:57:14 +00001482{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001483 int c, d, not, found;
Eric Andersenff9eee42001-06-29 04:57:14 +00001484
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001485 not = (*p == NOT);
1486 if (not != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00001487 p++;
1488 found = not;
1489 do {
1490 if (*p == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001491 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001492 c = *p & CMASK;
1493 if (p[1] == '-' && p[2] != ']') {
1494 d = p[2] & CMASK;
1495 p++;
1496 } else
1497 d = c;
1498 if (c == sub || (c <= sub && sub <= d))
1499 found = !not;
1500 } while (*++p != ']');
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001501 return found ? p + 1 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001502}
1503
1504
Eric Andersenff9eee42001-06-29 04:57:14 +00001505/* -------- csyn.c -------- */
1506/*
1507 * shell: syntax (C version)
1508 */
1509
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001510static void yyerror(const char *s) ATTRIBUTE_NORETURN;
1511static void yyerror(const char *s)
1512{
1513 yynerrs++;
1514 if (interactive && e.iop <= iostack) {
1515 multiline = 0;
1516 while (eofc() == 0 && yylex(0) != '\n');
1517 }
1518 err(s);
1519 fail();
1520}
1521
1522static void zzerr(void) ATTRIBUTE_NORETURN;
1523static void zzerr(void)
1524{
1525 yyerror("syntax error");
1526}
1527
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001528int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001529{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001530 DBGPRINTF7(("YYPARSE: enter...\n"));
1531
Eric Andersen8401eea2004-08-04 19:16:54 +00001532 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001533 peeksym = 0;
1534 yynerrs = 0;
1535 outtree = c_list();
1536 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001537 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001538}
1539
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001540static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001541{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001542 struct op *t, *p;
1543 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001544
1545 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001546
1547 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001548
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001549 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001550
Eric Andersenff9eee42001-06-29 04:57:14 +00001551 if (t != NULL) {
1552 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001553 p = command(CONTIN);
1554 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001555 DBGPRINTF8(("PIPELINE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001556 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001557 }
1558
Eric Andersenff9eee42001-06-29 04:57:14 +00001559 if (t->type != TPAREN && t->type != TCOM) {
1560 /* shell statement */
1561 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1562 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001563
Eric Andersenff9eee42001-06-29 04:57:14 +00001564 t = block(TPIPE, t, p, NOWORDS);
1565 }
1566 peeksym = c;
1567 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001568
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001569 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001570 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001571}
1572
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001573static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001574{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001575 struct op *t, *p;
1576 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001577
1578 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001579
1580 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001581
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001582 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001583
Eric Andersenff9eee42001-06-29 04:57:14 +00001584 if (t != NULL) {
1585 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001586 p = pipeline(CONTIN);
1587 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001588 DBGPRINTF8(("ANDOR: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001589 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001590 }
1591
Eric Andersen8401eea2004-08-04 19:16:54 +00001592 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001593 } /* WHILE */
1594
Eric Andersenff9eee42001-06-29 04:57:14 +00001595 peeksym = c;
1596 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001597
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001598 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001599 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001600}
1601
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001602static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001603{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001604 struct op *t, *p;
1605 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001606
1607 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001608
1609 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001610
Eric Andersenff9eee42001-06-29 04:57:14 +00001611 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001612 peeksym = yylex(0);
1613 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001614 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001615
Eric Andersen8401eea2004-08-04 19:16:54 +00001616 while ((c = yylex(0)) == ';' || c == '&'
1617 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001618
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001619 p = andor();
1620 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001621 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001622
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001623 peeksym = yylex(0);
1624 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001625 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001626
Eric Andersenff9eee42001-06-29 04:57:14 +00001627 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001628 } /* WHILE */
1629
Eric Andersenff9eee42001-06-29 04:57:14 +00001630 peeksym = c;
1631 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001632 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001633 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001634 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001635}
1636
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001637static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001638{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001639 struct ioword *iop;
1640 int i;
1641 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001642
1643 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001644
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001645 c = yylex(cf);
1646 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001647 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001648 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001649 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001650
Eric Andersenff9eee42001-06-29 04:57:14 +00001651 i = yylval.i;
1652 musthave(WORD, 0);
1653 iop = io(iounit, i, yylval.cp);
1654 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001655
Eric Andersenff9eee42001-06-29 04:57:14 +00001656 if (i & IOHERE)
1657 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001658
1659 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001660 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001661}
1662
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001663static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001664{
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001665 peeksym = yylex(cf);
1666 if (peeksym != c) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001667 DBGPRINTF7(("MUSTHAVE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001668 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001669 }
1670
Eric Andersenff9eee42001-06-29 04:57:14 +00001671 peeksym = 0;
1672}
1673
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001674static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001675{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001676 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001677
1678 t = NULL;
1679 for (;;) {
1680 switch (peeksym = yylex(0)) {
1681 case '<':
1682 case '>':
1683 (void) synio(0);
1684 break;
1685
1686 case WORD:
1687 if (t == NULL) {
1688 t = newtp();
1689 t->type = TCOM;
1690 }
1691 peeksym = 0;
1692 word(yylval.cp);
1693 break;
1694
1695 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001696 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001697 }
1698 }
1699}
1700
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001701static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001702{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001703 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001704
1705 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001706
1707 multiline++;
1708 t = c_list();
1709 musthave(mark, 0);
1710 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001711 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001712}
1713
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001714static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001715{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001716 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001717 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001718 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001719
1720 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001721
1722 iosave = iolist;
1723 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001724
Eric Andersenff9eee42001-06-29 04:57:14 +00001725 if (multiline)
1726 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001727
Eric Andersenff9eee42001-06-29 04:57:14 +00001728 while (synio(cf))
1729 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001730
1731 c = yylex(cf);
1732
1733 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001734 default:
1735 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001736 t = simple();
1737 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001738 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001739 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001740 t = newtp();
1741 t->type = TCOM;
1742 }
1743 break;
1744
1745 case '(':
1746 t = nested(TPAREN, ')');
1747 break;
1748
1749 case '{':
1750 t = nested(TBRACE, '}');
1751 break;
1752
1753 case FOR:
1754 t = newtp();
1755 t->type = TFOR;
1756 musthave(WORD, 0);
1757 startl = 1;
1758 t->str = yylval.cp;
1759 multiline++;
1760 t->words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001761 c = yylex(0);
1762 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001763 peeksym = c;
1764 t->left = dogroup(0);
1765 multiline--;
1766 break;
1767
1768 case WHILE:
1769 case UNTIL:
1770 multiline++;
1771 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001772 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001773 t->left = c_list();
1774 t->right = dogroup(1);
1775 t->words = NULL;
1776 multiline--;
1777 break;
1778
1779 case CASE:
1780 t = newtp();
1781 t->type = TCASE;
1782 musthave(WORD, 0);
1783 t->str = yylval.cp;
1784 startl++;
1785 multiline++;
1786 musthave(IN, CONTIN);
1787 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001788
Eric Andersenff9eee42001-06-29 04:57:14 +00001789 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001790
Eric Andersenff9eee42001-06-29 04:57:14 +00001791 musthave(ESAC, 0);
1792 multiline--;
1793 break;
1794
1795 case IF:
1796 multiline++;
1797 t = newtp();
1798 t->type = TIF;
1799 t->left = c_list();
1800 t->right = thenpart();
1801 musthave(FI, 0);
1802 multiline--;
1803 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001804
1805 case DOT:
1806 t = newtp();
1807 t->type = TDOT;
1808
1809 musthave(WORD, 0); /* gets name of file */
1810 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1811
1812 word(yylval.cp); /* add word to wdlist */
1813 word(NOWORD); /* terminate wdlist */
1814 t->words = copyw(); /* dup wdlist */
1815 break;
1816
Eric Andersenff9eee42001-06-29 04:57:14 +00001817 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001818
Eric Andersen8401eea2004-08-04 19:16:54 +00001819 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001820
Eric Andersenff9eee42001-06-29 04:57:14 +00001821 t = namelist(t);
1822 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001823
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001824 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001825
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001826 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001827}
1828
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001829static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001830{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001831 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001832
1833 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
1834
1835 multiline++;
1836 t = c_list();
1837 multiline--;
1838 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001839 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001840 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001841}
1842
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001843static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00001844{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001845 int c;
1846 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001847
1848 c = yylex(CONTIN);
1849 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001850 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001851 if (c != DO)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001852 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001853 mylist = c_list();
1854 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001855 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001856}
1857
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001858static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001859{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001860 int c;
1861 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001862
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001863 c = yylex(0);
1864 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001865 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001866 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001867 }
1868 t = newtp();
1869 t->type = 0;
1870 t->left = c_list();
1871 if (t->left == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001872 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001873 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001874 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001875}
1876
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001877static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001878{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001879 int c;
1880 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001881
1882 switch (c = yylex(0)) {
1883 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001884 t = c_list();
1885 if (t == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001886 zzerr();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001887 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001888
1889 case ELIF:
1890 t = newtp();
1891 t->type = TELIF;
1892 t->left = c_list();
1893 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001894 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001895
1896 default:
1897 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001898 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001899 }
1900}
1901
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001902static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001903{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001904 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001905
1906 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001907 while ((peeksym = yylex(CONTIN)) != ESAC) {
1908 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00001909 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00001910 }
1911
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001912 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001913 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001914}
1915
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001916static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001917{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001918 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001919
1920 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001921
1922 t = newtp();
1923 t->type = TPAT;
1924 t->words = pattern();
1925 musthave(')', 0);
1926 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001927 peeksym = yylex(CONTIN);
1928 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00001929 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001930
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001931 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001932
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001933 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001934}
1935
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001936static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001937{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001938 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00001939
1940 cf = CONTIN;
1941 do {
1942 musthave(WORD, cf);
1943 word(yylval.cp);
1944 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001945 c = yylex(0);
1946 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00001947 peeksym = c;
1948 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001949
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001950 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00001951}
1952
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001953static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001954{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001955 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001956
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001957 c = yylex(0);
1958 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001959 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001960 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001961 }
1962 startl = 0;
1963 while ((c = yylex(0)) == WORD)
1964 word(yylval.cp);
1965 word(NOWORD);
1966 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001967 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00001968}
1969
1970/*
1971 * supporting functions
1972 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001973static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001974{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001975 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001976
Eric Andersenff9eee42001-06-29 04:57:14 +00001977 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001978 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00001979 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001980 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001981
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001982 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001983}
1984
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001985static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001986{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001987 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001988
1989 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00001990
1991 t = newtp();
1992 t->type = type;
1993 t->left = t1;
1994 t->right = t2;
1995 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001996
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001997 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00001998 t2));
1999
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002000 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002001}
2002
Eric Andersen12de6cf2004-08-04 19:19:10 +00002003/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002004static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002005{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002006 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002007
2008 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002009
2010 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002011 if (strcmp(rp->r_name, n) == 0) {
2012 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002013 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002014 }
2015
2016 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002017 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002018}
2019
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002020static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002021{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002022 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002023
Eric Andersen8401eea2004-08-04 19:16:54 +00002024 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002025 t->type = 0;
2026 t->words = NULL;
2027 t->ioact = NULL;
2028 t->left = NULL;
2029 t->right = NULL;
2030 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002031
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002032 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002033
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002034 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002035}
2036
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002037static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002038{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002039
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002040 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002041 T_CMD_NAMES[t->type], iolist));
2042
Eric Andersenff9eee42001-06-29 04:57:14 +00002043 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002044 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002045 t->ioact = copyio();
2046 } else
2047 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002048
Eric Andersenff9eee42001-06-29 04:57:14 +00002049 if (t->type != TCOM) {
2050 if (t->type != TPAREN && t->ioact != NULL) {
2051 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2052 t->ioact = t->left->ioact;
2053 t->left->ioact = NULL;
2054 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002055 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002056 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002057
Eric Andersenff9eee42001-06-29 04:57:14 +00002058 word(NOWORD);
2059 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002060
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002061 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002062}
2063
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002064static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002065{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002066 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002067
2068 wd = getwords(wdlist);
2069 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002070 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002071}
2072
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002073static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002074{
2075 wdlist = addword(cp, wdlist);
2076}
2077
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002078static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002079{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002080 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002081
2082 iop = (struct ioword **) getwords(iolist);
2083 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002084 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002085}
2086
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002087static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002088{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002089 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002090
2091 iop = (struct ioword *) tree(sizeof(*iop));
2092 iop->io_unit = u;
2093 iop->io_flag = f;
2094 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002095 iolist = addword((char *) iop, iolist);
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 int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002100{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002101 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002102 int atstart;
2103
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002104 c = peeksym;
2105 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002106 peeksym = 0;
2107 if (c == '\n')
2108 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002109 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002110 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002111
Eric Andersenff9eee42001-06-29 04:57:14 +00002112 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002113 atstart = startl;
2114 startl = 0;
2115 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002116 e.linep = line;
2117
2118/* MALAMO */
2119 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002120
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002121 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002122 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2123 ;
2124
Eric Andersenff9eee42001-06-29 04:57:14 +00002125 switch (c) {
2126 default:
2127 if (any(c, "0123456789")) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002128 c1 = my_getc(0);
2129 unget(c1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002130 if (c1 == '<' || c1 == '>') {
2131 iounit = c - '0';
2132 goto loop;
2133 }
2134 *e.linep++ = c;
2135 c = c1;
2136 }
2137 break;
2138
Eric Andersen12de6cf2004-08-04 19:19:10 +00002139 case '#': /* Comment, skip to next newline or End-of-string */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002140 while ((c = my_getc(0)) != '\0' && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002141 unget(c);
2142 goto loop;
2143
2144 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002145 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002146 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002147
2148 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002149 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002150 *e.linep++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002151 c = my_getc(0);
2152 if (c == '{') {
2153 c = collect(c, '}');
2154 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002155 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002156 goto pack;
2157 }
2158 break;
2159
2160 case '`':
2161 case '\'':
2162 case '"':
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002163 c = collect(c, c);
2164 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002165 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002166 goto pack;
2167
2168 case '|':
2169 case '&':
2170 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002171 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002172 /* If more chars process them, else return NULL char */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002173 c1 = dual(c);
2174 if (c1 != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002175 return c1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002176 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002177
Eric Andersenff9eee42001-06-29 04:57:14 +00002178 case '^':
2179 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002180 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002181 case '>':
2182 case '<':
2183 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002184 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002185
2186 case '\n':
2187 nlseen++;
2188 gethere();
2189 startl = 1;
2190 if (multiline || cf & CONTIN) {
2191 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002192#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002193 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002194#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002195 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002196#endif
2197 }
2198 if (cf & CONTIN)
2199 goto loop;
2200 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002201 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002202
2203 case '(':
2204 case ')':
2205 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002206 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002207 }
2208
2209 unget(c);
2210
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002211 pack:
2212 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002213 if (e.linep >= elinep)
2214 err("word too long");
2215 else
2216 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002217 };
2218
Eric Andersenff9eee42001-06-29 04:57:14 +00002219 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002220
Eric Andersen8401eea2004-08-04 19:16:54 +00002221 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002222 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002223
Eric Andersenff9eee42001-06-29 04:57:14 +00002224 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002225
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002226 if (atstart) {
2227 c = rlookup(line);
2228 if (c != 0) {
2229 startl = 1;
2230 return c;
2231 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002232 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002233
Eric Andersenff9eee42001-06-29 04:57:14 +00002234 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002235 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002236}
2237
Eric Andersen12de6cf2004-08-04 19:19:10 +00002238
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002239static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002240{
2241 char s[2];
2242
Eric Andersen12de6cf2004-08-04 19:19:10 +00002243 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2244
Eric Andersenff9eee42001-06-29 04:57:14 +00002245 *e.linep++ = c;
2246 while ((c = my_getc(c1)) != c1) {
2247 if (c == 0) {
2248 unget(c);
2249 s[0] = c1;
2250 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002251 prs("no closing ");
2252 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002253 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002254 }
2255 if (interactive && c == '\n' && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002256#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002257 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002258#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002259 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002260#endif
2261 }
2262 *e.linep++ = c;
2263 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002264
Eric Andersenff9eee42001-06-29 04:57:14 +00002265 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002266
2267 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2268
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002269 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002270}
2271
Eric Andersen12de6cf2004-08-04 19:19:10 +00002272/* "multiline commands" helper func */
2273/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002274static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002275{
2276 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002277 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002278
Eric Andersen12de6cf2004-08-04 19:19:10 +00002279 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2280
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002281 *cp++ = c; /* c is the given "peek" char */
2282 *cp++ = my_getc(0); /* get next char of input */
2283 *cp = '\0'; /* add EOS marker */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002284
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002285 c = rlookup(s); /* see if 2 chars form a shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002286 if (c == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002287 unget(*--cp); /* String is not a shell multiline, put peek char back */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002288
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002289 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002290}
2291
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002292static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002293{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002294 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002295
2296 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002297
2298 c = my_getc(0);
2299 if (c == '>' || c == '<') {
2300 if (c != ec)
2301 zzerr();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002302 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002303 c = my_getc(0);
2304 } else
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002305 yylval.i = (ec == '>' ? IOWRITE : IOREAD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002306 if (c != '&' || yylval.i == IOHERE)
2307 unget(c);
2308 else
2309 yylval.i |= IODUP;
2310}
2311
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002312static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002313{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002314 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002315
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002316 t = getcell(size);
2317 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002318 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002319 prs("command line too complicated\n");
2320 fail();
2321 /* NOTREACHED */
2322 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002323 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002324}
2325
2326/* VARARGS1 */
2327/* ARGSUSED */
2328
2329/* -------- exec.c -------- */
2330
2331/*
2332 * execute tree
2333 */
2334
2335
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002336static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002337{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002338 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002339 volatile int i, rv, a;
2340 char *cp, **wp, **wp2;
2341 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002342 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002343 struct brkcon bc;
2344
2345#if __GNUC__
2346 /* Avoid longjmp clobbering */
2347 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002348#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002349
Eric Andersen12de6cf2004-08-04 19:19:10 +00002350 if (t == NULL) {
2351 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002352 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002353 }
2354
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002355 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002356 t->type, T_CMD_NAMES[t->type],
2357 ((t->words == NULL) ? "NULL" : t->words[0])));
2358
Eric Andersenff9eee42001-06-29 04:57:14 +00002359 rv = 0;
2360 a = areanum++;
2361 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002362 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2363 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002364
Eric Andersen8401eea2004-08-04 19:16:54 +00002365 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002366 case TDOT:
2367 DBGPRINTF3(("EXECUTE: TDOT\n"));
2368
2369 outtree_save = outtree;
2370
2371 newfile(evalstr(t->words[0], DOALL));
2372
2373 t->left = dowholefile(TLIST, 0);
2374 t->right = NULL;
2375
2376 outtree = outtree_save;
2377
2378 if (t->left)
2379 rv = execute(t->left, pin, pout, 0);
2380 if (t->right)
2381 rv = execute(t->right, pin, pout, 0);
2382 break;
2383
Eric Andersenff9eee42001-06-29 04:57:14 +00002384 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002385 rv = execute(t->left, pin, pout, 0);
2386 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002387
Eric Andersenff9eee42001-06-29 04:57:14 +00002388 case TCOM:
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002389 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002390 break;
2391
2392 case TPIPE:
2393 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002394 int pv[2];
2395
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002396 rv = openpipe(pv);
2397 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002398 break;
2399 pv[0] = remap(pv[0]);
2400 pv[1] = remap(pv[1]);
2401 (void) execute(t->left, pin, pv, 0);
2402 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002403 }
2404 break;
2405
2406 case TLIST:
2407 (void) execute(t->left, pin, pout, 0);
2408 rv = execute(t->right, pin, pout, 0);
2409 break;
2410
2411 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002412 {
2413 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002414
Eric Andersen12de6cf2004-08-04 19:19:10 +00002415 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2416
Eric Andersen8401eea2004-08-04 19:16:54 +00002417 i = vfork();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002418 if (i == 0) { /* child */
Eric Andersen8401eea2004-08-04 19:16:54 +00002419 signal(SIGINT, SIG_IGN);
2420 signal(SIGQUIT, SIG_IGN);
2421 if (interactive)
2422 signal(SIGTERM, SIG_DFL);
2423 interactive = 0;
2424 if (pin == NULL) {
2425 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002426 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002427 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002428 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002429 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002430 interactive = hinteractive;
2431 if (i != -1) {
2432 setval(lookup("!"), putn(i));
2433 if (pin != NULL)
2434 closepipe(pin);
2435 if (interactive) {
2436 prs(putn(i));
2437 prs("\n");
2438 }
2439 } else
2440 rv = -1;
2441 setstatus(rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002442 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002443 break;
2444
2445 case TOR:
2446 case TAND:
2447 rv = execute(t->left, pin, pout, 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002448 t1 = t->right;
2449 if (t1 != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002450 rv = execute(t1, pin, pout, 0);
2451 break;
2452
2453 case TFOR:
2454 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002455 wp = dolv + 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002456 i = dolc;
2457 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002458 i = 0;
2459 } else {
2460 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002461 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002462 }
2463 vp = lookup(t->str);
2464 while (setjmp(bc.brkpt))
2465 if (isbreak)
2466 goto broken;
2467 brkset(&bc);
2468 for (t1 = t->left; i-- && *wp != NULL;) {
2469 setval(vp, *wp++);
2470 rv = execute(t1, pin, pout, 0);
2471 }
2472 brklist = brklist->nextlev;
2473 break;
2474
2475 case TWHILE:
2476 case TUNTIL:
2477 while (setjmp(bc.brkpt))
2478 if (isbreak)
2479 goto broken;
2480 brkset(&bc);
2481 t1 = t->left;
2482 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2483 rv = execute(t->right, pin, pout, 0);
2484 brklist = brklist->nextlev;
2485 break;
2486
2487 case TIF:
2488 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002489 if (t->right != NULL) {
2490 rv = !execute(t->left, pin, pout, 0) ?
2491 execute(t->right->left, pin, pout, 0) :
2492 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002493 }
2494 break;
2495
2496 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002497 cp = evalstr(t->str, DOSUB | DOTRIM);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002498 if (cp == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002499 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002500
2501 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2502 ((t->str == NULL) ? "NULL" : t->str),
2503 ((cp == NULL) ? "NULL" : cp)));
2504
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002505 t1 = findcase(t->left, cp);
2506 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002507 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002508 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002509 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002510 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002511 break;
2512
2513 case TBRACE:
2514/*
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002515 iopp = t->ioact;
2516 if (i)
Eric Andersenff9eee42001-06-29 04:57:14 +00002517 while (*iopp)
2518 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2519 rv = -1;
2520 break;
2521 }
2522*/
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002523 if (rv >= 0) {
2524 t1 = t->left;
2525 if (t1) {
2526 rv = execute(t1, pin, pout, 0);
2527 }
2528 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002529 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002530
2531 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002532
Eric Andersen8401eea2004-08-04 19:16:54 +00002533 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002534 t->words = wp2;
2535 isbreak = 0;
2536 freehere(areanum);
2537 freearea(areanum);
2538 areanum = a;
2539 if (interactive && intr) {
2540 closeall();
2541 fail();
2542 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002543
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002544 i = trapset;
2545 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002546 trapset = 0;
2547 runtrap(i);
2548 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002549
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002550 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002551 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002552}
2553
2554static int
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002555forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002556{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002557 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002558 int i, rv;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002559 builtin_func_ptr shcom = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002560 int f;
Eric Andersenff9eee42001-06-29 04:57:14 +00002561 char *cp = NULL;
2562 struct ioword **iopp;
2563 int resetsig;
2564 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002565 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002566
2567 int *hpin = pin;
2568 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002569 char *hwp;
2570 int hinteractive;
2571 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002572 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002573 int hexecflg;
2574
2575#if __GNUC__
2576 /* Avoid longjmp clobbering */
2577 (void) &pin;
2578 (void) &pout;
2579 (void) &wp;
2580 (void) &shcom;
2581 (void) &cp;
2582 (void) &resetsig;
2583 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002584#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002585
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002586 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002587 pout, act));
2588 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2589 ((t->words == NULL) ? "NULL" : t->words[0])));
2590
Eric Andersenff9eee42001-06-29 04:57:14 +00002591 owp = wp;
2592 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002593 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002594 if (t->type == TCOM) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002595 while ((cp = *wp++) != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002596 cp = *wp;
2597
2598 /* strip all initial assignments */
2599 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002600 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002601 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002602 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002603 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002604 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002605
Eric Andersenff9eee42001-06-29 04:57:14 +00002606 if (cp == NULL && t->ioact == NULL) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002607 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2608 /**/;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002609 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002610 return setstatus(0);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002611 }
2612 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002613 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002614 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002615 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002616
Eric Andersenff9eee42001-06-29 04:57:14 +00002617 t->words = wp;
2618 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002619
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002620 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002621 f & FEXEC, owp));
2622
2623 if (shcom == NULL && (f & FEXEC) == 0) {
2624 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002625 hpin = pin;
2626 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002627 hwp = *wp;
2628 hinteractive = interactive;
2629 hintr = intr;
2630 hbrklist = brklist;
2631 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002632
Eric Andersen12de6cf2004-08-04 19:19:10 +00002633 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2634
2635 newpid = vfork();
2636
2637 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002638 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002639 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002640 }
2641
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002642 if (newpid > 0) { /* Parent */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002643 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002644 pin = hpin;
2645 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002646 *wp = hwp;
2647 interactive = hinteractive;
2648 intr = hintr;
2649 brklist = hbrklist;
2650 execflg = hexecflg;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002651/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002652 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002653 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002654*/
Eric Andersenff9eee42001-06-29 04:57:14 +00002655 if (pin != NULL)
2656 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002657
2658 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002659 }
2660
Eric Andersen12de6cf2004-08-04 19:19:10 +00002661 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002662 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002663
Eric Andersenff9eee42001-06-29 04:57:14 +00002664 if (interactive) {
2665 signal(SIGINT, SIG_IGN);
2666 signal(SIGQUIT, SIG_IGN);
2667 resetsig = 1;
2668 }
2669 interactive = 0;
2670 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002671 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002672 brklist = 0;
2673 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002674 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002675
Eric Andersenff9eee42001-06-29 04:57:14 +00002676 if (owp != NULL)
2677 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2678 if (shcom == NULL)
2679 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002680
Eric Andersenff9eee42001-06-29 04:57:14 +00002681#ifdef COMPIPE
2682 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2683 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002684 if (forked)
2685 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002686 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002687 }
2688#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002689
Eric Andersenff9eee42001-06-29 04:57:14 +00002690 if (pin != NULL) {
2691 dup2(pin[0], 0);
2692 closepipe(pin);
2693 }
2694 if (pout != NULL) {
2695 dup2(pout[1], 1);
2696 closepipe(pout);
2697 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002698
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002699 iopp = t->ioact;
2700 if (iopp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002701 if (shcom != NULL && shcom != doexec) {
2702 prs(cp);
2703 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002704 if (forked)
2705 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002706 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002707 }
2708 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002709 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2710 if (forked)
2711 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002712 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002713 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002714 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002715
2716 if (shcom) {
2717 i = setstatus((*shcom) (t));
2718 if (forked)
2719 _exit(i);
2720 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002721 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002722 }
2723
Eric Andersenff9eee42001-06-29 04:57:14 +00002724 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002725 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002726 close(i);
2727 if (resetsig) {
2728 signal(SIGINT, SIG_DFL);
2729 signal(SIGQUIT, SIG_DFL);
2730 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002731
Eric Andersen12de6cf2004-08-04 19:19:10 +00002732 if (t->type == TPAREN)
2733 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2734 if (wp[0] == NULL)
2735 _exit(0);
2736
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002737 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002738 prs(wp[0]);
2739 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002740 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002741 if (!execflg)
2742 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002743
2744 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2745
Eric Andersenff9eee42001-06-29 04:57:14 +00002746 leave();
2747 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002748 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002749}
2750
2751/*
2752 * 0< 1> are ignored as required
2753 * within pipelines.
2754 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002755static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002756{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002757 int u = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002758 char *cp = NULL, *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002759
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002760 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002761 pipein, pipeout));
2762
Eric Andersenff9eee42001-06-29 04:57:14 +00002763 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002764 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002765
Eric Andersenff9eee42001-06-29 04:57:14 +00002766 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002767 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002768
Eric Andersenff9eee42001-06-29 04:57:14 +00002769 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002770 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002771
Eric Andersen8401eea2004-08-04 19:16:54 +00002772 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002773 if ((iop->io_flag & IOHERE) == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002774 cp = iop->io_name; /* huh?? */
2775 cp = evalstr(cp, DOSUB | DOTRIM);
2776 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002777 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002778 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002779
Eric Andersenff9eee42001-06-29 04:57:14 +00002780 if (iop->io_flag & IODUP) {
2781 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2782 prs(cp);
2783 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002784 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002785 }
2786 if (*cp == '-')
2787 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002788 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002789 }
2790 switch (iop->io_flag) {
2791 case IOREAD:
2792 u = open(cp, 0);
2793 break;
2794
2795 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002796 case IOHERE | IOXHERE:
2797 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002798 cp = "here file";
2799 break;
2800
Eric Andersen8401eea2004-08-04 19:16:54 +00002801 case IOWRITE | IOCAT:
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002802 u = open(cp, 1);
2803 if (u >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002804 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002805 break;
2806 }
2807 case IOWRITE:
2808 u = creat(cp, 0666);
2809 break;
2810
2811 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002812 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002813 break;
2814
2815 case IOCLOSE:
2816 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002817 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002818 }
2819 if (u < 0) {
2820 prs(cp);
2821 prs(": cannot ");
2822 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002823 return 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002824 }
2825 if (u != iop->io_unit) {
2826 dup2(u, iop->io_unit);
2827 close(u);
Eric Andersenff9eee42001-06-29 04:57:14 +00002828 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002829 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002830}
2831
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002832static void echo(char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002833{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002834 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00002835
2836 prs("+");
Eric Andersen8401eea2004-08-04 19:16:54 +00002837 for (i = 0; wp[i]; i++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002838 if (i)
2839 prs(" ");
2840 prs(wp[i]);
2841 }
2842 prs("\n");
2843}
2844
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002845static struct op **find1case(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00002846{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002847 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002848 struct op **tp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002849 char **wp, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00002850
Eric Andersen12de6cf2004-08-04 19:19:10 +00002851 if (t == NULL) {
2852 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002853 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002854 }
2855
2856 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
2857 T_CMD_NAMES[t->type]));
2858
Eric Andersenff9eee42001-06-29 04:57:14 +00002859 if (t->type == TLIST) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002860 tp = find1case(t->left, w);
2861 if (tp != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002862 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002863 return tp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002864 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002865 t1 = t->right; /* TPAT */
Eric Andersenff9eee42001-06-29 04:57:14 +00002866 } else
2867 t1 = t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002868
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002869 for (wp = t1->words; *wp;) {
2870 cp = evalstr(*wp++, DOSUB);
2871 if (cp && gmatch(w, cp)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002872 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002873 &t1->left));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002874 return &t1->left;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002875 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002876 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002877
2878 DBGPRINTF(("FIND1CASE: returning NULL\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002879 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002880}
2881
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002882static struct op *findcase(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00002883{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002884 struct op **tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00002885
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002886 tp = find1case(t, w);
2887 return tp != NULL ? *tp : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002888}
2889
2890/*
2891 * Enter a new loop level (marked for break/continue).
2892 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002893static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00002894{
2895 bc->nextlev = brklist;
2896 brklist = bc;
2897}
2898
2899/*
2900 * Wait for the last process created.
2901 * Print a message for each process found
2902 * that was killed by a signal.
2903 * Ignore interrupt signals while waiting
2904 * unless `canintr' is true.
2905 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002906static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00002907{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002908 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002909 int s;
2910 int oheedint = heedint;
2911
2912 heedint = 0;
2913 rv = 0;
2914 do {
2915 pid = wait(&s);
2916 if (pid == -1) {
2917 if (errno != EINTR || canintr)
2918 break;
2919 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002920 rv = WAITSIG(s);
2921 if (rv != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002922 if (rv < NSIGNAL) {
2923 if (signame[rv] != NULL) {
2924 if (pid != lastpid) {
2925 prn(pid);
2926 prs(": ");
2927 }
2928 prs(signame[rv]);
2929 }
2930 } else {
2931 if (pid != lastpid) {
2932 prn(pid);
2933 prs(": ");
2934 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002935 prs("Signal ");
2936 prn(rv);
2937 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00002938 }
2939 if (WAITCORE(s))
2940 prs(" - core dumped");
2941 if (rv >= NSIGNAL || signame[rv])
2942 prs("\n");
2943 rv = -1;
2944 } else
2945 rv = WAITVAL(s);
2946 }
2947 } while (pid != lastpid);
2948 heedint = oheedint;
2949 if (intr) {
2950 if (interactive) {
2951 if (canintr)
2952 intr = 0;
2953 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00002954 if (exstat == 0)
2955 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002956 onintr(0);
2957 }
2958 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002959 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002960}
2961
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002962static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00002963{
2964 exstat = s;
2965 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002966 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002967}
2968
2969/*
2970 * PATH-searching interface to execve.
2971 * If getenv("PATH") were kept up-to-date,
2972 * execvp might be used.
2973 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002974static char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002975{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002976 int i;
2977 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00002978 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00002979 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002980
Rob Landleya299efb2006-08-10 21:46:43 +00002981 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
2982 optind = 1;
2983 if (find_applet_by_name(name)) {
2984 /* We have to exec here since we vforked. Running
2985 * run_applet_by_name() won't work and bad things
2986 * will happen. */
2987 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
2988 }
Eric Andersen1c039232001-07-07 00:05:55 +00002989 }
Eric Andersen1c039232001-07-07 00:05:55 +00002990
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002991 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002992
Eric Andersen8401eea2004-08-04 19:16:54 +00002993 sp = any('/', c) ? "" : path->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002994 asis = *sp == '\0';
2995 while (asis || *sp != '\0') {
2996 asis = 0;
2997 tp = e.linep;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002998 for (; *sp != '\0'; tp++) {
2999 *tp = *sp++;
3000 if (*tp == ':') {
3001 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003002 break;
3003 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003004 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003005 if (tp != e.linep)
3006 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003007 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003008
Eric Andersen12de6cf2004-08-04 19:19:10 +00003009 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3010
Eric Andersenff9eee42001-06-29 04:57:14 +00003011 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003012
Eric Andersenff9eee42001-06-29 04:57:14 +00003013 switch (errno) {
3014 case ENOEXEC:
3015 *v = e.linep;
3016 tp = *--v;
3017 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003018 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003019 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003020 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003021
3022 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003023 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003024
3025 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003026 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003027
3028 case EACCES:
3029 eacces++;
3030 break;
3031 }
3032 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003033 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003034}
3035
3036/*
3037 * Run the command produced by generator `f'
3038 * applied to stream `arg'.
3039 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003040static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003041{
3042 struct op *otree;
3043 struct wdblock *swdlist;
3044 struct wdblock *siolist;
3045 jmp_buf ev, rt;
3046 xint *ofail;
3047 int rv;
3048
3049#if __GNUC__
3050 /* Avoid longjmp clobbering */
3051 (void) &rv;
3052#endif
3053
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003054 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003055 areanum, outtree, failpt));
3056
Eric Andersenff9eee42001-06-29 04:57:14 +00003057 areanum++;
3058 swdlist = wdlist;
3059 siolist = iolist;
3060 otree = outtree;
3061 ofail = failpt;
3062 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003063
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003064 errpt = ev;
3065 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003066 wdlist = 0;
3067 iolist = 0;
3068 pushio(argp, f);
3069 e.iobase = e.iop;
3070 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003071 failpt = rt;
3072 if (setjmp(failpt) == 0 && yyparse() == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003073 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3074 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003075 } else {
3076 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003077 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003078
Eric Andersenff9eee42001-06-29 04:57:14 +00003079 wdlist = swdlist;
3080 iolist = siolist;
3081 failpt = ofail;
3082 outtree = otree;
3083 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003084
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003085 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003086}
3087
3088/* -------- do.c -------- */
3089
3090/*
3091 * built-in commands: doX
3092 */
3093
Eric Andersen8401eea2004-08-04 19:16:54 +00003094static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003095{
3096 int col;
3097 const struct builtincmd *x;
3098
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003099 puts("\nBuilt-in commands:\n"
3100 "-------------------");
Eric Andersen1c039232001-07-07 00:05:55 +00003101
Eric Andersen8401eea2004-08-04 19:16:54 +00003102 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003103 if (!x->name)
3104 continue;
3105 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3106 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003107 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003108 col = 0;
3109 }
3110 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00003111#if ENABLE_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003112 {
3113 int i;
3114 const struct BB_applet *applet;
Eric Andersen1c039232001-07-07 00:05:55 +00003115
Eric Andersen8401eea2004-08-04 19:16:54 +00003116 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003117 if (!applet->name)
3118 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003119
Eric Andersen8401eea2004-08-04 19:16:54 +00003120 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003121 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003122 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003123 col = 0;
3124 }
3125 }
3126 }
3127#endif
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003128 puts("\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003129 return EXIT_SUCCESS;
3130}
3131
3132
3133
Eric Andersen8401eea2004-08-04 19:16:54 +00003134static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003135{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003136 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003137}
3138
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003139static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003140{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003141 char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003142
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003143 cp = t->words[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003144 if (cp == NULL) {
3145 cp = homedir->value;
3146 if (cp == NULL)
3147 er = ": no home directory";
3148 } else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003149 er = ": bad directory";
3150 else
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003151 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003152 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003153 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003154 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003155}
3156
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003157static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003158{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003159 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003160
Eric Andersen8401eea2004-08-04 19:16:54 +00003161 n = t->words[1] ? getn(t->words[1]) : 1;
3162 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003163 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003164 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003165 }
3166 dolv[n] = dolv[0];
3167 dolv += n;
3168 dolc -= n;
3169 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003170 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003171}
3172
3173/*
3174 * execute login and newgrp directly
3175 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003176static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003177{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003178 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003179
3180 if (interactive) {
3181 signal(SIGINT, SIG_DFL);
3182 signal(SIGQUIT, SIG_DFL);
3183 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003184 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003185 prs(t->words[0]);
3186 prs(": ");
3187 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003188 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003189}
3190
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003191static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003192{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003193 int i, n;
3194 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003195
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003196 cp = t->words[1];
3197 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003198 i = umask(0);
3199 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003200 for (n = 3 * 4; (n -= 3) >= 0;)
3201 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003202 putc('\n', stderr);
3203 } else {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003204/* huh??? '8','9' are not allowed! */
Eric Andersen8401eea2004-08-04 19:16:54 +00003205 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3206 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003207 umask(n);
3208 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003209 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003210}
3211
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003212static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003213{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003214 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003215 jmp_buf ex;
3216 xint *ofail;
3217
3218 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003219 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003220 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003221 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003222 execflg = 1;
3223 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003224 failpt = ex;
3225 if (setjmp(failpt) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003226 execute(t, NOPIPE, NOPIPE, FEXEC);
3227 failpt = ofail;
3228 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003229 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003230}
3231
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003232static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003233{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003234 int i;
3235 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003236 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003237 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003238
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003239 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 +00003240
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003241 cp = t->words[1];
3242 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003243 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003244 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003245 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003246 DBGPRINTF(("DODOT: cp is %s\n", cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003247
Eric Andersen8401eea2004-08-04 19:16:54 +00003248 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003249
3250 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3251 ((sp == NULL) ? "NULL" : sp),
3252 ((e.linep == NULL) ? "NULL" : e.linep)));
3253
Eric Andersenff9eee42001-06-29 04:57:14 +00003254 while (*sp) {
3255 tp = e.linep;
3256 while (*sp && (*tp = *sp++) != ':')
3257 tp++;
3258 if (tp != e.linep)
3259 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003260
Eric Andersen8401eea2004-08-04 19:16:54 +00003261 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003262
3263 /* Original code */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003264 i = open(e.linep, 0);
3265 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003266 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003267 maltmp = remap(i);
3268 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3269
3270 next(maltmp); /* Basically a PUSHIO */
3271
3272 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3273
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003274 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003275 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003276 } /* while */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003277
Eric Andersenff9eee42001-06-29 04:57:14 +00003278 prs(cp);
3279 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003280
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003281 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003282}
3283
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003284static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003285{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003286 int i;
3287 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003288
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003289 cp = t->words[1];
3290 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003291 i = getn(cp);
3292 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003293 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003294 } else
3295 i = -1;
3296 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003297 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003298}
3299
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003300static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003301{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003302 char *cp, **wp;
3303 int nb = 0;
3304 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003305
3306 if (t->words[1] == NULL) {
3307 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003308 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003309 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003310 for (wp = t->words + 1; *wp; wp++) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003311 for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
3312 nb = read(0, cp, sizeof(*cp));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003313 if (nb != sizeof(*cp))
Eric Andersenff9eee42001-06-29 04:57:14 +00003314 break;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003315 nl = (*cp == '\n');
3316 if (nl || (wp[1] && any(*cp, ifs->value)))
3317 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003318 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003319 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003320 if (nb <= 0)
3321 break;
3322 setval(lookup(*wp), e.linep);
3323 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003324 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003325}
3326
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003327static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003328{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003329 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003330}
3331
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003332static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003333{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003334 int n, i;
3335 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003336
3337 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003338 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003339 if (trap[i]) {
3340 prn(i);
3341 prs(": ");
3342 prs(trap[i]);
3343 prs("\n");
3344 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003345 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003346 }
3347 resetsig = isdigit(*t->words[1]);
3348 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3349 n = getsig(t->words[i]);
3350 freecell(trap[n]);
3351 trap[n] = 0;
3352 if (!resetsig) {
3353 if (*t->words[1] != '\0') {
3354 trap[n] = strsave(t->words[1], 0);
3355 setsig(n, sig);
3356 } else
3357 setsig(n, SIG_IGN);
3358 } else {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003359 if (interactive) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003360 if (n == SIGINT)
3361 setsig(n, onintr);
3362 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003363 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003364 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00003365 setsig(n, SIG_DFL);
3366 }
3367 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003368 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003369}
3370
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003371static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003372{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003373 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003374
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003375 n = getn(s);
3376 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003377 err("trap: bad signal number");
3378 n = 0;
3379 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003380 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003381}
3382
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003383static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003384{
3385 if (n == 0)
3386 return;
3387 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3388 ourtrap[n] = 1;
3389 signal(n, f);
3390 }
3391}
3392
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003393static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003394{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003395 char *s;
3396 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003397
3398 s = as;
3399 m = 1;
3400 if (*s == '-') {
3401 m = -1;
3402 s++;
3403 }
3404 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003405 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003406 if (*s) {
3407 prs(as);
3408 err(": bad number");
3409 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003410 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003411}
3412
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003413static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003414{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003415 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003416}
3417
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003418static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003419{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003420 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003421}
3422
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003423static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003424{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003425 struct brkcon *bc;
3426 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003427
Eric Andersen8401eea2004-08-04 19:16:54 +00003428 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003429 if (nl <= 0)
3430 nl = 999;
3431 do {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003432 bc = brklist;
3433 if (bc == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003434 break;
3435 brklist = bc->nextlev;
3436 } while (--nl);
3437 if (nl) {
3438 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003439 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003440 }
3441 isbreak = val;
3442 longjmp(bc->brkpt, 1);
3443 /* NOTREACHED */
3444}
3445
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003446static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003447{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003448 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003449
3450 execflg = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003451 cp = t->words[1];
3452 if (cp != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003453 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003454
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003455 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003456
Eric Andersenff9eee42001-06-29 04:57:14 +00003457 leave();
3458 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003459 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003460}
3461
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003462static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003463{
Eric Andersen8401eea2004-08-04 19:16:54 +00003464 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003465 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003466}
3467
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003468static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003469{
Eric Andersen8401eea2004-08-04 19:16:54 +00003470 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003471 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003472}
3473
Eric Andersen8401eea2004-08-04 19:16:54 +00003474static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003475{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003476 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003477 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3478
Eric Andersenff9eee42001-06-29 04:57:14 +00003479 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003480 for (; *wp != NULL; wp++) {
3481 if (isassign(*wp)) {
3482 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003483
Matt Kraaif69bfc72001-07-12 19:39:59 +00003484 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003485 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003486 *cp = '\0';
3487 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003488 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003489 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003490 else
3491 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003492 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003493 } else
3494 putvlist(key, 1);
3495}
3496
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003497static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003498{
3499 prs(s);
3500 err(": bad identifier");
3501}
3502
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003503static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003504{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003505 struct var *vp;
3506 char *cp;
3507 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003508
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003509 cp = t->words[1];
3510 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003511 for (vp = vlist; vp; vp = vp->next)
3512 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003513 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003514 }
3515 if (*cp == '-') {
3516 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003517 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003518 if (*++cp == 0)
3519 flag['x'] = flag['v'] = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003520 else {
3521 for (; *cp; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003522 switch (*cp) {
3523 case 'e':
3524 if (!interactive)
3525 flag['e']++;
3526 break;
3527
3528 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003529 if (*cp >= 'a' && *cp <= 'z')
3530 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003531 break;
3532 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003533 }
3534 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003535 setdash();
3536 }
3537 if (t->words[1]) {
3538 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003539 for (n = 1; t->words[n]; n++)
3540 setarea((char *) t->words[n], 0);
3541 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003542 dolv = t->words;
3543 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003544 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003545 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003546 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003547}
3548
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003549static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003550{
Matt Kraai69edfec2001-08-06 14:14:18 +00003551 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003552 write(out, s, strlen(s));
3553 write(out, "\n", 1);
3554 }
3555}
3556
3557
3558/*
3559 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3560 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003561 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003562static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003563{
3564 struct tms buf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003565 long clk_tck = sysconf(_SC_CLK_TCK);
Eric Andersenff9eee42001-06-29 04:57:14 +00003566
3567 times(&buf);
3568 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003569 (int) (buf.tms_utime / clk_tck / 60),
3570 ((double) buf.tms_utime) / clk_tck,
3571 (int) (buf.tms_stime / clk_tck / 60),
3572 ((double) buf.tms_stime) / clk_tck,
3573 (int) (buf.tms_cutime / clk_tck / 60),
3574 ((double) buf.tms_cutime) / clk_tck,
3575 (int) (buf.tms_cstime / clk_tck / 60),
3576 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003577 return 0;
3578}
3579
3580
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003581static builtin_func_ptr inbuilt(char *s) {
Eric Andersen1c039232001-07-07 00:05:55 +00003582 const struct builtincmd *bp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003583
Eric Andersen1c039232001-07-07 00:05:55 +00003584 for (bp = builtincmds; bp->name != NULL; bp++)
3585 if (strcmp(bp->name, s) == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003586 return bp->builtinfunc;
Eric Andersen1c039232001-07-07 00:05:55 +00003587
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003588 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003589}
3590
3591/* -------- eval.c -------- */
3592
3593/*
3594 * ${}
3595 * `command`
3596 * blank interpretation
3597 * quoting
3598 * glob
3599 */
3600
Eric Andersen8401eea2004-08-04 19:16:54 +00003601static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003602{
3603 struct wdblock *wb;
3604 char **wp;
3605 char **wf;
3606 jmp_buf ev;
3607
3608#if __GNUC__
3609 /* Avoid longjmp clobbering */
3610 (void) &wp;
3611 (void) &ap;
3612#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003613
3614 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3615
Eric Andersenff9eee42001-06-29 04:57:14 +00003616 wp = NULL;
3617 wb = NULL;
3618 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003619 errpt = ev;
3620 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003621 while (*ap && isassign(*ap))
3622 expand(*ap++, &wb, f & ~DOGLOB);
3623 if (flag['k']) {
3624 for (wf = ap; *wf; wf++) {
3625 if (isassign(*wf))
3626 expand(*wf, &wb, f & ~DOGLOB);
3627 }
3628 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003629 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003630 if (!flag['k'] || !isassign(*ap))
3631 expand(*ap, &wb, f & ~DOKEY);
3632 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003633 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003634 wp = getwords(wb);
3635 quitenv();
3636 } else
3637 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003638
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003639 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003640}
3641
3642/*
3643 * Make the exported environment from the exported
3644 * names in the dictionary. Keyword assignments
3645 * will already have been done.
3646 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003647static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003648{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003649 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003650
3651 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003652
Eric Andersenff9eee42001-06-29 04:57:14 +00003653 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003654 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003655 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003656 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003657 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003658}
3659
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003660static char *evalstr(char *cp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003661{
3662 struct wdblock *wb;
3663
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003664 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003665
Eric Andersenff9eee42001-06-29 04:57:14 +00003666 wb = NULL;
3667 if (expand(cp, &wb, f)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003668 if (wb == NULL || wb->w_nword == 0
3669 || (cp = wb->w_words[0]) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003670 cp = "";
3671 DELETE(wb);
3672 } else
3673 cp = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003674 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003675}
3676
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003677static int expand(char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003678{
3679 jmp_buf ev;
3680
3681#if __GNUC__
3682 /* Avoid longjmp clobbering */
3683 (void) &cp;
3684#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003685
3686 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3687
Eric Andersenff9eee42001-06-29 04:57:14 +00003688 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003689
Eric Andersenff9eee42001-06-29 04:57:14 +00003690 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003691 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003692
Eric Andersenff9eee42001-06-29 04:57:14 +00003693 if (!anys("$`'\"", cp) &&
Eric Andersen8401eea2004-08-04 19:16:54 +00003694 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003695 cp = strsave(cp, areanum);
3696 if (f & DOTRIM)
3697 unquote(cp);
3698 *wbp = addword(cp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003699 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003700 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003701 errpt = ev;
3702 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003703 PUSHIO(aword, cp, strchar);
3704 e.iobase = e.iop;
3705 while ((cp = blank(f)) && gflg == 0) {
3706 e.linep = cp;
3707 cp = strsave(cp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003708 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003709 if (f & DOTRIM)
3710 unquote(cp);
3711 *wbp = addword(cp, *wbp);
3712 } else
3713 *wbp = glob(cp, *wbp);
3714 }
3715 quitenv();
3716 } else
3717 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003718 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003719}
3720
3721/*
3722 * Blank interpretation and quoting
3723 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003724static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003725{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003726 int c, c1;
3727 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003728 int scanequals, foundequals;
3729
Eric Andersen12de6cf2004-08-04 19:19:10 +00003730 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3731
Eric Andersenff9eee42001-06-29 04:57:14 +00003732 sp = e.linep;
3733 scanequals = f & DOKEY;
3734 foundequals = 0;
3735
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003736 loop:
3737 c = subgetc('"', foundequals);
3738 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003739 case 0:
3740 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003741 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003742 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003743 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003744
3745 default:
3746 if (f & DOBLANK && any(c, ifs->value))
3747 goto loop;
3748 break;
3749
3750 case '"':
3751 case '\'':
3752 scanequals = 0;
3753 if (INSUB())
3754 break;
3755 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3756 if (c == 0)
3757 break;
3758 if (c == '\'' || !any(c, "$`\""))
3759 c |= QUOTE;
3760 *e.linep++ = c;
3761 }
3762 c = 0;
3763 }
3764 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003765 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003766 scanequals = 0;
3767 for (;;) {
3768 c = subgetc('"', foundequals);
3769 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003770 f & (DOBLANK && any(c, ifs->value)) ||
3771 (!INSUB() && any(c, "\"'"))) {
3772 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003773 unget(c);
3774 if (any(c, "\"'"))
3775 goto loop;
3776 break;
3777 }
3778 if (scanequals) {
3779 if (c == '=') {
3780 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003781 scanequals = 0;
3782 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003783 scanequals = 0;
3784 }
3785 *e.linep++ = c;
3786 }
3787 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003788 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003789}
3790
3791/*
3792 * Get characters, substituting for ` and $
3793 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003794static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003795{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003796 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003797
3798 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003799
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003800 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003801 c = my_getc(ec);
3802 if (!INSUB() && ec != '\'') {
3803 if (c == '`') {
3804 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003805 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003806 e.iop->task = XGRAVE;
3807 goto again;
3808 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003809 if (c == '$') {
3810 c = dollar(quoted);
3811 if (c == 0) {
3812 e.iop->task = XDOLL;
3813 goto again;
3814 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003815 }
3816 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003817 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003818}
3819
3820/*
3821 * Prepare to generate the string returned by ${} substitution.
3822 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003823static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003824{
3825 int otask;
3826 struct io *oiop;
3827 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003828 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003829 struct var *vp;
3830
Eric Andersen12de6cf2004-08-04 19:19:10 +00003831 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3832
Eric Andersenff9eee42001-06-29 04:57:14 +00003833 c = readc();
3834 s = e.linep;
3835 if (c != '{') {
3836 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003837 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003838 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003839 if (e.linep < elinep)
3840 *e.linep++ = c;
3841 unget(c);
3842 }
3843 c = 0;
3844 } else {
3845 oiop = e.iop;
3846 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003847
Eric Andersenff9eee42001-06-29 04:57:14 +00003848 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003849 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003850 if (e.linep < elinep)
3851 *e.linep++ = c;
3852 if (oiop == e.iop)
3853 e.iop->task = otask;
3854 if (c != '}') {
3855 err("unclosed ${");
3856 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003857 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003858 }
3859 }
3860 if (e.linep >= elinep) {
3861 err("string in ${} too long");
3862 gflg++;
3863 e.linep -= 10;
3864 }
3865 *e.linep = 0;
3866 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003867 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003868 if (any(*cp, "=-+?")) {
3869 c = *cp;
3870 *cp++ = 0;
3871 break;
3872 }
3873 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3874 if (dolc > 1) {
3875 /* currently this does not distinguish $* and $@ */
3876 /* should check dollar */
3877 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00003878 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003879 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003880 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00003881 s[0] = '1';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003882 s[1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003883 }
3884 }
3885 vp = lookup(s);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003886 dolp = vp->value;
3887 if (dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003888 switch (c) {
3889 case '=':
3890 if (isdigit(*s)) {
3891 err("cannot use ${...=...} with $n");
3892 gflg++;
3893 break;
3894 }
3895 setval(vp, cp);
3896 dolp = vp->value;
3897 break;
3898
3899 case '-':
3900 dolp = strsave(cp, areanum);
3901 break;
3902
3903 case '?':
3904 if (*cp == 0) {
3905 prs("missing value for ");
3906 err(s);
3907 } else
3908 err(cp);
3909 gflg++;
3910 break;
3911 }
3912 } else if (c == '+')
3913 dolp = strsave(cp, areanum);
3914 if (flag['u'] && dolp == null) {
3915 prs("unset variable: ");
3916 err(s);
3917 gflg++;
3918 }
3919 e.linep = s;
3920 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003921 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003922}
3923
3924/*
3925 * Run the command in `...` and read its output.
3926 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00003927
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003928static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003929{
Eric Andersenff9eee42001-06-29 04:57:14 +00003930 char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003931 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00003932 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00003933 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00003934 static char child_cmd[LINELIM];
3935 char *src;
3936 char *dest;
3937 int count;
3938 int ignore;
3939 int ignore_once;
3940 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003941 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003942
3943#if __GNUC__
3944 /* Avoid longjmp clobbering */
3945 (void) &cp;
3946#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003947
Eric Andersenff9eee42001-06-29 04:57:14 +00003948 for (cp = e.iop->argp->aword; *cp != '`'; cp++)
3949 if (*cp == 0) {
3950 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003951 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003952 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00003953
3954 /* string copy with dollar expansion */
3955 src = e.iop->argp->aword;
3956 dest = child_cmd;
3957 count = 0;
3958 ignore = 0;
3959 ignore_once = 0;
3960 while ((*src != '`') && (count < LINELIM)) {
3961 if (*src == '\'')
3962 ignore = !ignore;
3963 if (*src == '\\')
3964 ignore_once = 1;
3965 if (*src == '$' && !ignore && !ignore_once) {
3966 struct var *vp;
3967 char var_name[LINELIM];
3968 char alt_value[LINELIM];
3969 int var_index = 0;
3970 int alt_index = 0;
3971 char operator = 0;
3972 int braces = 0;
3973 char *value;
3974
3975 src++;
3976 if (*src == '{') {
3977 braces = 1;
3978 src++;
3979 }
3980
3981 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00003982 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00003983 var_name[var_index++] = *src++;
3984 var_name[var_index] = 0;
3985
3986 if (braces) {
3987 switch (*src) {
3988 case '}':
3989 break;
3990 case '-':
3991 case '=':
3992 case '+':
3993 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00003994 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00003995 break;
3996 default:
3997 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003998 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00003999 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004000 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004001 src++;
4002 while (*src && (*src != '}')) {
4003 alt_value[alt_index++] = *src++;
4004 }
4005 alt_value[alt_index] = 0;
4006 if (*src != '}') {
4007 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004008 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004009 }
4010 }
4011 src++;
4012 }
4013
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004014 if (isalpha(*var_name)) {
4015 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004016
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004017 char *namep = var_name;
4018
4019 *dest++ = '$';
4020 if (braces)
4021 *dest++ = '{';
4022 while (*namep)
4023 *dest++ = *namep++;
4024 if (operator) {
4025 char *altp = alt_value;
4026 *dest++ = operator;
4027 while (*altp)
4028 *dest++ = *altp++;
4029 }
4030 if (braces)
4031 *dest++ = '}';
4032
4033 wb = addword(lookup(var_name)->name, wb);
4034 } else {
4035 /* expand */
4036
4037 vp = lookup(var_name);
4038 if (vp->value != null)
4039 value = (operator == '+') ?
4040 alt_value : vp->value;
4041 else if (operator == '?') {
4042 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004043 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004044 } else if (alt_index && (operator != '+')) {
4045 value = alt_value;
4046 if (operator == '=')
4047 setval(vp, value);
4048 } else
4049 continue;
4050
4051 while (*value && (count < LINELIM)) {
4052 *dest++ = *value++;
4053 count++;
4054 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004055 }
4056 } else {
4057 *dest++ = *src++;
4058 count++;
4059 ignore_once = 0;
4060 }
4061 }
4062 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004063
Eric Andersenff9eee42001-06-29 04:57:14 +00004064 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004065 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004066
Eric Andersen8401eea2004-08-04 19:16:54 +00004067 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004068
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004069 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004070
Eric Andersen737f5fb2003-03-14 16:05:59 +00004071 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004072 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004073 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004074 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004075 }
4076 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004077 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004078 e.iop->argp->aword = ++cp;
4079 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004080 PUSHIO(afile, remap(pf[0]),
4081 (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
4082 gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004083 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004084 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004085 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004086 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004087 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004088 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4089 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004090
Eric Andersenff9eee42001-06-29 04:57:14 +00004091 dup2(pf[1], 1);
4092 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004093
Eric Andersen8401eea2004-08-04 19:16:54 +00004094 argument_list[0] = (char *) DEFAULT_SHELL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004095 argument_list[1] = "-c";
4096 argument_list[2] = child_cmd;
4097 argument_list[3] = 0;
4098
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004099 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004100 prs(argument_list[0]);
4101 prs(": ");
4102 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004103 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004104}
4105
Eric Andersen737f5fb2003-03-14 16:05:59 +00004106
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004107static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004108{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004109 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004110
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004111 s = as;
4112 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004113 while (*s)
4114 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004115 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004116}
4117
4118/* -------- glob.c -------- */
4119
4120/*
4121 * glob
4122 */
4123
4124#define scopy(x) strsave((x), areanum)
4125#define BLKSIZ 512
4126#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4127
Eric Andersen8401eea2004-08-04 19:16:54 +00004128static struct wdblock *cl, *nl;
4129static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004130
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004131static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004132{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004133 int i;
4134 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004135
4136 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004137 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004138 i = 0;
4139 for (pp = cp; *pp; pp++)
4140 if (any(*pp, spcl))
4141 i++;
4142 else if (!any(*pp & ~QUOTE, spcl))
4143 *pp &= ~QUOTE;
4144 if (i != 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004145 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004146 nl = newword(cl->w_nword * 2);
4147 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004148 for (pp = cl->w_words[i]; *pp; pp++)
4149 if (any(*pp, spcl)) {
4150 globname(cl->w_words[i], pp);
4151 break;
4152 }
4153 if (*pp == '\0')
4154 nl = addword(scopy(cl->w_words[i]), nl);
4155 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004156 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004157 DELETE(cl->w_words[i]);
4158 DELETE(cl);
4159 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004160 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004161 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004162 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004163 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004164 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004165 wb = addword(cl->w_words[i], wb);
4166 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004167 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004168 }
4169 }
4170 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004171 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004172}
4173
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004174static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004175{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004176 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004177 char *name, *gp, *dp;
4178 int k;
4179 DIR *dirp;
4180 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004181 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004182 struct stat dbuf;
4183
4184 for (np = we; np != pp; pp--)
4185 if (pp[-1] == '/')
4186 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004187 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004188 *cp++ = *np++;
4189 *cp++ = '.';
4190 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004191 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004192 *cp++ = *np++;
4193 *cp = '\0';
4194 dirp = opendir(dp);
4195 if (dirp == 0) {
4196 DELETE(dp);
4197 DELETE(gp);
4198 return;
4199 }
4200 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004201 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004202 /* XXX Hmmm... What this could be? (abial) */
4203 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004204 if (ent[j].d_ino == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004205 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004206 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004207 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004208 if (dname[0] == '.')
4209 if (*gp != '.')
4210 continue;
4211 for (k = 0; k < NAME_MAX; k++)
4212 if (any(dname[k], spcl))
4213 dname[k] |= QUOTE;
4214 if (gmatch(dname, gp)) {
4215 name = generate(we, pp, dname, np);
4216 if (*np && !anys(np, spcl)) {
4217 if (stat(name, &dbuf)) {
4218 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004219 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004220 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004221 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004222 nl = addword(name, nl);
4223 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004224 }
4225 closedir(dirp);
4226 DELETE(dp);
4227 DELETE(gp);
4228}
4229
4230/*
4231 * generate a pathname as below.
4232 * start..end1 / middle end
4233 * the slashes come for free
4234 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004235static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004236{
4237 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004238 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004239
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004240 p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004241 for (xp = start1; xp != end1;)
4242 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004243 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004244 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004245 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004246 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004247}
4248
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004249static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004250{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004251 int i;
4252 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004253
4254 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004255 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004256 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004257 return 1;
4258 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004259}
4260
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004261static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004262{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004263 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004264}
4265
4266/* -------- word.c -------- */
4267
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004268static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004269{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004270 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004271
Eric Andersen8401eea2004-08-04 19:16:54 +00004272 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004273 wb->w_bsize = nw;
4274 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004275 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004276}
4277
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004278static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004279{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004280 struct wdblock *wb2;
4281 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004282
4283 if (wb == NULL)
4284 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004285 nw = wb->w_nword;
4286 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004287 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004288 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4289 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004290 wb2->w_nword = nw;
4291 DELETE(wb);
4292 wb = wb2;
4293 }
4294 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004295 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004296}
Eric Andersen8401eea2004-08-04 19:16:54 +00004297
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004298static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004299char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004300{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004301 char **wd;
4302 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004303
4304 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004305 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004306 if (wb->w_nword == 0) {
4307 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004308 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004309 }
4310 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004311 memcpy((char *) wd, (char *) wb->w_words, nb);
4312 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004313 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004314}
4315
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004316static int (*func) (char *, char *);
4317static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004318
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004319static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004320{
4321 func = a3;
4322 globv = a2;
4323 glob1(a0, a0 + a1 * a2);
4324}
4325
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004326static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004327{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004328 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004329 int v2;
4330 char *lptr, *hptr;
4331 int c;
4332 unsigned n;
4333
Eric Andersenff9eee42001-06-29 04:57:14 +00004334 v2 = globv;
4335
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004336 top:
4337 n = (int) (lim - base);
4338 if (n <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004339 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004340 n = v2 * (n / (2 * v2));
4341 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004342 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004343 j = lim - v2;
4344 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004345 if (i < lptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004346 c = (*func) (i, lptr);
4347 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004348 lptr -= v2;
4349 glob2(i, lptr);
Eric Andersenff9eee42001-06-29 04:57:14 +00004350 continue;
4351 }
4352 if (c < 0) {
4353 i += v2;
4354 continue;
4355 }
4356 }
4357
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004358 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004359 if (j > hptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004360 c = (*func) (hptr, j);
4361 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004362 hptr += v2;
4363 glob2(hptr, j);
Eric Andersenff9eee42001-06-29 04:57:14 +00004364 goto begin;
4365 }
4366 if (c > 0) {
4367 if (i == lptr) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004368 hptr += v2;
4369 glob3(i, hptr, j);
4370 i = (lptr += v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004371 goto begin;
4372 }
4373 glob2(i, j);
4374 j -= v2;
4375 i += v2;
4376 continue;
4377 }
4378 j -= v2;
4379 goto begin;
4380 }
4381
4382
4383 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004384 if (lptr - base >= lim - hptr) {
4385 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004386 lim = lptr;
4387 } else {
4388 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004389 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004390 }
4391 goto top;
4392 }
4393
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004394 lptr -= v2;
4395 glob3(j, lptr, i);
4396 j = (hptr -= v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004397 }
4398}
4399
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004400static void glob2(char *i, char *j)
Eric Andersenff9eee42001-06-29 04:57:14 +00004401{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004402 char *index1, *index2, c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004403 int m;
4404
4405 m = globv;
4406 index1 = i;
4407 index2 = j;
4408 do {
4409 c = *index1;
4410 *index1++ = *index2;
4411 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004412 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004413}
4414
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004415static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004416{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004417 char *index1, *index2, *index3;
Eric Andersenff9eee42001-06-29 04:57:14 +00004418 int c;
4419 int m;
4420
4421 m = globv;
4422 index1 = i;
4423 index2 = j;
4424 index3 = k;
4425 do {
4426 c = *index1;
4427 *index1++ = *index3;
4428 *index3++ = *index2;
4429 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004430 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004431}
4432
4433/* -------- io.c -------- */
4434
4435/*
4436 * shell IO
4437 */
4438
Eric Andersen8401eea2004-08-04 19:16:54 +00004439static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004440{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004441 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004442
Eric Andersen8401eea2004-08-04 19:16:54 +00004443 if (e.linep > elinep) {
4444 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004445 err("input line too long");
4446 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004447 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004448 }
4449 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004450 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004451 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004452 c = readc();
4453 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004454 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004455 c |= QUOTE;
4456 }
4457 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004458 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004459}
4460
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004461static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004462{
4463 if (e.iop >= e.iobase)
4464 e.iop->peekc = c;
4465}
4466
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004467static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004468{
Eric Andersen8401eea2004-08-04 19:16:54 +00004469 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004470}
4471
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004472static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004473{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004474 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004475
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004476 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004477
4478 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004479 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004480 c = e.iop->peekc;
4481 if (c != '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004482 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004483 return c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004484 }
4485 if (e.iop->prev != 0) {
4486 c = (*e.iop->iofn)(e.iop->argp, e.iop);
4487 if (c != '\0') {
4488 if (c == -1) {
4489 e.iop++;
4490 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004491 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004492 if (e.iop == iostack)
4493 ioecho(c);
4494 e.iop->prev = c;
4495 return e.iop->prev;
Eric Andersenff9eee42001-06-29 04:57:14 +00004496 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004497 if (e.iop->task == XIO && e.iop->prev != '\n') {
4498 e.iop->prev = 0;
4499 if (e.iop == iostack)
4500 ioecho('\n');
4501 return '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004502 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004503 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004504 if (e.iop->task == XIO) {
4505 if (multiline) {
4506 e.iop->prev = 0;
4507 return e.iop->prev;
4508 }
4509 if (interactive && e.iop == iostack + 1) {
4510#if ENABLE_FEATURE_EDITING
4511 current_prompt = prompt->value;
4512#else
4513 prs(prompt->value);
4514#endif
4515 }
4516 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004517 } /* FOR */
4518
4519 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004520 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004521 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004522 }
4523
4524 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004525 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004526
Eric Andersenff9eee42001-06-29 04:57:14 +00004527 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004528 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004529}
4530
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004531static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004532{
4533 if (flag['v'])
4534 write(2, &c, sizeof c);
4535}
4536
Eric Andersen12de6cf2004-08-04 19:19:10 +00004537
Eric Andersen8401eea2004-08-04 19:16:54 +00004538static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004539{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004540 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004541 argp->afid, e.iop));
4542
4543 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004544 if (++e.iop >= &iostack[NPUSH]) {
4545 e.iop--;
4546 err("Shell input nested too deeply");
4547 gflg++;
4548 return;
4549 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004550
4551 /* We did not overflow the NPUSH array spots so setup data structs */
4552
4553 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004554
4555 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004556 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004557 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004558
4559 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4560 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4561
4562 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4563
4564 if (e.iop == &iostack[0])
4565 e.iop->argp->afbuf = &mainbuf;
4566 else
4567 e.iop->argp->afbuf = &sharedbuf;
4568
4569 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4570 /* This line appears to be active when running scripts from command line */
4571 if ((isatty(e.iop->argp->afile) == 0)
4572 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004573 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004574 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4575 bufid = AFID_ID; /* AFID_ID = 0 */
4576
4577 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004578 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004579
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004580 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004581 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004582 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004583 &mainbuf, &sharedbuf, bufid, e.iop));
4584
Eric Andersenff9eee42001-06-29 04:57:14 +00004585 }
4586
Eric Andersen8401eea2004-08-04 19:16:54 +00004587 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004588 e.iop->peekc = 0;
4589 e.iop->xchar = 0;
4590 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004591
Eric Andersenff9eee42001-06-29 04:57:14 +00004592 if (fn == filechar || fn == linechar)
4593 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004594 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004595 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004596 e.iop->task = XGRAVE;
4597 else
4598 e.iop->task = XOTHER;
4599}
4600
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004601static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004602{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004603 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004604
4605 xp = e.iobase;
4606 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004607 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004608}
4609
4610/*
4611 * Input generating functions
4612 */
4613
4614/*
4615 * Produce the characters of a string, then a newline, then EOF.
4616 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004617static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004618{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004619 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004620
4621 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004622 return 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004623 c = *ap->aword++;
4624 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004625 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004626 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004627 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004628 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004629}
4630
4631/*
4632 * Given a list of words, produce the characters
4633 * in them, with a space after each word.
4634 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004635static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004636{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004637 char c;
4638 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004639
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004640 wl = ap->awordlist;
4641 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004642 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004643 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004644 c = *(*wl)++;
4645 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004646 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004647 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004648 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004649 }
4650 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004651 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004652}
4653
4654/*
4655 * Return the characters of a list of words,
4656 * producing a space between them.
4657 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004658static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004659{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004660 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004661
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004662 wp = *ap->awordlist++;
4663 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004664 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004665 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004666 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004667 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004668}
4669
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004670static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004671{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004672 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004673
4674 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004675 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004676 c = *ap->aword++;
4677 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004678 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004679 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004680 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004681 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004682}
4683
4684/*
4685 * Produce the characters from a single word (string).
4686 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004687static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004688{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004689 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004690 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004691 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004692}
4693
4694/*
4695 * Produce quoted characters from a single word (string).
4696 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004697static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004698{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004699 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004700
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004701 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004702 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004703 c = *ap->aword++;
4704 if (c)
4705 c |= QUOTE;
4706 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004707}
4708
4709/*
4710 * Return the characters from a file.
4711 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004712static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004713{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004714 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004715 char c;
4716 struct iobuf *bp = ap->afbuf;
4717
4718 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004719 i = (ap->afid != bp->id);
4720 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004721 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004722 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004723
Eric Andersen8401eea2004-08-04 19:16:54 +00004724 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4725 if (i <= 0) {
4726 closef(ap->afile);
4727 return 0;
4728 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004729
Eric Andersen8401eea2004-08-04 19:16:54 +00004730 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004731 bp->bufp = bp->buf;
4732 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004733 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004734
Eric Andersen8401eea2004-08-04 19:16:54 +00004735 ap->afpos++;
4736 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004737 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00004738#if ENABLE_FEATURE_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004739 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004740 static char mycommand[BUFSIZ];
4741 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004742
Eric Andersen8401eea2004-08-04 19:16:54 +00004743 while (size == 0 || position >= size) {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00004744 read_line_input(current_prompt, mycommand, BUFSIZ, line_input_state);
Eric Andersen8401eea2004-08-04 19:16:54 +00004745 size = strlen(mycommand);
4746 position = 0;
4747 }
4748 c = mycommand[position];
4749 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004750 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004751 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004752#endif
4753 i = safe_read(ap->afile, &c, sizeof(c));
4754 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004755}
4756
4757/*
4758 * Return the characters from a here temp file.
4759 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004760static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004761{
4762 char c;
4763
Eric Andersenff9eee42001-06-29 04:57:14 +00004764 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4765 close(ap->afile);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004766 c = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00004767 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004768 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004769}
4770
4771/*
4772 * Return the characters produced by a process (`...`).
4773 * Quote them if required, and remove any trailing newline characters.
4774 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004775static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004776{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004777 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004778
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004779 c = qgravechar(ap, iop) & ~QUOTE;
4780 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004781 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004782 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004783}
4784
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004785static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004786{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004787 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004788
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004789 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004790
4791 if (iop->xchar) {
4792 if (iop->nlcount) {
4793 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004794 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004795 }
4796 c = iop->xchar;
4797 iop->xchar = 0;
4798 } else if ((c = filechar(ap)) == '\n') {
4799 iop->nlcount = 1;
4800 while ((c = filechar(ap)) == '\n')
4801 iop->nlcount++;
4802 iop->xchar = c;
4803 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004804 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004805 iop->nlcount--;
4806 c = '\n';
4807 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004808 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004809}
4810
4811/*
4812 * Return a single command (usually the first line) from a file.
4813 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004814static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004815{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004816 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004817
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004818 c = filechar(ap);
4819 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004820 if (!multiline) {
4821 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004822 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004823 }
4824 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004825 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004826}
4827
Eric Andersenff9eee42001-06-29 04:57:14 +00004828/*
4829 * remap fd into Shell's fd space
4830 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004831static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004832{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004833 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004834 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004835 int newfd;
4836
Eric Andersen12de6cf2004-08-04 19:19:10 +00004837 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004838
4839 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004840 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004841 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004842
Eric Andersenff9eee42001-06-29 04:57:14 +00004843 do {
4844 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004845 newfd = dup(fd);
4846 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004847 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004848
Eric Andersen8401eea2004-08-04 19:16:54 +00004849 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004850 if (map[i])
4851 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004852
Eric Andersenff9eee42001-06-29 04:57:14 +00004853 if (fd < 0)
4854 err("too many files open in shell");
4855 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004856
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004857 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004858}
4859
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004860static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004861{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004862 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004863
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004864 i = pipe(pv);
4865 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004866 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004867 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004868}
4869
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004870static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004871{
4872 if (pv != NULL) {
4873 close(*pv++);
4874 close(*pv);
4875 }
4876}
4877
4878/* -------- here.c -------- */
4879
4880/*
4881 * here documents
4882 */
4883
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004884static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004885{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004886 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004887
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004888 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00004889
4890 h = (struct here *) space(sizeof(struct here));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004891 if (h == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004892 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004893
Eric Andersenff9eee42001-06-29 04:57:14 +00004894 h->h_tag = evalstr(s, DOSUB);
4895 if (h->h_tag == 0)
4896 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004897
Eric Andersenff9eee42001-06-29 04:57:14 +00004898 h->h_iop = iop;
4899 iop->io_name = 0;
4900 h->h_next = NULL;
4901 if (inhere == 0)
4902 inhere = h;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004903 else {
4904 for (lh = inhere; lh != NULL; lh = lh->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004905 if (lh->h_next == 0) {
4906 lh->h_next = h;
4907 break;
4908 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004909 }
4910 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004911 iop->io_flag |= IOHERE | IOXHERE;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004912 for (s = h->h_tag; *s; s++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004913 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004914 iop->io_flag &= ~IOXHERE;
4915 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004916 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004917 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004918 h->h_dosub = iop->io_flag & IOXHERE;
4919}
4920
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004921static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004922{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004923 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004924
4925 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004926
4927 /* Scan here files first leaving inhere list in place */
4928 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00004929 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00004930
4931 /* Make inhere list active - keep list intact for scraphere */
4932 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004933 hp->h_next = acthere;
4934 acthere = inhere;
4935 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004936 }
4937}
4938
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004939static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004940{
4941 int tf;
4942 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004943 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004944 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00004945 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004946 char *thenext;
4947
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004948 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004949
Eric Andersenff9eee42001-06-29 04:57:14 +00004950 tf = mkstemp(tname);
4951 if (tf < 0)
4952 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004953
Eric Andersenff9eee42001-06-29 04:57:14 +00004954 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004955 errpt = ev;
4956 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004957 unlink(tname);
4958 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00004959 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00004960 e.iobase = e.iop;
4961 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004962 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00004963#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00004964 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00004965#else
Eric Andersen8401eea2004-08-04 19:16:54 +00004966 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00004967#endif
4968 }
4969 thenext = myline;
4970 while ((c = my_getc(ec)) != '\n' && c) {
4971 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00004972 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004973 if (thenext >= &myline[LINELIM]) {
4974 c = 0;
4975 break;
4976 }
4977 *thenext++ = c;
4978 }
4979 *thenext = 0;
4980 if (strcmp(s, myline) == 0 || c == 0)
4981 break;
4982 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004983 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00004984 }
4985 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004986 prs("here document `");
4987 prs(s);
4988 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00004989 }
4990 quitenv();
4991 }
4992 close(tf);
4993}
4994
4995/*
4996 * open here temp file.
4997 * if unquoted here, expand here temp file into second temp file.
4998 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004999static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005000{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005001 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005002 int tf;
5003
5004#if __GNUC__
5005 /* Avoid longjmp clobbering */
5006 (void) &tf;
5007#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005008 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005009 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005010
5011 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5012
Eric Andersenff9eee42001-06-29 04:57:14 +00005013 hf = open(hname, 0);
5014 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005015 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005016
Eric Andersenff9eee42001-06-29 04:57:14 +00005017 if (xdoll) {
5018 char c;
5019 char tname[30] = ".msh_XXXXXX";
5020 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005021
Eric Andersenff9eee42001-06-29 04:57:14 +00005022 tf = mkstemp(tname);
5023 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005024 return -1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005025 errpt = ev;
5026 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005027 PUSHIO(afile, hf, herechar);
5028 setbase(e.iop);
5029 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005030 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005031 write(tf, &c, sizeof c);
5032 }
5033 quitenv();
5034 } else
5035 unlink(tname);
5036 close(tf);
5037 tf = open(tname, 0);
5038 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005039 return tf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005040 }
5041 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005042}
5043
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005044static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005045{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005046 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005047
5048 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005049
5050 for (h = inhere; h != NULL; h = h->h_next) {
5051 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005052 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005053 }
5054 inhere = NULL;
5055}
5056
5057/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005058static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005059{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005060 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005061
5062 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005063
5064 hl = NULL;
5065 for (h = acthere; h != NULL; h = h->h_next)
5066 if (getarea((char *) h) >= area) {
5067 if (h->h_iop->io_name != NULL)
5068 unlink(h->h_iop->io_name);
5069 if (hl == NULL)
5070 acthere = h->h_next;
5071 else
5072 hl->h_next = h->h_next;
5073 } else
5074 hl = h;
5075}
5076
5077
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005078/* -------- sh.c -------- */
5079/*
5080 * shell
5081 */
5082
5083int msh_main(int argc, char **argv)
5084{
5085 int f;
5086 char *s;
5087 int cflag;
5088 char *name, **ap;
5089 int (*iof) (struct ioarg *);
5090
5091#if ENABLE_FEATURE_EDITING
5092 line_input_state = new_line_input_t(FOR_SHELL);
5093#endif
5094
5095 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
5096
5097 initarea();
5098 ap = environ;
5099 if (ap != NULL) {
5100 while (*ap)
5101 assign(*ap++, !COPYV);
5102 for (ap = environ; *ap;)
5103 export(lookup(*ap++));
5104 }
5105 closeall();
5106 areanum = 1;
5107
5108 shell = lookup("SHELL");
5109 if (shell->value == null)
5110 setval(shell, (char *)DEFAULT_SHELL);
5111 export(shell);
5112
5113 homedir = lookup("HOME");
5114 if (homedir->value == null)
5115 setval(homedir, "/");
5116 export(homedir);
5117
5118 setval(lookup("$"), putn(getpid()));
5119
5120 path = lookup("PATH");
5121 if (path->value == null) {
5122 if (geteuid() == 0)
5123 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
5124 else
5125 setval(path, "/bin:/usr/bin");
5126 }
5127 export(path);
5128
5129 ifs = lookup("IFS");
5130 if (ifs->value == null)
5131 setval(ifs, " \t\n");
5132
5133#ifdef MSHDEBUG
5134 mshdbg_var = lookup("MSHDEBUG");
5135 if (mshdbg_var->value == null)
5136 setval(mshdbg_var, "0");
5137#endif
5138
5139 prompt = lookup("PS1");
5140#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5141 if (prompt->value == null)
5142#endif
5143 setval(prompt, DEFAULT_USER_PROMPT);
5144 if (geteuid() == 0) {
5145 setval(prompt, DEFAULT_ROOT_PROMPT);
5146 prompt->status &= ~EXPORT;
5147 }
5148 cprompt = lookup("PS2");
5149#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5150 if (cprompt->value == null)
5151#endif
5152 setval(cprompt, "> ");
5153
5154 iof = filechar;
5155 cflag = 0;
5156 name = *argv++;
5157 if (--argc >= 1) {
5158 if (argv[0][0] == '-' && argv[0][1] != '\0') {
5159 for (s = argv[0] + 1; *s; s++)
5160 switch (*s) {
5161 case 'c':
5162 prompt->status &= ~EXPORT;
5163 cprompt->status &= ~EXPORT;
5164 setval(prompt, "");
5165 setval(cprompt, "");
5166 cflag = 1;
5167 if (--argc > 0)
5168 PUSHIO(aword, *++argv, iof = nlchar);
5169 break;
5170
5171 case 'q':
5172 qflag = SIG_DFL;
5173 break;
5174
5175 case 's':
5176 /* standard input */
5177 break;
5178
5179 case 't':
5180 prompt->status &= ~EXPORT;
5181 setval(prompt, "");
5182 iof = linechar;
5183 break;
5184
5185 case 'i':
5186 interactive++;
5187 default:
5188 if (*s >= 'a' && *s <= 'z')
5189 flag[(int) *s]++;
5190 }
5191 } else {
5192 argv--;
5193 argc++;
5194 }
5195
5196 if (iof == filechar && --argc > 0) {
5197 setval(prompt, "");
5198 setval(cprompt, "");
5199 prompt->status &= ~EXPORT;
5200 cprompt->status &= ~EXPORT;
5201
5202/* Shell is non-interactive, activate printf-based debug */
5203#ifdef MSHDEBUG
5204 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
5205 if (mshdbg < 0)
5206 mshdbg = 0;
5207#endif
5208 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
5209
5210 name = *++argv;
5211 if (newfile(name))
5212 exit(1); /* Exit on error */
5213 }
5214 }
5215
5216 setdash();
5217
5218 /* This won't be true if PUSHIO has been called, say from newfile() above */
5219 if (e.iop < iostack) {
5220 PUSHIO(afile, 0, iof);
5221 if (isatty(0) && isatty(1) && !cflag) {
5222 interactive++;
5223#if !ENABLE_FEATURE_SH_EXTRA_QUIET
5224#ifdef MSHDEBUG
5225 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
5226#else
5227 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
5228#endif
5229 printf("Enter 'help' for a list of built-in commands.\n\n");
5230#endif
5231 }
5232 }
5233
5234 signal(SIGQUIT, qflag);
5235 if (name && name[0] == '-') {
5236 interactive++;
5237 f = open(".profile", 0);
5238 if (f >= 0)
5239 next(remap(f));
5240 f = open("/etc/profile", 0);
5241 if (f >= 0)
5242 next(remap(f));
5243 }
5244 if (interactive)
5245 signal(SIGTERM, sig);
5246
5247 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
5248 signal(SIGINT, onintr);
5249 dolv = argv;
5250 dolc = argc;
5251 dolv[0] = name;
5252 if (dolc > 1) {
5253 for (ap = ++argv; --argc > 0;) {
5254 *ap = *argv++;
5255 if (assign(*ap, !COPYV)) {
5256 dolc--; /* keyword */
5257 } else {
5258 ap++;
5259 }
5260 }
5261 }
5262 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
5263
5264 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
5265
5266 for (;;) {
5267 if (interactive && e.iop <= iostack) {
5268#if ENABLE_FEATURE_EDITING
5269 current_prompt = prompt->value;
5270#else
5271 prs(prompt->value);
5272#endif
5273 }
5274 onecommand();
5275 /* Ensure that getenv("PATH") stays current */
5276 setenv("PATH", path->value, 1);
5277 }
5278
5279 DBGPRINTF(("MSH_MAIN: returning.\n"));
5280}
5281
5282
Eric Andersenff9eee42001-06-29 04:57:14 +00005283/*
5284 * Copyright (c) 1987,1997, Prentice Hall
5285 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005286 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005287 * Redistribution and use of the MINIX operating system in source and
5288 * binary forms, with or without modification, are permitted provided
5289 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005290 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005291 * Redistributions of source code must retain the above copyright
5292 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005293 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005294 * Redistributions in binary form must reproduce the above
5295 * copyright notice, this list of conditions and the following
5296 * disclaimer in the documentation and/or other materials provided
5297 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005298 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005299 * Neither the name of Prentice Hall nor the names of the software
5300 * authors or contributors may be used to endorse or promote
5301 * products derived from this software without specific prior
5302 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005303 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005304 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5305 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5306 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5307 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5308 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5309 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5310 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5311 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5312 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5313 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5314 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5315 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5316 *
5317 */