blob: 492d3cf43f3c62b06c6a667b5d8372b095270e3c [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
Bernhard Reutner-Fischere15d7572006-06-02 20:56:16 +000016#include "busybox.h"
Eric Andersenff9eee42001-06-29 04:57:14 +000017#include <setjmp.h>
Eric Andersenff9eee42001-06-29 04:57:14 +000018#include <sys/times.h>
Eric Andersenff9eee42001-06-29 04:57:14 +000019
20#include "cmdedit.h"
Eric Andersenff9eee42001-06-29 04:57:14 +000021
Mike Frysinger17811882006-05-05 20:33:07 +000022/*#define MSHDEBUG 1*/
Eric Andersen12de6cf2004-08-04 19:19:10 +000023
24#ifdef MSHDEBUG
Mike Frysinger14ff19b2006-06-20 20:37:01 +000025int mshdbg = MSHDEBUG;
Eric Andersen12de6cf2004-08-04 19:19:10 +000026
27#define DBGPRINTF(x) if(mshdbg>0)printf x
28#define DBGPRINTF0(x) if(mshdbg>0)printf x
29#define DBGPRINTF1(x) if(mshdbg>1)printf x
30#define DBGPRINTF2(x) if(mshdbg>2)printf x
31#define DBGPRINTF3(x) if(mshdbg>3)printf x
32#define DBGPRINTF4(x) if(mshdbg>4)printf x
33#define DBGPRINTF5(x) if(mshdbg>5)printf x
34#define DBGPRINTF6(x) if(mshdbg>6)printf x
35#define DBGPRINTF7(x) if(mshdbg>7)printf x
36#define DBGPRINTF8(x) if(mshdbg>8)printf x
37#define DBGPRINTF9(x) if(mshdbg>9)printf x
38
39int mshdbg_rc = 0;
40
41#define RCPRINTF(x) if(mshdbg_rc)printf x
42
43#else
44
45#define DBGPRINTF(x)
46#define DBGPRINTF0(x)
47#define DBGPRINTF1(x)
48#define DBGPRINTF2(x)
49#define DBGPRINTF3(x)
50#define DBGPRINTF4(x)
51#define DBGPRINTF5(x)
52#define DBGPRINTF6(x)
53#define DBGPRINTF7(x)
54#define DBGPRINTF8(x)
55#define DBGPRINTF9(x)
56
57#define RCPRINTF(x)
58
59#endif /* MSHDEBUG */
60
61
Mike Frysinger2a131752006-06-06 06:26:12 +000062#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
63# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
64# define DEFAULT_USER_PROMPT "\\u:\\w$ "
65#else
66# define DEFAULT_ROOT_PROMPT "# "
67# define DEFAULT_USER_PROMPT "$ "
68#endif
69
70
Eric Andersenff9eee42001-06-29 04:57:14 +000071/* -------- sh.h -------- */
72/*
73 * shell
74 */
75
Eric Andersen12de6cf2004-08-04 19:19:10 +000076#define LINELIM 2100
77#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +000078
Eric Andersen392947c2002-12-11 07:42:46 +000079#undef NOFILE
Eric Andersen12de6cf2004-08-04 19:19:10 +000080#define NOFILE 20 /* Number of open files */
81#define NUFILE 10 /* Number of user-accessible files */
82#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +000083
84/*
85 * values returned by wait
86 */
Eric Andersen12de6cf2004-08-04 19:19:10 +000087#define WAITSIG(s) ((s)&0177)
88#define WAITVAL(s) (((s)>>8)&0377)
Eric Andersenff9eee42001-06-29 04:57:14 +000089#define WAITCORE(s) (((s)&0200)!=0)
90
91/*
Eric Andersenaff114c2004-04-14 17:51:38 +000092 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +000093 */
Eric Andersen8401eea2004-08-04 19:16:54 +000094typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +000095
96/*
97 * shell components
98 */
99
100#define QUOTE 0200
101
102#define NOBLOCK ((struct op *)NULL)
103#define NOWORD ((char *)NULL)
104#define NOWORDS ((char **)NULL)
105#define NOPIPE ((int *)NULL)
106
107/*
108 * Description of a command or an operation on commands.
109 * Might eventually use a union.
110 */
111struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000112 int type; /* operation type, see below */
113 char **words; /* arguments to a command */
114 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000115 struct op *left;
116 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000117 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000118};
119
Eric Andersen8401eea2004-08-04 19:16:54 +0000120#define TCOM 1 /* command */
121#define TPAREN 2 /* (c-list) */
122#define TPIPE 3 /* a | b */
123#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000124#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000125#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000126#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000127#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000128#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000129#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000130#define TWHILE 11
131#define TUNTIL 12
132#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000133#define TPAT 14 /* pattern in case */
134#define TBRACE 15 /* {c-list} */
135#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000136/* Added to support "." file expansion */
137#define TDOT 17
138
139/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000140#ifdef MSHDEBUG
141static char *T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000142 "PLACEHOLDER",
143 "TCOM",
144 "TPAREN",
145 "TPIPE",
146 "TLIST",
147 "TOR",
148 "TAND",
149 "TFOR",
150 "TDO",
151 "TCASE",
152 "TIF",
153 "TWHILE",
154 "TUNTIL",
155 "TELIF",
156 "TPAT",
157 "TBRACE",
158 "TASYNC",
159 "TDOT",
160};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000161#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000162
163/*
164 * actions determining the environment of a process
165 */
166#define BIT(i) (1<<(i))
Eric Andersen8401eea2004-08-04 19:16:54 +0000167#define FEXEC BIT(0) /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000168
Eric Andersen12de6cf2004-08-04 19:19:10 +0000169#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000170
Eric Andersenff9eee42001-06-29 04:57:14 +0000171/*
172 * flags to control evaluation of words
173 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000174#define DOSUB 1 /* interpret $, `, and quotes */
175#define DOBLANK 2 /* perform blank interpretation */
176#define DOGLOB 4 /* interpret [?* */
177#define DOKEY 8 /* move words with `=' to 2nd arg. list */
178#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000179
180#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
181
Eric Andersenff9eee42001-06-29 04:57:14 +0000182
Eric Andersen12de6cf2004-08-04 19:19:10 +0000183/* PROTOTYPES */
Eric Andersenff9eee42001-06-29 04:57:14 +0000184static int newfile(char *s);
185static char *findeq(char *cp);
186static char *cclass(char *p, int sub);
187static void initarea(void);
Matt Kraai2d91deb2001-08-01 17:21:35 +0000188extern int msh_main(int argc, char **argv);
Eric Andersenff9eee42001-06-29 04:57:14 +0000189
190
Eric Andersen8401eea2004-08-04 19:16:54 +0000191struct brkcon {
192 jmp_buf brkpt;
193 struct brkcon *nextlev;
194};
Eric Andersenff9eee42001-06-29 04:57:14 +0000195
Eric Andersen12de6cf2004-08-04 19:19:10 +0000196
Eric Andersenff9eee42001-06-29 04:57:14 +0000197/*
198 * redirection
199 */
200struct ioword {
Eric Andersen8401eea2004-08-04 19:16:54 +0000201 short io_unit; /* unit affected */
202 short io_flag; /* action (below) */
203 char *io_name; /* file name */
Eric Andersenff9eee42001-06-29 04:57:14 +0000204};
Eric Andersenff9eee42001-06-29 04:57:14 +0000205
Eric Andersen12de6cf2004-08-04 19:19:10 +0000206#define IOREAD 1 /* < */
207#define IOHERE 2 /* << (here file) */
208#define IOWRITE 4 /* > */
209#define IOCAT 8 /* >> */
210#define IOXHERE 16 /* ${}, ` in << */
211#define IODUP 32 /* >&digit */
212#define IOCLOSE 64 /* >&- */
Eric Andersenff9eee42001-06-29 04:57:14 +0000213
Eric Andersen8401eea2004-08-04 19:16:54 +0000214#define IODEFAULT (-1) /* token for default IO unit */
215
Eric Andersen12de6cf2004-08-04 19:19:10 +0000216
Eric Andersenff9eee42001-06-29 04:57:14 +0000217
218/*
219 * parsing & execution environment
220 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000221static struct env {
222 char *linep;
223 struct io *iobase;
224 struct io *iop;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000225 xint *errpt; /* void * */
Eric Andersen8401eea2004-08-04 19:16:54 +0000226 int iofd;
227 struct env *oenv;
Eric Andersenff9eee42001-06-29 04:57:14 +0000228} e;
229
230/*
231 * flags:
232 * -e: quit on error
233 * -k: look for name=value everywhere on command line
234 * -n: no execution
235 * -t: exit after reading and executing one command
236 * -v: echo as read
237 * -x: trace
238 * -u: unset variables net diagnostic
239 */
Mike Frysinger3672fe92006-11-15 21:52:10 +0000240static char flags['z' - 'a' + 1];
241/* this looks weird, but is OK ... we index flag with 'a'...'z' */
242static char *flag = flags - 'a';
Eric Andersenff9eee42001-06-29 04:57:14 +0000243
Eric Andersen8401eea2004-08-04 19:16:54 +0000244static char *null; /* null value for variable */
245static int intr; /* interrupt pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000246
Eric Andersen8401eea2004-08-04 19:16:54 +0000247static char *trap[_NSIG + 1];
248static char ourtrap[_NSIG + 1];
249static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000250
Eric Andersen8401eea2004-08-04 19:16:54 +0000251static int heedint; /* heed interrupt signals */
Eric Andersenff9eee42001-06-29 04:57:14 +0000252
Eric Andersen8401eea2004-08-04 19:16:54 +0000253static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000254
Eric Andersen8401eea2004-08-04 19:16:54 +0000255static char line[LINELIM];
256static char *elinep;
Eric Andersenff9eee42001-06-29 04:57:14 +0000257
Eric Andersen12de6cf2004-08-04 19:19:10 +0000258
Eric Andersenff9eee42001-06-29 04:57:14 +0000259/*
260 * other functions
261 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000262static int (*inbuilt(char *s)) (struct op *);
Eric Andersen392947c2002-12-11 07:42:46 +0000263
Eric Andersen8401eea2004-08-04 19:16:54 +0000264static char *rexecve(char *c, char **v, char **envp);
265static char *space(int n);
266static char *strsave(char *s, int a);
267static char *evalstr(char *cp, int f);
268static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000269static char *unquote(char *as);
270static struct var *lookup(char *n);
271static int rlookup(char *n);
272static struct wdblock *glob(char *cp, struct wdblock *wb);
273static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000274static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000275static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000276static char **eval(char **ap, int f);
277static int setstatus(int s);
278static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000279
Eric Andersen8401eea2004-08-04 19:16:54 +0000280static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000281
Eric Andersen8401eea2004-08-04 19:16:54 +0000282static int newenv(int f);
283static void quitenv(void);
284static void err(char *s);
285static int anys(char *s1, char *s2);
286static int any(int c, char *s);
287static void next(int f);
288static void setdash(void);
289static void onecommand(void);
290static void runtrap(int i);
291static int gmatch(char *s, char *p);
Eric Andersenff9eee42001-06-29 04:57:14 +0000292
Eric Andersen12de6cf2004-08-04 19:19:10 +0000293
Eric Andersenff9eee42001-06-29 04:57:14 +0000294/*
295 * error handling
296 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000297static void leave(void); /* abort shell (or fail in subshell) */
298static void fail(void); /* fail but return to process next command */
299static void warn(char *s);
300static void sig(int i); /* default signal handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000301
302
303
304/* -------- area stuff -------- */
305
Eric Andersen12de6cf2004-08-04 19:19:10 +0000306#define REGSIZE sizeof(struct region)
307#define GROWBY (256)
308/* #define SHRINKBY (64) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000309#undef SHRINKBY
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000310#define FREE (32767)
311#define BUSY (0)
312#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000313
314
315struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000316 struct region *next;
317 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000318};
319
320
321
322/* -------- grammar stuff -------- */
323typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000324 char *cp;
325 char **wp;
326 int i;
327 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000328} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000329
Eric Andersenff9eee42001-06-29 04:57:14 +0000330#define WORD 256
331#define LOGAND 257
332#define LOGOR 258
333#define BREAK 259
Eric Andersen12de6cf2004-08-04 19:19:10 +0000334#define IF 260
Eric Andersenff9eee42001-06-29 04:57:14 +0000335#define THEN 261
336#define ELSE 262
337#define ELIF 263
Eric Andersen12de6cf2004-08-04 19:19:10 +0000338#define FI 264
Eric Andersenff9eee42001-06-29 04:57:14 +0000339#define CASE 265
340#define ESAC 266
Eric Andersen12de6cf2004-08-04 19:19:10 +0000341#define FOR 267
Eric Andersenff9eee42001-06-29 04:57:14 +0000342#define WHILE 268
343#define UNTIL 269
Eric Andersen12de6cf2004-08-04 19:19:10 +0000344#define DO 270
Eric Andersenff9eee42001-06-29 04:57:14 +0000345#define DONE 271
Eric Andersen12de6cf2004-08-04 19:19:10 +0000346#define IN 272
347/* Added for "." file expansion */
348#define DOT 273
349
Eric Andersenff9eee42001-06-29 04:57:14 +0000350#define YYERRCODE 300
351
352/* flags to yylex */
Eric Andersen8401eea2004-08-04 19:16:54 +0000353#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000354
355#define SYNTAXERR zzerr()
Eric Andersen12de6cf2004-08-04 19:19:10 +0000356
Eric Andersen8401eea2004-08-04 19:16:54 +0000357static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000358static struct op *andor(void);
359static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000360static int synio(int cf);
361static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000362static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000363static struct op *nested(int type, int mark);
364static struct op *command(int cf);
365static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000366static struct op *thenpart(void);
367static struct op *elsepart(void);
368static struct op *caselist(void);
369static struct op *casepart(void);
370static char **pattern(void);
371static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000372static struct op *list(struct op *t1, struct op *t2);
373static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000374static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000375static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000376static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000377static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000378static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000379static struct ioword *io(int u, int f, char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000380static void zzerr(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000381static void yyerror(char *s);
382static int yylex(int cf);
383static int collect(int c, int c1);
384static int dual(int c);
385static void diag(int ec);
386static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000387
388/* -------- var.h -------- */
389
Eric Andersen8401eea2004-08-04 19:16:54 +0000390struct var {
391 char *value;
392 char *name;
393 struct var *next;
394 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000395};
Eric Andersenff9eee42001-06-29 04:57:14 +0000396
Eric Andersen8401eea2004-08-04 19:16:54 +0000397#define COPYV 1 /* flag to setval, suggesting copy */
398#define RONLY 01 /* variable is read-only */
399#define EXPORT 02 /* variable is to be exported */
400#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000401
Eric Andersen8401eea2004-08-04 19:16:54 +0000402static int yyparse(void);
403static struct var *lookup(char *n);
404static void setval(struct var *vp, char *val);
405static void nameval(struct var *vp, char *val, char *name);
406static void export(struct var *vp);
407static void ronly(struct var *vp);
408static int isassign(char *s);
409static int checkname(char *cp);
410static int assign(char *s, int cf);
411static void putvlist(int f, int out);
412static int eqname(char *n1, char *n2);
413
414static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000415
Eric Andersen12de6cf2004-08-04 19:19:10 +0000416
Eric Andersenff9eee42001-06-29 04:57:14 +0000417/* -------- io.h -------- */
418/* io buffer */
419struct iobuf {
Eric Andersen8401eea2004-08-04 19:16:54 +0000420 unsigned id; /* buffer id */
421 char buf[512]; /* buffer */
422 char *bufp; /* pointer into buffer */
423 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000424};
425
426/* possible arguments to an IO function */
427struct ioarg {
Eric Andersen8401eea2004-08-04 19:16:54 +0000428 char *aword;
429 char **awordlist;
430 int afile; /* file descriptor */
431 unsigned afid; /* buffer id */
432 long afpos; /* file position */
433 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000434};
Eric Andersen8401eea2004-08-04 19:16:54 +0000435
Eric Andersenff9eee42001-06-29 04:57:14 +0000436//static struct ioarg ioargstack[NPUSH];
437#define AFID_NOBUF (~0)
438#define AFID_ID 0
439
440/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000441struct io {
442 int (*iofn) (struct ioarg *, struct io *);
443 struct ioarg *argp;
444 int peekc;
445 char prev; /* previous character read by readc() */
446 char nlcount; /* for `'s */
447 char xchar; /* for `'s */
448 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000449};
Eric Andersen8401eea2004-08-04 19:16:54 +0000450
451//static struct io iostack[NPUSH];
452#define XOTHER 0 /* none of the below */
453#define XDOLL 1 /* expanding ${} */
454#define XGRAVE 2 /* expanding `'s */
455#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000456
457/* in substitution */
458#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
459
Eric Andersen12de6cf2004-08-04 19:19:10 +0000460
Eric Andersenff9eee42001-06-29 04:57:14 +0000461/*
462 * input generators for IO structure
463 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000464static int nlchar(struct ioarg *ap);
465static int strchar(struct ioarg *ap);
466static int qstrchar(struct ioarg *ap);
467static int filechar(struct ioarg *ap);
468static int herechar(struct ioarg *ap);
469static int linechar(struct ioarg *ap);
470static int gravechar(struct ioarg *ap, struct io *iop);
471static int qgravechar(struct ioarg *ap, struct io *iop);
472static int dolchar(struct ioarg *ap);
473static int wdchar(struct ioarg *ap);
474static void scraphere(void);
475static void freehere(int area);
476static void gethere(void);
477static void markhere(char *s, struct ioword *iop);
478static int herein(char *hname, int xdoll);
479static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000480
Eric Andersen12de6cf2004-08-04 19:19:10 +0000481
Eric Andersenff9eee42001-06-29 04:57:14 +0000482/*
483 * IO functions
484 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000485static int eofc(void);
486static int readc(void);
487static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000488static void ioecho(char c);
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000489static void prs(const char *s);
Eric Andersen8401eea2004-08-04 19:16:54 +0000490static void prn(unsigned u);
491static void closef(int i);
492static void closeall(void);
Eric Andersenff9eee42001-06-29 04:57:14 +0000493
Eric Andersen12de6cf2004-08-04 19:19:10 +0000494
Eric Andersenff9eee42001-06-29 04:57:14 +0000495/*
496 * IO control
497 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000498static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
499static int remap(int fd);
500static int openpipe(int *pv);
501static void closepipe(int *pv);
502static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000503
Eric Andersenff9eee42001-06-29 04:57:14 +0000504#define PUSHIO(what,arg,gen) ((temparg.what = (arg)),pushio(&temparg,(gen)))
505#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
506
507/* -------- word.h -------- */
508
Eric Andersen8401eea2004-08-04 19:16:54 +0000509#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000510
Eric Andersen8401eea2004-08-04 19:16:54 +0000511struct wdblock {
512 short w_bsize;
513 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000514 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000515 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000516};
517
Eric Andersen8401eea2004-08-04 19:16:54 +0000518static struct wdblock *addword(char *wd, struct wdblock *wb);
519static struct wdblock *newword(int nw);
520static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000521
522/* -------- area.h -------- */
523
524/*
525 * storage allocation
526 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000527static char *getcell(unsigned nbytes);
528static void garbage(void);
529static void setarea(char *cp, int a);
530static int getarea(char *cp);
531static void freearea(int a);
532static void freecell(char *cp);
533static int areanum; /* current allocation area */
Eric Andersenff9eee42001-06-29 04:57:14 +0000534
Eric Andersen12de6cf2004-08-04 19:19:10 +0000535#define NEW(type) (type *)getcell(sizeof(type))
Eric Andersenff9eee42001-06-29 04:57:14 +0000536#define DELETE(obj) freecell((char *)obj)
537
538
539/* -------- misc stuff -------- */
540
Eric Andersen12de6cf2004-08-04 19:19:10 +0000541static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000542static int iosetup(struct ioword *iop, int pipein, int pipeout);
543static void echo(char **wp);
544static struct op **find1case(struct op *t, char *w);
545static struct op *findcase(struct op *t, char *w);
546static void brkset(struct brkcon *bc);
547static int dolabel(struct op *t);
548static int dohelp(struct op *t);
549static int dochdir(struct op *t);
550static int doshift(struct op *t);
551static int dologin(struct op *t);
552static int doumask(struct op *t);
553static int doexec(struct op *t);
554static int dodot(struct op *t);
555static int dowait(struct op *t);
556static int doread(struct op *t);
557static int doeval(struct op *t);
558static int dotrap(struct op *t);
559static int getsig(char *s);
560static void setsig(int n, sighandler_t f);
561static int getn(char *as);
562static int dobreak(struct op *t);
563static int docontinue(struct op *t);
564static int brkcontin(char *cp, int val);
565static int doexit(struct op *t);
566static int doexport(struct op *t);
567static int doreadonly(struct op *t);
568static void rdexp(char **wp, void (*f) (struct var *), int key);
569static void badid(char *s);
570static int doset(struct op *t);
571static void varput(char *s, int out);
572static int dotimes(struct op *t);
573static int expand(char *cp, struct wdblock **wbp, int f);
574static char *blank(int f);
575static int dollar(int quoted);
576static int grave(int quoted);
577static void globname(char *we, char *pp);
578static char *generate(char *start1, char *end1, char *middle, char *end);
579static int anyspcl(struct wdblock *wb);
580static int xstrcmp(char *p1, char *p2);
581static void glob0(char *a0, unsigned int a1, int a2,
582 int (*a3) (char *, char *));
583static void glob1(char *base, char *lim);
584static void glob2(char *i, char *j);
585static void glob3(char *i, char *j, char *k);
586static void readhere(char **name, char *s, int ec);
587static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
588static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000589
Eric Andersen8401eea2004-08-04 19:16:54 +0000590struct here {
591 char *h_tag;
592 int h_dosub;
593 struct ioword *h_iop;
594 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000595};
596
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000597static const char * const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000598 "Signal 0",
599 "Hangup",
Eric Andersen8401eea2004-08-04 19:16:54 +0000600 (char *) NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000601 "Quit",
602 "Illegal instruction",
603 "Trace/BPT trap",
604 "Abort",
605 "Bus error",
606 "Floating Point Exception",
607 "Killed",
608 "SIGUSR1",
609 "SIGSEGV",
610 "SIGUSR2",
Eric Andersen8401eea2004-08-04 19:16:54 +0000611 (char *) NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000612 "Alarm clock",
613 "Terminated",
614};
Eric Andersen8401eea2004-08-04 19:16:54 +0000615
Eric Andersenff9eee42001-06-29 04:57:14 +0000616#define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
617
618struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000619 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000620 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000621};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000622static const struct res restab[] = {
Eric Andersen8401eea2004-08-04 19:16:54 +0000623 {"for", FOR},
624 {"case", CASE},
625 {"esac", ESAC},
626 {"while", WHILE},
627 {"do", DO},
628 {"done", DONE},
629 {"if", IF},
630 {"in", IN},
631 {"then", THEN},
632 {"else", ELSE},
633 {"elif", ELIF},
634 {"until", UNTIL},
635 {"fi", FI},
Eric Andersen8401eea2004-08-04 19:16:54 +0000636 {";;", BREAK},
637 {"||", LOGOR},
638 {"&&", LOGAND},
639 {"{", '{'},
640 {"}", '}'},
Eric Andersen12de6cf2004-08-04 19:19:10 +0000641 {".", DOT},
Eric Andersen8401eea2004-08-04 19:16:54 +0000642 {0, 0},
Eric Andersenff9eee42001-06-29 04:57:14 +0000643};
644
645
Eric Andersen1c039232001-07-07 00:05:55 +0000646struct builtincmd {
647 const char *name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000648 int (*builtinfunc) (struct op * t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000649};
Eric Andersen8401eea2004-08-04 19:16:54 +0000650static const struct builtincmd builtincmds[] = {
651 {".", dodot},
652 {":", dolabel},
653 {"break", dobreak},
654 {"cd", dochdir},
655 {"continue", docontinue},
656 {"eval", doeval},
657 {"exec", doexec},
658 {"exit", doexit},
659 {"export", doexport},
660 {"help", dohelp},
661 {"login", dologin},
662 {"newgrp", dologin},
663 {"read", doread},
664 {"readonly", doreadonly},
665 {"set", doset},
666 {"shift", doshift},
667 {"times", dotimes},
668 {"trap", dotrap},
669 {"umask", doumask},
670 {"wait", dowait},
671 {0, 0}
Eric Andersenff9eee42001-06-29 04:57:14 +0000672};
673
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000674static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000675static struct op *dowholefile(int, int);
676
Eric Andersenff9eee42001-06-29 04:57:14 +0000677/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000678extern char **environ; /* environment pointer */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000679
Eric Andersen8401eea2004-08-04 19:16:54 +0000680static char **dolv;
681static int dolc;
682static int exstat;
683static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000684static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000685static int execflg;
686static int multiline; /* \n changed to ; */
687static struct op *outtree; /* result from parser */
688static xint *failpt;
689static xint *errpt;
690static struct brkcon *brklist;
691static int isbreak;
692static struct wdblock *wdlist;
693static struct wdblock *iolist;
694static char *trap[_NSIG + 1];
695static char ourtrap[_NSIG + 1];
696static int trapset; /* trap pending */
697static int yynerrs; /* yacc */
698static char line[LINELIM];
Eric Andersen12de6cf2004-08-04 19:19:10 +0000699
700#ifdef MSHDEBUG
701static struct var *mshdbg_var;
702#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000703static struct var *vlist; /* dictionary */
704static struct var *homedir; /* home directory */
705static struct var *prompt; /* main prompt */
706static struct var *cprompt; /* continuation prompt */
707static struct var *path; /* search path for commands */
708static struct var *shell; /* shell to interpret command files */
709static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000710
Eric Andersen8401eea2004-08-04 19:16:54 +0000711static int areanum; /* current allocation area */
712static int intr;
713static int inparse;
Eric Andersen8401eea2004-08-04 19:16:54 +0000714static char *null = "";
715static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000716static void (*qflag) (int) = SIG_IGN;
717static int startl;
718static int peeksym;
719static int nlseen;
720static int iounit = IODEFAULT;
721static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000722static char *elinep = line + sizeof(line) - 5;
723
724static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
725static struct ioarg ioargstack[NPUSH];
726static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000727static struct iobuf sharedbuf = { AFID_NOBUF };
728static struct iobuf mainbuf = { AFID_NOBUF };
Eric Andersenff9eee42001-06-29 04:57:14 +0000729static unsigned bufid = AFID_ID; /* buffer id counter */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000730
Eric Andersen8401eea2004-08-04 19:16:54 +0000731static struct here *inhere; /* list of hear docs while parsing */
732static struct here *acthere; /* list of active here documents */
733static struct region *areabot; /* bottom of area */
734static struct region *areatop; /* top of area */
735static struct region *areanxt; /* starting point of scan */
736static void *brktop;
737static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000738
Eric Andersen12de6cf2004-08-04 19:19:10 +0000739static struct env e = {
740 line, /* linep: char ptr */
741 iostack, /* iobase: struct io ptr */
742 iostack - 1, /* iop: struct io ptr */
743 (xint *) NULL, /* errpt: void ptr for errors? */
744 FDBASE, /* iofd: file desc */
745 (struct env *) NULL /* oenv: struct env ptr */
746};
747
748#ifdef MSHDEBUG
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000749void print_t(struct op *t);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000750void print_t(struct op *t)
751{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000752 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
753 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000754
755 if (t->words) {
756 DBGPRINTF(("T: W1: %s", t->words[0]));
757 }
758
759 return;
760}
761
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000762void print_tree(struct op *head);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000763void print_tree(struct op *head)
764{
765 if (head == NULL) {
766 DBGPRINTF(("PRINT_TREE: no tree\n"));
767 return;
768 }
769
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000770 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000771 head->right));
772
773 if (head->left)
774 print_tree(head->left);
775
776 if (head->right)
777 print_tree(head->right);
778
779 return;
780}
781#endif /* MSHDEBUG */
782
Eric Andersenff9eee42001-06-29 04:57:14 +0000783
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000784#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +0000785static char *current_prompt;
Eric Andersenff9eee42001-06-29 04:57:14 +0000786#endif
787
Eric Andersenff9eee42001-06-29 04:57:14 +0000788/* -------- sh.c -------- */
789/*
790 * shell
791 */
792
793
Rob Landleydfba7412006-03-06 20:47:33 +0000794int msh_main(int argc, char **argv)
Eric Andersenff9eee42001-06-29 04:57:14 +0000795{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000796 int f;
797 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +0000798 int cflag;
799 char *name, **ap;
Eric Andersen8401eea2004-08-04 19:16:54 +0000800 int (*iof) (struct ioarg *);
Eric Andersenff9eee42001-06-29 04:57:14 +0000801
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000802 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000803
Eric Andersenff9eee42001-06-29 04:57:14 +0000804 initarea();
805 if ((ap = environ) != NULL) {
806 while (*ap)
807 assign(*ap++, !COPYV);
808 for (ap = environ; *ap;)
809 export(lookup(*ap++));
810 }
811 closeall();
812 areanum = 1;
813
814 shell = lookup("SHELL");
815 if (shell->value == null)
Eric Andersen78500142004-08-27 19:55:28 +0000816 setval(shell, (char *)DEFAULT_SHELL);
Eric Andersenff9eee42001-06-29 04:57:14 +0000817 export(shell);
818
819 homedir = lookup("HOME");
820 if (homedir->value == null)
821 setval(homedir, "/");
822 export(homedir);
823
Eric Andersen737f5fb2003-03-14 16:05:59 +0000824 setval(lookup("$"), putn(getpid()));
Eric Andersenff9eee42001-06-29 04:57:14 +0000825
826 path = lookup("PATH");
Eric Andersen737f5fb2003-03-14 16:05:59 +0000827 if (path->value == null) {
828 if (geteuid() == 0)
829 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
830 else
831 setval(path, "/bin:/usr/bin");
832 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000833 export(path);
834
835 ifs = lookup("IFS");
836 if (ifs->value == null)
837 setval(ifs, " \t\n");
838
Eric Andersen12de6cf2004-08-04 19:19:10 +0000839#ifdef MSHDEBUG
840 mshdbg_var = lookup("MSHDEBUG");
841 if (mshdbg_var->value == null)
842 setval(mshdbg_var, "0");
843#endif
844
Eric Andersenff9eee42001-06-29 04:57:14 +0000845 prompt = lookup("PS1");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000846#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000847 if (prompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000848#endif
Mike Frysinger2a131752006-06-06 06:26:12 +0000849 setval(prompt, DEFAULT_USER_PROMPT);
Eric Andersenff9eee42001-06-29 04:57:14 +0000850 if (geteuid() == 0) {
Mike Frysinger2a131752006-06-06 06:26:12 +0000851 setval(prompt, DEFAULT_ROOT_PROMPT);
Eric Andersenff9eee42001-06-29 04:57:14 +0000852 prompt->status &= ~EXPORT;
853 }
854 cprompt = lookup("PS2");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000855#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000856 if (cprompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000857#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000858 setval(cprompt, "> ");
859
860 iof = filechar;
861 cflag = 0;
862 name = *argv++;
863 if (--argc >= 1) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000864 if (argv[0][0] == '-' && argv[0][1] != '\0') {
865 for (s = argv[0] + 1; *s; s++)
Eric Andersenff9eee42001-06-29 04:57:14 +0000866 switch (*s) {
867 case 'c':
868 prompt->status &= ~EXPORT;
869 cprompt->status &= ~EXPORT;
870 setval(prompt, "");
871 setval(cprompt, "");
872 cflag = 1;
873 if (--argc > 0)
874 PUSHIO(aword, *++argv, iof = nlchar);
875 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000876
Eric Andersenff9eee42001-06-29 04:57:14 +0000877 case 'q':
878 qflag = SIG_DFL;
879 break;
880
881 case 's':
882 /* standard input */
883 break;
884
885 case 't':
886 prompt->status &= ~EXPORT;
887 setval(prompt, "");
888 iof = linechar;
889 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000890
Eric Andersenff9eee42001-06-29 04:57:14 +0000891 case 'i':
892 interactive++;
893 default:
Eric Andersen8401eea2004-08-04 19:16:54 +0000894 if (*s >= 'a' && *s <= 'z')
895 flag[(int) *s]++;
Eric Andersenff9eee42001-06-29 04:57:14 +0000896 }
897 } else {
898 argv--;
899 argc++;
900 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000901
Eric Andersenff9eee42001-06-29 04:57:14 +0000902 if (iof == filechar && --argc > 0) {
903 setval(prompt, "");
904 setval(cprompt, "");
905 prompt->status &= ~EXPORT;
906 cprompt->status &= ~EXPORT;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000907
908/* Shell is non-interactive, activate printf-based debug */
909#ifdef MSHDEBUG
910 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
911 if (mshdbg < 0)
912 mshdbg = 0;
913#endif
914 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
915
Eric Andersenff9eee42001-06-29 04:57:14 +0000916 if (newfile(name = *++argv))
Eric Andersen12de6cf2004-08-04 19:19:10 +0000917 exit(1); /* Exit on error */
Eric Andersenff9eee42001-06-29 04:57:14 +0000918 }
919 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000920
Eric Andersenff9eee42001-06-29 04:57:14 +0000921 setdash();
Eric Andersen12de6cf2004-08-04 19:19:10 +0000922
923 /* This won't be true if PUSHIO has been called, say from newfile() above */
Eric Andersenff9eee42001-06-29 04:57:14 +0000924 if (e.iop < iostack) {
925 PUSHIO(afile, 0, iof);
Eric Andersen1c039232001-07-07 00:05:55 +0000926 if (isatty(0) && isatty(1) && !cflag) {
Eric Andersenff9eee42001-06-29 04:57:14 +0000927 interactive++;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000928#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
Eric Andersen12de6cf2004-08-04 19:19:10 +0000929#ifdef MSHDEBUG
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000930 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000931#else
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000932 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000933#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000934 printf("Enter 'help' for a list of built-in commands.\n\n");
Eric Andersend63dee42001-10-19 00:22:23 +0000935#endif
Eric Andersen1c039232001-07-07 00:05:55 +0000936 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000937 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000938
Eric Andersenff9eee42001-06-29 04:57:14 +0000939 signal(SIGQUIT, qflag);
940 if (name && name[0] == '-') {
941 interactive++;
942 if ((f = open(".profile", 0)) >= 0)
943 next(remap(f));
944 if ((f = open("/etc/profile", 0)) >= 0)
945 next(remap(f));
946 }
947 if (interactive)
948 signal(SIGTERM, sig);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000949
Eric Andersenff9eee42001-06-29 04:57:14 +0000950 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
951 signal(SIGINT, onintr);
952 dolv = argv;
953 dolc = argc;
954 dolv[0] = name;
955 if (dolc > 1) {
956 for (ap = ++argv; --argc > 0;) {
957 if (assign(*ap = *argv++, !COPYV)) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000958 dolc--; /* keyword */
Eric Andersenff9eee42001-06-29 04:57:14 +0000959 } else {
960 ap++;
961 }
962 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000963 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000964 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
965
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000966 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000967
Eric Andersenff9eee42001-06-29 04:57:14 +0000968 for (;;) {
969 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000970#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +0000971 current_prompt = prompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +0000972#else
973 prs(prompt->value);
974#endif
975 }
976 onecommand();
Eric Andersen1c315012002-04-26 23:40:09 +0000977 /* Ensure that getenv("PATH") stays current */
978 setenv("PATH", path->value, 1);
Eric Andersenff9eee42001-06-29 04:57:14 +0000979 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000980
981 DBGPRINTF(("MSH_MAIN: returning.\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +0000982}
983
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000984static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000985{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000986 char *cp;
987 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +0000988 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000989
990 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +0000991 for (c = 'a'; c <= 'z'; c++)
992 if (flag[(int) c])
Eric Andersenff9eee42001-06-29 04:57:14 +0000993 *cp++ = c;
994 *cp = 0;
995 setval(lookup("-"), m);
996}
997
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000998static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +0000999{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001000 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001001
1002 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001003
1004 if (strcmp(s, "-") != 0) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001005 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001006 f = open(s, 0);
1007 if (f < 0) {
1008 prs(s);
1009 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001010 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001011 }
1012 } else
1013 f = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001014
Eric Andersenff9eee42001-06-29 04:57:14 +00001015 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001016 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001017}
1018
Eric Andersen12de6cf2004-08-04 19:19:10 +00001019
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001020struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001021{
1022 struct op *dotnode;
1023
1024 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001025 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001026
1027 if (head->left != NULL) {
1028 dotnode = scantree(head->left);
1029 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001030 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001031 }
1032
1033 if (head->right != NULL) {
1034 dotnode = scantree(head->right);
1035 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001036 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001037 }
1038
1039 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001040 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001041
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001042 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001043
1044 if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001045 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001046 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001047 }
1048
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001049 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001050}
1051
1052
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001053static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001054{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001055 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001056 jmp_buf m1;
1057
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001058 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001059
Eric Andersenff9eee42001-06-29 04:57:14 +00001060 while (e.oenv)
1061 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001062
Eric Andersenff9eee42001-06-29 04:57:14 +00001063 areanum = 1;
1064 freehere(areanum);
1065 freearea(areanum);
1066 garbage();
1067 wdlist = 0;
1068 iolist = 0;
1069 e.errpt = 0;
1070 e.linep = line;
1071 yynerrs = 0;
1072 multiline = 0;
1073 inparse = 1;
1074 intr = 0;
1075 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001076
Eric Andersen8401eea2004-08-04 19:16:54 +00001077 setjmp(failpt = m1); /* Bruce Evans' fix */
Eric Andersenff9eee42001-06-29 04:57:14 +00001078 if (setjmp(failpt = m1) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001079
1080 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1081
Eric Andersenff9eee42001-06-29 04:57:14 +00001082 while (e.oenv)
1083 quitenv();
1084 scraphere();
1085 if (!interactive && intr)
1086 leave();
1087 inparse = 0;
1088 intr = 0;
1089 return;
1090 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001091
Eric Andersenff9eee42001-06-29 04:57:14 +00001092 inparse = 0;
1093 brklist = 0;
1094 intr = 0;
1095 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001096
1097 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001098 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001099 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001100 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001101 }
1102
Eric Andersenff9eee42001-06-29 04:57:14 +00001103 if (!interactive && intr) {
1104 execflg = 0;
1105 leave();
1106 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001107
Eric Andersenff9eee42001-06-29 04:57:14 +00001108 if ((i = trapset) != 0) {
1109 trapset = 0;
1110 runtrap(i);
1111 }
1112}
1113
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001114static void fail(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001115{
1116 longjmp(failpt, 1);
1117 /* NOTREACHED */
1118}
1119
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001120static void leave(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001121{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001122 DBGPRINTF(("LEAVE: leave called!\n"));
1123
Eric Andersenff9eee42001-06-29 04:57:14 +00001124 if (execflg)
1125 fail();
1126 scraphere();
1127 freehere(1);
1128 runtrap(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001129 _exit(exstat);
Eric Andersenff9eee42001-06-29 04:57:14 +00001130 /* NOTREACHED */
1131}
1132
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001133static void warn(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001134{
Eric Andersen8401eea2004-08-04 19:16:54 +00001135 if (*s) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001136 prs(s);
1137 exstat = -1;
1138 }
1139 prs("\n");
1140 if (flag['e'])
1141 leave();
1142}
1143
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001144static void err(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001145{
1146 warn(s);
1147 if (flag['n'])
1148 return;
1149 if (!interactive)
1150 leave();
1151 if (e.errpt)
1152 longjmp(e.errpt, 1);
1153 closeall();
1154 e.iop = e.iobase = iostack;
1155}
1156
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001157static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001158{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001159 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001160
1161 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001162
1163 if (f) {
1164 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001165 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001166 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001167
Eric Andersenff9eee42001-06-29 04:57:14 +00001168 ep = (struct env *) space(sizeof(*ep));
1169 if (ep == NULL) {
1170 while (e.oenv)
1171 quitenv();
1172 fail();
1173 }
1174 *ep = e;
1175 e.oenv = ep;
1176 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001177
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001178 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001179}
1180
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001181static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001182{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001183 struct env *ep;
1184 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001185
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001186 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001187
1188 if ((ep = e.oenv) != NULL) {
1189 fd = e.iofd;
1190 e = *ep;
1191 /* should close `'d files */
1192 DELETE(ep);
1193 while (--fd >= e.iofd)
1194 close(fd);
1195 }
1196}
1197
1198/*
1199 * Is any character from s1 in s2?
1200 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001201static int anys(char *s1, char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001202{
1203 while (*s1)
1204 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001205 return 1;
1206 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001207}
1208
1209/*
1210 * Is character c in s?
1211 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001212static int any(int c, char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001213{
1214 while (*s)
1215 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001216 return 1;
1217 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001218}
1219
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001220static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001221{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001222 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001223}
1224
Eric Andersen8401eea2004-08-04 19:16:54 +00001225static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001226{
1227 PUSHIO(afile, f, filechar);
1228}
1229
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001230static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001231{
1232 signal(SIGINT, onintr);
1233 intr = 1;
1234 if (interactive) {
1235 if (inparse) {
1236 prs("\n");
1237 fail();
1238 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001239 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001240 execflg = 0;
1241 leave();
1242 }
1243}
1244
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001245static char *space(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001246{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001247 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001248
1249 if ((cp = getcell(n)) == 0)
1250 err("out of string space");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001251 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001252}
1253
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001254static char *strsave(char *s, int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001255{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001256 char *cp, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001257
Eric Andersen8401eea2004-08-04 19:16:54 +00001258 if ((cp = space(strlen(s) + 1)) != NULL) {
1259 setarea((char *) cp, a);
1260 for (xp = cp; (*xp++ = *s++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001261 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001262 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001263 return "";
Eric Andersenff9eee42001-06-29 04:57:14 +00001264}
1265
1266/*
1267 * trap handling
1268 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001269static void sig(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00001270{
1271 trapset = i;
1272 signal(i, sig);
1273}
1274
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001275static void runtrap(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00001276{
1277 char *trapstr;
1278
1279 if ((trapstr = trap[i]) == NULL)
1280 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001281
Eric Andersenff9eee42001-06-29 04:57:14 +00001282 if (i == 0)
1283 trap[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001284
Eric Andersenff9eee42001-06-29 04:57:14 +00001285 RUN(aword, trapstr, nlchar);
1286}
1287
1288/* -------- var.c -------- */
1289
1290/*
1291 * Find the given name in the dictionary
1292 * and return its value. If the name was
1293 * not previously there, enter it now and
1294 * return a null value.
1295 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001296static struct var *lookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001297{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001298 struct var *vp;
1299 char *cp;
1300 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001301 static struct var dummy;
1302
1303 if (isdigit(*n)) {
1304 dummy.name = n;
1305 for (c = 0; isdigit(*n) && c < 1000; n++)
Eric Andersen8401eea2004-08-04 19:16:54 +00001306 c = c * 10 + *n - '0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001307 dummy.status = RONLY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001308 dummy.value = c <= dolc ? dolv[c] : null;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001309 return &dummy;
Eric Andersenff9eee42001-06-29 04:57:14 +00001310 }
1311 for (vp = vlist; vp; vp = vp->next)
1312 if (eqname(vp->name, n))
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001313 return vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001314 cp = findeq(n);
Eric Andersen8401eea2004-08-04 19:16:54 +00001315 vp = (struct var *) space(sizeof(*vp));
1316 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001317 dummy.name = dummy.value = "";
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001318 return &dummy;
Eric Andersenff9eee42001-06-29 04:57:14 +00001319 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001320 for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001321 if (*cp == 0)
1322 *cp = '=';
1323 *++cp = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00001324 setarea((char *) vp, 0);
1325 setarea((char *) vp->name, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001326 vp->value = null;
1327 vp->next = vlist;
1328 vp->status = GETCELL;
1329 vlist = vp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001330 return vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001331}
1332
1333/*
1334 * give variable at `vp' the value `val'.
1335 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001336static void setval(struct var *vp, char *val)
Eric Andersenff9eee42001-06-29 04:57:14 +00001337{
Eric Andersen8401eea2004-08-04 19:16:54 +00001338 nameval(vp, val, (char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001339}
1340
1341/*
1342 * if name is not NULL, it must be
1343 * a prefix of the space `val',
1344 * and end with `='.
1345 * this is all so that exporting
1346 * values is reasonably painless.
1347 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001348static void nameval(struct var *vp, char *val, char *name)
Eric Andersenff9eee42001-06-29 04:57:14 +00001349{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001350 char *cp, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001351 char *nv;
1352 int fl;
1353
1354 if (vp->status & RONLY) {
1355 for (xp = vp->name; *xp && *xp != '=';)
1356 putc(*xp++, stderr);
1357 err(" is read-only");
1358 return;
1359 }
1360 fl = 0;
1361 if (name == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001362 xp = space(strlen(vp->name) + strlen(val) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00001363 if (xp == 0)
1364 return;
1365 /* make string: name=value */
Eric Andersen8401eea2004-08-04 19:16:54 +00001366 setarea((char *) xp, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001367 name = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001368 for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001369 if (*xp++ == 0)
1370 xp[-1] = '=';
1371 nv = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001372 for (cp = val; (*xp++ = *cp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00001373 val = nv;
1374 fl = GETCELL;
1375 }
1376 if (vp->status & GETCELL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001377 freecell(vp->name); /* form new string `name=value' */
Eric Andersenff9eee42001-06-29 04:57:14 +00001378 vp->name = name;
1379 vp->value = val;
1380 vp->status |= fl;
1381}
1382
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001383static void export(struct var *vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001384{
1385 vp->status |= EXPORT;
1386}
1387
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001388static void ronly(struct var *vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001389{
Matt Kraai69edfec2001-08-06 14:14:18 +00001390 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
Eric Andersenff9eee42001-06-29 04:57:14 +00001391 vp->status |= RONLY;
1392}
1393
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001394static int isassign(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001395{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001396 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1397
Eric Andersen8401eea2004-08-04 19:16:54 +00001398 if (!isalpha((int) *s) && *s != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001399 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001400 for (; *s != '='; s++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001401 if (*s == 0 || (!isalnum(*s) && *s != '_'))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001402 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001403
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001404 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001405}
1406
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001407static int assign(char *s, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001408{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001409 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001410 struct var *vp;
1411
Eric Andersen12de6cf2004-08-04 19:19:10 +00001412 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1413
Matt Kraai69edfec2001-08-06 14:14:18 +00001414 if (!isalpha(*s) && *s != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001415 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001416 for (cp = s; *cp != '='; cp++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001417 if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001418 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001419 vp = lookup(s);
Eric Andersen8401eea2004-08-04 19:16:54 +00001420 nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);
Eric Andersenff9eee42001-06-29 04:57:14 +00001421 if (cf != COPYV)
1422 vp->status &= ~GETCELL;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001423 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001424}
1425
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001426static int checkname(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001427{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001428 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1429
Eric Andersen8401eea2004-08-04 19:16:54 +00001430 if (!isalpha(*cp++) && *(cp - 1) != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001431 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001432 while (*cp)
Eric Andersen8401eea2004-08-04 19:16:54 +00001433 if (!isalnum(*cp++) && *(cp - 1) != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001434 return 0;
1435 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001436}
1437
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001438static void putvlist(int f, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00001439{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001440 struct var *vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001441
1442 for (vp = vlist; vp; vp = vp->next)
Matt Kraai69edfec2001-08-06 14:14:18 +00001443 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001444 if (vp->status & EXPORT)
1445 write(out, "export ", 7);
1446 if (vp->status & RONLY)
1447 write(out, "readonly ", 9);
Eric Andersen8401eea2004-08-04 19:16:54 +00001448 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
Eric Andersenff9eee42001-06-29 04:57:14 +00001449 write(out, "\n", 1);
1450 }
1451}
1452
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001453static int eqname(char *n1, char *n2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001454{
1455 for (; *n1 != '=' && *n1 != 0; n1++)
1456 if (*n2++ != *n1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001457 return 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001458 return *n2 == 0 || *n2 == '=';
Eric Andersenff9eee42001-06-29 04:57:14 +00001459}
1460
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001461static char *findeq(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001462{
1463 while (*cp != '\0' && *cp != '=')
1464 cp++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001465 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001466}
1467
1468/* -------- gmatch.c -------- */
1469/*
1470 * int gmatch(string, pattern)
1471 * char *string, *pattern;
1472 *
1473 * Match a pattern as in sh(1).
1474 */
1475
1476#define CMASK 0377
1477#define QUOTE 0200
1478#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001479#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001480
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001481static int gmatch(char *s, char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001482{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001483 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001484
1485 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001486 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001487 while ((pc = *p++ & CMASK) != '\0') {
1488 sc = *s++ & QMASK;
1489 switch (pc) {
1490 case '[':
1491 if ((p = cclass(p, sc)) == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001492 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001493 break;
1494
1495 case '?':
1496 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001497 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001498 break;
1499
1500 case '*':
1501 s--;
1502 do {
1503 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001504 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001505 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001506 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001507
1508 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001509 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001510 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001511 }
1512 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001513 return *s == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001514}
1515
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001516static char *cclass(char *p, int sub)
Eric Andersenff9eee42001-06-29 04:57:14 +00001517{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001518 int c, d, not, found;
Eric Andersenff9eee42001-06-29 04:57:14 +00001519
1520 if ((not = *p == NOT) != 0)
1521 p++;
1522 found = not;
1523 do {
1524 if (*p == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001525 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001526 c = *p & CMASK;
1527 if (p[1] == '-' && p[2] != ']') {
1528 d = p[2] & CMASK;
1529 p++;
1530 } else
1531 d = c;
1532 if (c == sub || (c <= sub && sub <= d))
1533 found = !not;
1534 } while (*++p != ']');
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001535 return found ? p + 1 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001536}
1537
1538
1539/* -------- area.c -------- */
1540
1541/*
1542 * All memory between (char *)areabot and (char *)(areatop+1) is
1543 * exclusively administered by the area management routines.
1544 * It is assumed that sbrk() and brk() manipulate the high end.
1545 */
1546
1547#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
1548
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001549static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001550{
Mike Frysinger3132e9d2006-06-02 06:30:30 +00001551 brkaddr = xmalloc(AREASIZE);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001552 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +00001553
Eric Andersena68ea1c2006-01-30 22:48:39 +00001554 while ((long) sbrk(0) & ALIGN)
Eric Andersenff9eee42001-06-29 04:57:14 +00001555 sbrk(1);
Eric Andersen8401eea2004-08-04 19:16:54 +00001556 areabot = (struct region *) sbrk(REGSIZE);
Eric Andersenff9eee42001-06-29 04:57:14 +00001557
1558 areabot->next = areabot;
1559 areabot->area = BUSY;
1560 areatop = areabot;
1561 areanxt = areabot;
1562}
1563
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001564char *getcell(unsigned nbytes)
Eric Andersenff9eee42001-06-29 04:57:14 +00001565{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001566 int nregio;
1567 struct region *p, *q;
1568 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001569
1570 if (nbytes == 0) {
1571 puts("getcell(0)");
1572 abort();
Eric Andersen8401eea2004-08-04 19:16:54 +00001573 }
1574 /* silly and defeats the algorithm */
Eric Andersenff9eee42001-06-29 04:57:14 +00001575 /*
1576 * round upwards and add administration area
1577 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001578 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001579 for (p = areanxt;;) {
1580 if (p->area > areanum) {
1581 /*
1582 * merge free cells
1583 */
1584 while ((q = p->next)->area > areanum && q != areanxt)
1585 p->next = q->next;
1586 /*
1587 * exit loop if cell big enough
1588 */
1589 if (q >= p + nregio)
1590 goto found;
1591 }
1592 p = p->next;
1593 if (p == areanxt)
1594 break;
1595 }
1596 i = nregio >= GROWBY ? nregio : GROWBY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001597 p = (struct region *) sbrk(i * REGSIZE);
1598 if (p == (struct region *) -1)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001599 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001600 p--;
1601 if (p != areatop) {
1602 puts("not contig");
Eric Andersen8401eea2004-08-04 19:16:54 +00001603 abort(); /* allocated areas are contiguous */
Eric Andersenff9eee42001-06-29 04:57:14 +00001604 }
1605 q = p + i;
1606 p->next = q;
1607 p->area = FREE;
1608 q->next = areabot;
1609 q->area = BUSY;
1610 areatop = q;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001611 found:
Eric Andersenff9eee42001-06-29 04:57:14 +00001612 /*
1613 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
1614 */
1615 areanxt = p + nregio;
1616 if (areanxt < q) {
1617 /*
1618 * split into requested area and rest
1619 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001620 if (areanxt + 1 > q) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001621 puts("OOM");
Eric Andersen8401eea2004-08-04 19:16:54 +00001622 abort(); /* insufficient space left for admin */
Eric Andersenff9eee42001-06-29 04:57:14 +00001623 }
1624 areanxt->next = q;
1625 areanxt->area = FREE;
1626 p->next = areanxt;
1627 }
1628 p->area = areanum;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001629 return (char *) (p + 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001630}
1631
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001632static void freecell(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001633{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001634 struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001635
Eric Andersen8401eea2004-08-04 19:16:54 +00001636 if ((p = (struct region *) cp) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001637 p--;
1638 if (p < areanxt)
1639 areanxt = p;
1640 p->area = FREE;
1641 }
1642}
1643
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001644static void freearea(int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001645{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001646 struct region *p, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001647
1648 top = areatop;
1649 for (p = areabot; p != top; p = p->next)
1650 if (p->area >= a)
1651 p->area = FREE;
1652}
1653
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001654static void setarea(char *cp, int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001655{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001656 struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001657
Eric Andersen8401eea2004-08-04 19:16:54 +00001658 if ((p = (struct region *) cp) != NULL)
1659 (p - 1)->area = a;
Eric Andersenff9eee42001-06-29 04:57:14 +00001660}
1661
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001662int getarea(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001663{
Eric Andersen8401eea2004-08-04 19:16:54 +00001664 return ((struct region *) cp - 1)->area;
Eric Andersenff9eee42001-06-29 04:57:14 +00001665}
1666
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001667static void garbage(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001668{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001669 struct region *p, *q, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001670
1671 top = areatop;
1672 for (p = areabot; p != top; p = p->next) {
1673 if (p->area > areanum) {
1674 while ((q = p->next)->area > areanum)
1675 p->next = q->next;
1676 areanxt = p;
1677 }
1678 }
1679#ifdef SHRINKBY
1680 if (areatop >= q + SHRINKBY && q->area > areanum) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001681 brk((char *) (q + 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00001682 q->next = areabot;
1683 q->area = BUSY;
1684 areatop = q;
1685 }
1686#endif
1687}
1688
1689/* -------- csyn.c -------- */
1690/*
1691 * shell: syntax (C version)
1692 */
1693
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001694int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001695{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001696 DBGPRINTF7(("YYPARSE: enter...\n"));
1697
Eric Andersen8401eea2004-08-04 19:16:54 +00001698 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001699 peeksym = 0;
1700 yynerrs = 0;
1701 outtree = c_list();
1702 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001703 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001704}
1705
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001706static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001707{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001708 struct op *t, *p;
1709 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001710
1711 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001712
1713 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001714
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001715 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001716
Eric Andersenff9eee42001-06-29 04:57:14 +00001717 if (t != NULL) {
1718 while ((c = yylex(0)) == '|') {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001719 if ((p = command(CONTIN)) == NULL) {
1720 DBGPRINTF8(("PIPELINE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001721 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001722 }
1723
Eric Andersenff9eee42001-06-29 04:57:14 +00001724 if (t->type != TPAREN && t->type != TCOM) {
1725 /* shell statement */
1726 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1727 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001728
Eric Andersenff9eee42001-06-29 04:57:14 +00001729 t = block(TPIPE, t, p, NOWORDS);
1730 }
1731 peeksym = c;
1732 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001733
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001734 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001735 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001736}
1737
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001738static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001739{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001740 struct op *t, *p;
1741 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001742
1743 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001744
1745 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001746
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001747 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001748
Eric Andersenff9eee42001-06-29 04:57:14 +00001749 if (t != NULL) {
1750 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001751 if ((p = pipeline(CONTIN)) == NULL) {
1752 DBGPRINTF8(("ANDOR: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001753 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001754 }
1755
Eric Andersen8401eea2004-08-04 19:16:54 +00001756 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001757 } /* WHILE */
1758
Eric Andersenff9eee42001-06-29 04:57:14 +00001759 peeksym = c;
1760 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001761
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001762 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001763 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001764}
1765
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001766static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001767{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001768 struct op *t, *p;
1769 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001770
1771 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001772
1773 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001774
Eric Andersenff9eee42001-06-29 04:57:14 +00001775 if (t != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001776 if ((peeksym = yylex(0)) == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001777 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001778
Eric Andersen8401eea2004-08-04 19:16:54 +00001779 while ((c = yylex(0)) == ';' || c == '&'
1780 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001781
Eric Andersenff9eee42001-06-29 04:57:14 +00001782 if ((p = andor()) == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001783 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001784
Eric Andersen8401eea2004-08-04 19:16:54 +00001785 if ((peeksym = yylex(0)) == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001786 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001787
Eric Andersenff9eee42001-06-29 04:57:14 +00001788 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001789 } /* WHILE */
1790
Eric Andersenff9eee42001-06-29 04:57:14 +00001791 peeksym = c;
1792 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001793 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001794 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001795 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001796}
1797
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001798static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001799{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001800 struct ioword *iop;
1801 int i;
1802 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001803
1804 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001805
1806 if ((c = yylex(cf)) != '<' && c != '>') {
1807 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001808 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001809 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001810
Eric Andersenff9eee42001-06-29 04:57:14 +00001811 i = yylval.i;
1812 musthave(WORD, 0);
1813 iop = io(iounit, i, yylval.cp);
1814 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001815
Eric Andersenff9eee42001-06-29 04:57:14 +00001816 if (i & IOHERE)
1817 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001818
1819 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001820 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001821}
1822
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001823static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001824{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001825 if ((peeksym = yylex(cf)) != c) {
1826 DBGPRINTF7(("MUSTHAVE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001827 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001828 }
1829
Eric Andersenff9eee42001-06-29 04:57:14 +00001830 peeksym = 0;
1831}
1832
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001833static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001834{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001835 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001836
1837 t = NULL;
1838 for (;;) {
1839 switch (peeksym = yylex(0)) {
1840 case '<':
1841 case '>':
1842 (void) synio(0);
1843 break;
1844
1845 case WORD:
1846 if (t == NULL) {
1847 t = newtp();
1848 t->type = TCOM;
1849 }
1850 peeksym = 0;
1851 word(yylval.cp);
1852 break;
1853
1854 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001855 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001856 }
1857 }
1858}
1859
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001860static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001861{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001862 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001863
1864 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001865
1866 multiline++;
1867 t = c_list();
1868 musthave(mark, 0);
1869 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001870 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001871}
1872
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001873static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001874{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001875 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001876 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001877 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001878
1879 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001880
1881 iosave = iolist;
1882 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001883
Eric Andersenff9eee42001-06-29 04:57:14 +00001884 if (multiline)
1885 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001886
Eric Andersenff9eee42001-06-29 04:57:14 +00001887 while (synio(cf))
1888 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001889
1890 c = yylex(cf);
1891
1892 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001893 default:
1894 peeksym = c;
1895 if ((t = simple()) == NULL) {
1896 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001897 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001898 t = newtp();
1899 t->type = TCOM;
1900 }
1901 break;
1902
1903 case '(':
1904 t = nested(TPAREN, ')');
1905 break;
1906
1907 case '{':
1908 t = nested(TBRACE, '}');
1909 break;
1910
1911 case FOR:
1912 t = newtp();
1913 t->type = TFOR;
1914 musthave(WORD, 0);
1915 startl = 1;
1916 t->str = yylval.cp;
1917 multiline++;
1918 t->words = wordlist();
1919 if ((c = yylex(0)) != '\n' && c != ';')
1920 peeksym = c;
1921 t->left = dogroup(0);
1922 multiline--;
1923 break;
1924
1925 case WHILE:
1926 case UNTIL:
1927 multiline++;
1928 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001929 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001930 t->left = c_list();
1931 t->right = dogroup(1);
1932 t->words = NULL;
1933 multiline--;
1934 break;
1935
1936 case CASE:
1937 t = newtp();
1938 t->type = TCASE;
1939 musthave(WORD, 0);
1940 t->str = yylval.cp;
1941 startl++;
1942 multiline++;
1943 musthave(IN, CONTIN);
1944 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001945
Eric Andersenff9eee42001-06-29 04:57:14 +00001946 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001947
Eric Andersenff9eee42001-06-29 04:57:14 +00001948 musthave(ESAC, 0);
1949 multiline--;
1950 break;
1951
1952 case IF:
1953 multiline++;
1954 t = newtp();
1955 t->type = TIF;
1956 t->left = c_list();
1957 t->right = thenpart();
1958 musthave(FI, 0);
1959 multiline--;
1960 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001961
1962 case DOT:
1963 t = newtp();
1964 t->type = TDOT;
1965
1966 musthave(WORD, 0); /* gets name of file */
1967 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1968
1969 word(yylval.cp); /* add word to wdlist */
1970 word(NOWORD); /* terminate wdlist */
1971 t->words = copyw(); /* dup wdlist */
1972 break;
1973
Eric Andersenff9eee42001-06-29 04:57:14 +00001974 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001975
Eric Andersen8401eea2004-08-04 19:16:54 +00001976 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001977
Eric Andersenff9eee42001-06-29 04:57:14 +00001978 t = namelist(t);
1979 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001980
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001981 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001982
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001983 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001984}
1985
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001986static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001987{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001988 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001989
1990 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
1991
1992 multiline++;
1993 t = c_list();
1994 multiline--;
1995 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001996 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001997 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001998}
1999
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002000static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00002001{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002002 int c;
2003 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002004
2005 c = yylex(CONTIN);
2006 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002007 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002008 if (c != DO)
2009 SYNTAXERR;
2010 mylist = c_list();
2011 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002012 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002013}
2014
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002015static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002016{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002017 int c;
2018 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002019
2020 if ((c = yylex(0)) != THEN) {
2021 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002022 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002023 }
2024 t = newtp();
2025 t->type = 0;
2026 t->left = c_list();
2027 if (t->left == NULL)
2028 SYNTAXERR;
2029 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002030 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002031}
2032
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002033static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002034{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002035 int c;
2036 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002037
2038 switch (c = yylex(0)) {
2039 case ELSE:
2040 if ((t = c_list()) == NULL)
2041 SYNTAXERR;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002042 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002043
2044 case ELIF:
2045 t = newtp();
2046 t->type = TELIF;
2047 t->left = c_list();
2048 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002049 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002050
2051 default:
2052 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002053 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002054 }
2055}
2056
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002057static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002058{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002059 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002060
2061 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002062 while ((peeksym = yylex(CONTIN)) != ESAC) {
2063 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00002064 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00002065 }
2066
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002067 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002068 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002069}
2070
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002071static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002072{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002073 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002074
2075 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002076
2077 t = newtp();
2078 t->type = TPAT;
2079 t->words = pattern();
2080 musthave(')', 0);
2081 t->left = c_list();
2082 if ((peeksym = yylex(CONTIN)) != ESAC)
2083 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002084
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002085 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002086
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002087 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002088}
2089
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002090static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002091{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002092 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00002093
2094 cf = CONTIN;
2095 do {
2096 musthave(WORD, cf);
2097 word(yylval.cp);
2098 cf = 0;
2099 } while ((c = yylex(0)) == '|');
2100 peeksym = c;
2101 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002102
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002103 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002104}
2105
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002106static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002107{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002108 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002109
2110 if ((c = yylex(0)) != IN) {
2111 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002112 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002113 }
2114 startl = 0;
2115 while ((c = yylex(0)) == WORD)
2116 word(yylval.cp);
2117 word(NOWORD);
2118 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002119 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002120}
2121
2122/*
2123 * supporting functions
2124 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002125static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00002126{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002127 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002128
Eric Andersenff9eee42001-06-29 04:57:14 +00002129 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002130 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002131 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002132 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002133
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002134 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00002135}
2136
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002137static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002138{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002139 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002140
2141 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002142
2143 t = newtp();
2144 t->type = type;
2145 t->left = t1;
2146 t->right = t2;
2147 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002148
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002149 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002150 t2));
2151
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002152 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002153}
2154
Eric Andersen12de6cf2004-08-04 19:19:10 +00002155/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002156static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002157{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002158 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002159
2160 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002161
2162 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002163 if (strcmp(rp->r_name, n) == 0) {
2164 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002165 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002166 }
2167
2168 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002169 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002170}
2171
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002172static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002173{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002174 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002175
Eric Andersen8401eea2004-08-04 19:16:54 +00002176 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002177 t->type = 0;
2178 t->words = NULL;
2179 t->ioact = NULL;
2180 t->left = NULL;
2181 t->right = NULL;
2182 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002183
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002184 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002185
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002186 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002187}
2188
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002189static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002190{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002191
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002192 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002193 T_CMD_NAMES[t->type], iolist));
2194
Eric Andersenff9eee42001-06-29 04:57:14 +00002195 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002196 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002197 t->ioact = copyio();
2198 } else
2199 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002200
Eric Andersenff9eee42001-06-29 04:57:14 +00002201 if (t->type != TCOM) {
2202 if (t->type != TPAREN && t->ioact != NULL) {
2203 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2204 t->ioact = t->left->ioact;
2205 t->left->ioact = NULL;
2206 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002207 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002208 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002209
Eric Andersenff9eee42001-06-29 04:57:14 +00002210 word(NOWORD);
2211 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002212
2213
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002214 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002215}
2216
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002217static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002218{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002219 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002220
2221 wd = getwords(wdlist);
2222 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002223 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002224}
2225
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002226static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002227{
2228 wdlist = addword(cp, wdlist);
2229}
2230
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002231static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002232{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002233 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002234
2235 iop = (struct ioword **) getwords(iolist);
2236 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002237 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002238}
2239
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002240static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002241{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002242 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002243
2244 iop = (struct ioword *) tree(sizeof(*iop));
2245 iop->io_unit = u;
2246 iop->io_flag = f;
2247 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002248 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002249 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002250}
2251
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002252static void zzerr(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002253{
2254 yyerror("syntax error");
2255}
2256
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002257static void yyerror(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00002258{
2259 yynerrs++;
2260 if (interactive && e.iop <= iostack) {
2261 multiline = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002262 while (eofc() == 0 && yylex(0) != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002263 }
2264 err(s);
2265 fail();
2266}
2267
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002268static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002269{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002270 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002271 int atstart;
2272
2273 if ((c = peeksym) > 0) {
2274 peeksym = 0;
2275 if (c == '\n')
2276 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002277 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002278 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002279
2280
Eric Andersenff9eee42001-06-29 04:57:14 +00002281 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002282 atstart = startl;
2283 startl = 0;
2284 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002285 e.linep = line;
2286
2287/* MALAMO */
2288 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002289
Eric Andersen8401eea2004-08-04 19:16:54 +00002290 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002291 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2292 ;
2293
Eric Andersenff9eee42001-06-29 04:57:14 +00002294 switch (c) {
2295 default:
2296 if (any(c, "0123456789")) {
2297 unget(c1 = my_getc(0));
2298 if (c1 == '<' || c1 == '>') {
2299 iounit = c - '0';
2300 goto loop;
2301 }
2302 *e.linep++ = c;
2303 c = c1;
2304 }
2305 break;
2306
Eric Andersen12de6cf2004-08-04 19:19:10 +00002307 case '#': /* Comment, skip to next newline or End-of-string */
Eric Andersen8401eea2004-08-04 19:16:54 +00002308 while ((c = my_getc(0)) != 0 && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002309 unget(c);
2310 goto loop;
2311
2312 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002313 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002314 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002315
2316 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002317 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002318 *e.linep++ = c;
2319 if ((c = my_getc(0)) == '{') {
2320 if ((c = collect(c, '}')) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002321 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002322 goto pack;
2323 }
2324 break;
2325
2326 case '`':
2327 case '\'':
2328 case '"':
2329 if ((c = collect(c, c)) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002330 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002331 goto pack;
2332
2333 case '|':
2334 case '&':
2335 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002336 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002337 /* If more chars process them, else return NULL char */
2338 if ((c1 = dual(c)) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002339 return c1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002340 else
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002341 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002342
Eric Andersenff9eee42001-06-29 04:57:14 +00002343 case '^':
2344 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002345 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002346 case '>':
2347 case '<':
2348 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002349 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002350
2351 case '\n':
2352 nlseen++;
2353 gethere();
2354 startl = 1;
2355 if (multiline || cf & CONTIN) {
2356 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002357#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002358 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002359#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002360 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002361#endif
2362 }
2363 if (cf & CONTIN)
2364 goto loop;
2365 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002366 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002367
2368 case '(':
2369 case ')':
2370 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002371 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002372 }
2373
2374 unget(c);
2375
Eric Andersen8401eea2004-08-04 19:16:54 +00002376 pack:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002377 while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002378 if (e.linep >= elinep)
2379 err("word too long");
2380 else
2381 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002382 };
2383
Eric Andersenff9eee42001-06-29 04:57:14 +00002384 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002385
Eric Andersen8401eea2004-08-04 19:16:54 +00002386 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002387 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002388
Eric Andersenff9eee42001-06-29 04:57:14 +00002389 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002390
Eric Andersen8401eea2004-08-04 19:16:54 +00002391 if (atstart && (c = rlookup(line)) != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002392 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002393 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002394 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002395
Eric Andersenff9eee42001-06-29 04:57:14 +00002396 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002397 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002398}
2399
Eric Andersen12de6cf2004-08-04 19:19:10 +00002400
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002401static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002402{
2403 char s[2];
2404
Eric Andersen12de6cf2004-08-04 19:19:10 +00002405 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2406
Eric Andersenff9eee42001-06-29 04:57:14 +00002407 *e.linep++ = c;
2408 while ((c = my_getc(c1)) != c1) {
2409 if (c == 0) {
2410 unget(c);
2411 s[0] = c1;
2412 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002413 prs("no closing ");
2414 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002415 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002416 }
2417 if (interactive && c == '\n' && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002418#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002419 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002420#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002421 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002422#endif
2423 }
2424 *e.linep++ = c;
2425 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002426
Eric Andersenff9eee42001-06-29 04:57:14 +00002427 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002428
2429 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2430
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002431 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002432}
2433
Eric Andersen12de6cf2004-08-04 19:19:10 +00002434/* "multiline commands" helper func */
2435/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002436static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002437{
2438 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002439 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002440
Eric Andersen12de6cf2004-08-04 19:19:10 +00002441 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2442
2443 *cp++ = c; /* c is the given "peek" char */
2444 *cp++ = my_getc(0); /* get next char of input */
2445 *cp = 0; /* add EOS marker */
2446
2447 c = rlookup(s); /* see if 2 chars form a shell multiline */
2448 if (c == 0)
2449 unget(*--cp); /* String is not a shell multiline, put peek char back */
2450
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002451 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002452}
2453
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002454static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002455{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002456 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002457
2458 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002459
2460 c = my_getc(0);
2461 if (c == '>' || c == '<') {
2462 if (c != ec)
2463 zzerr();
Eric Andersen8401eea2004-08-04 19:16:54 +00002464 yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002465 c = my_getc(0);
2466 } else
Eric Andersen8401eea2004-08-04 19:16:54 +00002467 yylval.i = ec == '>' ? IOWRITE : IOREAD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002468 if (c != '&' || yylval.i == IOHERE)
2469 unget(c);
2470 else
2471 yylval.i |= IODUP;
2472}
2473
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002474static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002475{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002476 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002477
2478 if ((t = getcell(size)) == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002479 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002480 prs("command line too complicated\n");
2481 fail();
2482 /* NOTREACHED */
2483 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002484 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002485}
2486
2487/* VARARGS1 */
2488/* ARGSUSED */
2489
2490/* -------- exec.c -------- */
2491
2492/*
2493 * execute tree
2494 */
2495
2496
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002497static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002498{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002499 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002500 volatile int i, rv, a;
2501 char *cp, **wp, **wp2;
2502 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002503 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002504 struct brkcon bc;
2505
2506#if __GNUC__
2507 /* Avoid longjmp clobbering */
2508 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002509#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002510
Eric Andersen12de6cf2004-08-04 19:19:10 +00002511 if (t == NULL) {
2512 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002513 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002514 }
2515
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002516 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002517 t->type, T_CMD_NAMES[t->type],
2518 ((t->words == NULL) ? "NULL" : t->words[0])));
2519
Eric Andersenff9eee42001-06-29 04:57:14 +00002520 rv = 0;
2521 a = areanum++;
2522 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002523 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2524 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002525
Eric Andersen8401eea2004-08-04 19:16:54 +00002526 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002527 case TDOT:
2528 DBGPRINTF3(("EXECUTE: TDOT\n"));
2529
2530 outtree_save = outtree;
2531
2532 newfile(evalstr(t->words[0], DOALL));
2533
2534 t->left = dowholefile(TLIST, 0);
2535 t->right = NULL;
2536
2537 outtree = outtree_save;
2538
2539 if (t->left)
2540 rv = execute(t->left, pin, pout, 0);
2541 if (t->right)
2542 rv = execute(t->right, pin, pout, 0);
2543 break;
2544
Eric Andersenff9eee42001-06-29 04:57:14 +00002545 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002546 rv = execute(t->left, pin, pout, 0);
2547 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002548
Eric Andersenff9eee42001-06-29 04:57:14 +00002549 case TCOM:
Eric Andersen1c039232001-07-07 00:05:55 +00002550 {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002551 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002552 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002553 break;
2554
2555 case TPIPE:
2556 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002557 int pv[2];
2558
2559 if ((rv = openpipe(pv)) < 0)
2560 break;
2561 pv[0] = remap(pv[0]);
2562 pv[1] = remap(pv[1]);
2563 (void) execute(t->left, pin, pv, 0);
2564 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002565 }
2566 break;
2567
2568 case TLIST:
2569 (void) execute(t->left, pin, pout, 0);
2570 rv = execute(t->right, pin, pout, 0);
2571 break;
2572
2573 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002574 {
2575 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002576
Eric Andersen12de6cf2004-08-04 19:19:10 +00002577 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2578
Eric Andersen8401eea2004-08-04 19:16:54 +00002579 i = vfork();
2580 if (i != 0) {
2581 interactive = hinteractive;
2582 if (i != -1) {
2583 setval(lookup("!"), putn(i));
2584 if (pin != NULL)
2585 closepipe(pin);
2586 if (interactive) {
2587 prs(putn(i));
2588 prs("\n");
2589 }
2590 } else
2591 rv = -1;
2592 setstatus(rv);
2593 } else {
2594 signal(SIGINT, SIG_IGN);
2595 signal(SIGQUIT, SIG_IGN);
2596 if (interactive)
2597 signal(SIGTERM, SIG_DFL);
2598 interactive = 0;
2599 if (pin == NULL) {
2600 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002601 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002602 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002603 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002604 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002605 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002606 break;
2607
2608 case TOR:
2609 case TAND:
2610 rv = execute(t->left, pin, pout, 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00002611 if ((t1 = t->right) != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002612 rv = execute(t1, pin, pout, 0);
2613 break;
2614
2615 case TFOR:
2616 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002617 wp = dolv + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002618 if ((i = dolc) < 0)
2619 i = 0;
2620 } else {
2621 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002622 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002623 }
2624 vp = lookup(t->str);
2625 while (setjmp(bc.brkpt))
2626 if (isbreak)
2627 goto broken;
2628 brkset(&bc);
2629 for (t1 = t->left; i-- && *wp != NULL;) {
2630 setval(vp, *wp++);
2631 rv = execute(t1, pin, pout, 0);
2632 }
2633 brklist = brklist->nextlev;
2634 break;
2635
2636 case TWHILE:
2637 case TUNTIL:
2638 while (setjmp(bc.brkpt))
2639 if (isbreak)
2640 goto broken;
2641 brkset(&bc);
2642 t1 = t->left;
2643 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2644 rv = execute(t->right, pin, pout, 0);
2645 brklist = brklist->nextlev;
2646 break;
2647
2648 case TIF:
2649 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002650 if (t->right != NULL) {
2651 rv = !execute(t->left, pin, pout, 0) ?
2652 execute(t->right->left, pin, pout, 0) :
2653 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002654 }
2655 break;
2656
2657 case TCASE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002658 if ((cp = evalstr(t->str, DOSUB | DOTRIM)) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002659 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002660
2661 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2662 ((t->str == NULL) ? "NULL" : t->str),
2663 ((cp == NULL) ? "NULL" : cp)));
2664
2665 if ((t1 = findcase(t->left, cp)) != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002666 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002667 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002668 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002669 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002670 break;
2671
2672 case TBRACE:
2673/*
2674 if (iopp = t->ioact)
2675 while (*iopp)
2676 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2677 rv = -1;
2678 break;
2679 }
2680*/
2681 if (rv >= 0 && (t1 = t->left))
2682 rv = execute(t1, pin, pout, 0);
2683 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002684
2685 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002686
Eric Andersen8401eea2004-08-04 19:16:54 +00002687 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002688 t->words = wp2;
2689 isbreak = 0;
2690 freehere(areanum);
2691 freearea(areanum);
2692 areanum = a;
2693 if (interactive && intr) {
2694 closeall();
2695 fail();
2696 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002697
Eric Andersenff9eee42001-06-29 04:57:14 +00002698 if ((i = trapset) != 0) {
2699 trapset = 0;
2700 runtrap(i);
2701 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002702
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002703 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002704 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002705}
2706
2707static int
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002708forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002709{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002710 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002711 int i, rv;
Eric Andersen8401eea2004-08-04 19:16:54 +00002712 int (*shcom) (struct op *) = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002713 int f;
Eric Andersenff9eee42001-06-29 04:57:14 +00002714 char *cp = NULL;
2715 struct ioword **iopp;
2716 int resetsig;
2717 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002718 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002719
2720 int *hpin = pin;
2721 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002722 char *hwp;
2723 int hinteractive;
2724 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002725 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002726 int hexecflg;
2727
2728#if __GNUC__
2729 /* Avoid longjmp clobbering */
2730 (void) &pin;
2731 (void) &pout;
2732 (void) &wp;
2733 (void) &shcom;
2734 (void) &cp;
2735 (void) &resetsig;
2736 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002737#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002738
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002739 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002740 pout, act));
2741 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2742 ((t->words == NULL) ? "NULL" : t->words[0])));
2743
Eric Andersenff9eee42001-06-29 04:57:14 +00002744 owp = wp;
2745 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002746 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002747 if (t->type == TCOM) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002748 while ((cp = *wp++) != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002749 cp = *wp;
2750
2751 /* strip all initial assignments */
2752 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002753 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002754 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002755 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002756 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002757 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002758
Eric Andersenff9eee42001-06-29 04:57:14 +00002759 if (cp == NULL && t->ioact == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002760 while ((cp = *owp++) != NULL && assign(cp, COPYV));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002761 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002762 return setstatus(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002763 } else if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002764 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002765 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002766 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002767
Eric Andersenff9eee42001-06-29 04:57:14 +00002768 t->words = wp;
2769 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002770
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002771 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002772 f & FEXEC, owp));
2773
2774 if (shcom == NULL && (f & FEXEC) == 0) {
2775 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002776 hpin = pin;
2777 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002778 hwp = *wp;
2779 hinteractive = interactive;
2780 hintr = intr;
2781 hbrklist = brklist;
2782 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002783
Eric Andersen12de6cf2004-08-04 19:19:10 +00002784 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2785
2786 newpid = vfork();
2787
2788 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002789 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002790 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002791 }
2792
2793
2794 if (newpid > 0) { /* Parent */
2795
2796 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002797 pin = hpin;
2798 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002799 *wp = hwp;
2800 interactive = hinteractive;
2801 intr = hintr;
2802 brklist = hbrklist;
2803 execflg = hexecflg;
2804
Eric Andersen12de6cf2004-08-04 19:19:10 +00002805/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002806 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002807 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002808*/
2809
Eric Andersenff9eee42001-06-29 04:57:14 +00002810 if (pin != NULL)
2811 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002812
2813 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002814 }
2815
Eric Andersen12de6cf2004-08-04 19:19:10 +00002816 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002817 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002818
Eric Andersenff9eee42001-06-29 04:57:14 +00002819 if (interactive) {
2820 signal(SIGINT, SIG_IGN);
2821 signal(SIGQUIT, SIG_IGN);
2822 resetsig = 1;
2823 }
2824 interactive = 0;
2825 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002826 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002827 brklist = 0;
2828 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002829 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002830
2831
Eric Andersenff9eee42001-06-29 04:57:14 +00002832 if (owp != NULL)
2833 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2834 if (shcom == NULL)
2835 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002836
Eric Andersenff9eee42001-06-29 04:57:14 +00002837#ifdef COMPIPE
2838 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2839 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002840 if (forked)
2841 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002842 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002843 }
2844#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002845
Eric Andersenff9eee42001-06-29 04:57:14 +00002846 if (pin != NULL) {
2847 dup2(pin[0], 0);
2848 closepipe(pin);
2849 }
2850 if (pout != NULL) {
2851 dup2(pout[1], 1);
2852 closepipe(pout);
2853 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002854
Eric Andersenff9eee42001-06-29 04:57:14 +00002855 if ((iopp = t->ioact) != NULL) {
2856 if (shcom != NULL && shcom != doexec) {
2857 prs(cp);
2858 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002859 if (forked)
2860 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002861 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002862 }
2863 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002864 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2865 if (forked)
2866 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002867 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002868 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002869 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002870
2871 if (shcom) {
2872 i = setstatus((*shcom) (t));
2873 if (forked)
2874 _exit(i);
2875 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002876 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002877 }
2878
Eric Andersenff9eee42001-06-29 04:57:14 +00002879 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002880 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002881 close(i);
2882 if (resetsig) {
2883 signal(SIGINT, SIG_DFL);
2884 signal(SIGQUIT, SIG_DFL);
2885 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002886
Eric Andersen12de6cf2004-08-04 19:19:10 +00002887 if (t->type == TPAREN)
2888 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2889 if (wp[0] == NULL)
2890 _exit(0);
2891
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002892 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002893 prs(wp[0]);
2894 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002895 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002896 if (!execflg)
2897 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002898
2899 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2900
Eric Andersenff9eee42001-06-29 04:57:14 +00002901 leave();
2902 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002903 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002904}
2905
2906/*
2907 * 0< 1> are ignored as required
2908 * within pipelines.
2909 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002910static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002911{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002912 int u = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002913 char *cp = NULL, *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002914
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002915 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002916 pipein, pipeout));
2917
Eric Andersenff9eee42001-06-29 04:57:14 +00002918 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002919 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002920
Eric Andersenff9eee42001-06-29 04:57:14 +00002921 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002922 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002923
Eric Andersenff9eee42001-06-29 04:57:14 +00002924 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002925 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002926
Eric Andersen8401eea2004-08-04 19:16:54 +00002927 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002928 if ((iop->io_flag & IOHERE) == 0) {
2929 cp = iop->io_name;
Eric Andersen8401eea2004-08-04 19:16:54 +00002930 if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002931 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002932 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002933
Eric Andersenff9eee42001-06-29 04:57:14 +00002934 if (iop->io_flag & IODUP) {
2935 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2936 prs(cp);
2937 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002938 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002939 }
2940 if (*cp == '-')
2941 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002942 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002943 }
2944 switch (iop->io_flag) {
2945 case IOREAD:
2946 u = open(cp, 0);
2947 break;
2948
2949 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002950 case IOHERE | IOXHERE:
2951 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002952 cp = "here file";
2953 break;
2954
Eric Andersen8401eea2004-08-04 19:16:54 +00002955 case IOWRITE | IOCAT:
Eric Andersenff9eee42001-06-29 04:57:14 +00002956 if ((u = open(cp, 1)) >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002957 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002958 break;
2959 }
2960 case IOWRITE:
2961 u = creat(cp, 0666);
2962 break;
2963
2964 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002965 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002966 break;
2967
2968 case IOCLOSE:
2969 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002970 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002971 }
2972 if (u < 0) {
2973 prs(cp);
2974 prs(": cannot ");
2975 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002976 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002977 } else {
2978 if (u != iop->io_unit) {
2979 dup2(u, iop->io_unit);
2980 close(u);
2981 }
2982 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002983 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002984}
2985
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002986static void echo(char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002987{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002988 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00002989
2990 prs("+");
Eric Andersen8401eea2004-08-04 19:16:54 +00002991 for (i = 0; wp[i]; i++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002992 if (i)
2993 prs(" ");
2994 prs(wp[i]);
2995 }
2996 prs("\n");
2997}
2998
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002999static struct op **find1case(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003000{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003001 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003002 struct op **tp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003003 char **wp, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003004
Eric Andersen12de6cf2004-08-04 19:19:10 +00003005
3006 if (t == NULL) {
3007 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003008 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003009 }
3010
3011 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
3012 T_CMD_NAMES[t->type]));
3013
Eric Andersenff9eee42001-06-29 04:57:14 +00003014 if (t->type == TLIST) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003015 if ((tp = find1case(t->left, w)) != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003016 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003017 return tp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003018 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003019 t1 = t->right; /* TPAT */
Eric Andersenff9eee42001-06-29 04:57:14 +00003020 } else
3021 t1 = t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003022
Eric Andersenff9eee42001-06-29 04:57:14 +00003023 for (wp = t1->words; *wp;)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003024 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003025 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003026 &t1->left));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003027 return &t1->left;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003028 }
3029
3030 DBGPRINTF(("FIND1CASE: returning NULL\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003031 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003032}
3033
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003034static struct op *findcase(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003035{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003036 struct op **tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003037
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003038 tp = find1case(t, w);
3039 return tp != NULL ? *tp : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003040}
3041
3042/*
3043 * Enter a new loop level (marked for break/continue).
3044 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003045static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00003046{
3047 bc->nextlev = brklist;
3048 brklist = bc;
3049}
3050
3051/*
3052 * Wait for the last process created.
3053 * Print a message for each process found
3054 * that was killed by a signal.
3055 * Ignore interrupt signals while waiting
3056 * unless `canintr' is true.
3057 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003058static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00003059{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003060 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003061 int s;
3062 int oheedint = heedint;
3063
3064 heedint = 0;
3065 rv = 0;
3066 do {
3067 pid = wait(&s);
3068 if (pid == -1) {
3069 if (errno != EINTR || canintr)
3070 break;
3071 } else {
3072 if ((rv = WAITSIG(s)) != 0) {
3073 if (rv < NSIGNAL) {
3074 if (signame[rv] != NULL) {
3075 if (pid != lastpid) {
3076 prn(pid);
3077 prs(": ");
3078 }
3079 prs(signame[rv]);
3080 }
3081 } else {
3082 if (pid != lastpid) {
3083 prn(pid);
3084 prs(": ");
3085 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003086 prs("Signal ");
3087 prn(rv);
3088 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003089 }
3090 if (WAITCORE(s))
3091 prs(" - core dumped");
3092 if (rv >= NSIGNAL || signame[rv])
3093 prs("\n");
3094 rv = -1;
3095 } else
3096 rv = WAITVAL(s);
3097 }
3098 } while (pid != lastpid);
3099 heedint = oheedint;
3100 if (intr) {
3101 if (interactive) {
3102 if (canintr)
3103 intr = 0;
3104 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003105 if (exstat == 0)
3106 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003107 onintr(0);
3108 }
3109 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003110 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003111}
3112
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003113static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003114{
3115 exstat = s;
3116 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003117 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003118}
3119
3120/*
3121 * PATH-searching interface to execve.
3122 * If getenv("PATH") were kept up-to-date,
3123 * execvp might be used.
3124 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003125static char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003126{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003127 int i;
3128 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003129 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003130 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003131
Rob Landleya299efb2006-08-10 21:46:43 +00003132 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
3133 optind = 1;
3134 if (find_applet_by_name(name)) {
3135 /* We have to exec here since we vforked. Running
3136 * run_applet_by_name() won't work and bad things
3137 * will happen. */
3138 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
3139 }
Eric Andersen1c039232001-07-07 00:05:55 +00003140 }
Eric Andersen1c039232001-07-07 00:05:55 +00003141
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003142 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003143
Eric Andersen8401eea2004-08-04 19:16:54 +00003144 sp = any('/', c) ? "" : path->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00003145 asis = *sp == '\0';
3146 while (asis || *sp != '\0') {
3147 asis = 0;
3148 tp = e.linep;
3149 for (; *sp != '\0'; tp++)
3150 if ((*tp = *sp++) == ':') {
3151 asis = *sp == '\0';
3152 break;
3153 }
3154 if (tp != e.linep)
3155 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003156 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003157
Eric Andersen12de6cf2004-08-04 19:19:10 +00003158 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3159
Eric Andersenff9eee42001-06-29 04:57:14 +00003160 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003161
Eric Andersenff9eee42001-06-29 04:57:14 +00003162 switch (errno) {
3163 case ENOEXEC:
3164 *v = e.linep;
3165 tp = *--v;
3166 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003167 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003168 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003169 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003170
3171 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003172 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003173
3174 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003175 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003176
3177 case EACCES:
3178 eacces++;
3179 break;
3180 }
3181 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003182 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003183}
3184
3185/*
3186 * Run the command produced by generator `f'
3187 * applied to stream `arg'.
3188 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003189static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003190{
3191 struct op *otree;
3192 struct wdblock *swdlist;
3193 struct wdblock *siolist;
3194 jmp_buf ev, rt;
3195 xint *ofail;
3196 int rv;
3197
3198#if __GNUC__
3199 /* Avoid longjmp clobbering */
3200 (void) &rv;
3201#endif
3202
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003203 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003204 areanum, outtree, failpt));
3205
Eric Andersenff9eee42001-06-29 04:57:14 +00003206 areanum++;
3207 swdlist = wdlist;
3208 siolist = iolist;
3209 otree = outtree;
3210 ofail = failpt;
3211 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003212
Eric Andersenff9eee42001-06-29 04:57:14 +00003213 if (newenv(setjmp(errpt = ev)) == 0) {
3214 wdlist = 0;
3215 iolist = 0;
3216 pushio(argp, f);
3217 e.iobase = e.iop;
3218 yynerrs = 0;
3219 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
3220 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3221 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003222 } else {
3223 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003224 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003225
Eric Andersenff9eee42001-06-29 04:57:14 +00003226 wdlist = swdlist;
3227 iolist = siolist;
3228 failpt = ofail;
3229 outtree = otree;
3230 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003231
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003232 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003233}
3234
3235/* -------- do.c -------- */
3236
3237/*
3238 * built-in commands: doX
3239 */
3240
Eric Andersen8401eea2004-08-04 19:16:54 +00003241static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003242{
3243 int col;
3244 const struct builtincmd *x;
3245
3246 printf("\nBuilt-in commands:\n");
3247 printf("-------------------\n");
3248
Eric Andersen8401eea2004-08-04 19:16:54 +00003249 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003250 if (!x->name)
3251 continue;
3252 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3253 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003254 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003255 col = 0;
3256 }
3257 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003258#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003259 {
3260 int i;
3261 const struct BB_applet *applet;
3262 extern const struct BB_applet applets[];
3263 extern const size_t NUM_APPLETS;
3264
Eric Andersen8401eea2004-08-04 19:16:54 +00003265 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003266 if (!applet->name)
3267 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003268
Eric Andersen8401eea2004-08-04 19:16:54 +00003269 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003270 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003271 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003272 col = 0;
3273 }
3274 }
3275 }
3276#endif
3277 printf("\n\n");
3278 return EXIT_SUCCESS;
3279}
3280
3281
3282
Eric Andersen8401eea2004-08-04 19:16:54 +00003283static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003284{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003285 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003286}
3287
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003288static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003289{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003290 char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003291
3292 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
3293 er = ": no home directory";
Eric Andersen8401eea2004-08-04 19:16:54 +00003294 else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003295 er = ": bad directory";
3296 else
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003297 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003298 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003299 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003300 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003301}
3302
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003303static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003304{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003305 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003306
Eric Andersen8401eea2004-08-04 19:16:54 +00003307 n = t->words[1] ? getn(t->words[1]) : 1;
3308 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003309 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003310 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003311 }
3312 dolv[n] = dolv[0];
3313 dolv += n;
3314 dolc -= n;
3315 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003316 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003317}
3318
3319/*
3320 * execute login and newgrp directly
3321 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003322static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003323{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003324 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003325
3326 if (interactive) {
3327 signal(SIGINT, SIG_DFL);
3328 signal(SIGQUIT, SIG_DFL);
3329 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003330 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003331 prs(t->words[0]);
3332 prs(": ");
3333 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003334 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003335}
3336
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003337static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003338{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003339 int i, n;
3340 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003341
3342 if ((cp = t->words[1]) == NULL) {
3343 i = umask(0);
3344 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003345 for (n = 3 * 4; (n -= 3) >= 0;)
3346 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003347 putc('\n', stderr);
3348 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003349 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3350 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003351 umask(n);
3352 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003353 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003354}
3355
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003356static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003357{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003358 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003359 jmp_buf ex;
3360 xint *ofail;
3361
3362 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003363 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003364 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003365 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003366 execflg = 1;
3367 ofail = failpt;
3368 if (setjmp(failpt = ex) == 0)
3369 execute(t, NOPIPE, NOPIPE, FEXEC);
3370 failpt = ofail;
3371 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003372 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003373}
3374
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003375static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003376{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003377 int i;
3378 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003379 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003380 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003381
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003382 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 +00003383
3384 if ((cp = t->words[1]) == NULL) {
3385 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003386 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003387 } else {
3388 DBGPRINTF(("DODOT: cp is %s\n", cp));
3389 }
3390
Eric Andersen8401eea2004-08-04 19:16:54 +00003391 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003392
3393 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3394 ((sp == NULL) ? "NULL" : sp),
3395 ((e.linep == NULL) ? "NULL" : e.linep)));
3396
Eric Andersenff9eee42001-06-29 04:57:14 +00003397 while (*sp) {
3398 tp = e.linep;
3399 while (*sp && (*tp = *sp++) != ':')
3400 tp++;
3401 if (tp != e.linep)
3402 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003403
Eric Andersen8401eea2004-08-04 19:16:54 +00003404 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003405
3406 /* Original code */
Eric Andersenff9eee42001-06-29 04:57:14 +00003407 if ((i = open(e.linep, 0)) >= 0) {
3408 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003409 maltmp = remap(i);
3410 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3411
3412 next(maltmp); /* Basically a PUSHIO */
3413
3414 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3415
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003416 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003417 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003418
3419 } /* While */
3420
Eric Andersenff9eee42001-06-29 04:57:14 +00003421 prs(cp);
3422 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003423
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003424 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003425}
3426
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003427static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003428{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003429 int i;
3430 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003431
3432 if ((cp = t->words[1]) != NULL) {
3433 i = getn(cp);
3434 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003435 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003436 } else
3437 i = -1;
3438 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003439 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003440}
3441
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003442static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003443{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003444 char *cp, **wp;
3445 int nb = 0;
3446 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003447
3448 if (t->words[1] == NULL) {
3449 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003450 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003451 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003452 for (wp = t->words + 1; *wp; wp++) {
3453 for (cp = e.linep; !nl && cp < elinep - 1; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003454 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003455 (nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))
Eric Andersenff9eee42001-06-29 04:57:14 +00003456 break;
3457 *cp = 0;
3458 if (nb <= 0)
3459 break;
3460 setval(lookup(*wp), e.linep);
3461 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003462 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003463}
3464
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003465static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003466{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003467 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003468}
3469
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003470static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003471{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003472 int n, i;
3473 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003474
3475 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003476 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003477 if (trap[i]) {
3478 prn(i);
3479 prs(": ");
3480 prs(trap[i]);
3481 prs("\n");
3482 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003483 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003484 }
3485 resetsig = isdigit(*t->words[1]);
3486 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3487 n = getsig(t->words[i]);
3488 freecell(trap[n]);
3489 trap[n] = 0;
3490 if (!resetsig) {
3491 if (*t->words[1] != '\0') {
3492 trap[n] = strsave(t->words[1], 0);
3493 setsig(n, sig);
3494 } else
3495 setsig(n, SIG_IGN);
3496 } else {
3497 if (interactive)
3498 if (n == SIGINT)
3499 setsig(n, onintr);
3500 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003501 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003502 else
3503 setsig(n, SIG_DFL);
3504 }
3505 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003506 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003507}
3508
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003509static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003510{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003511 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003512
3513 if ((n = getn(s)) < 0 || n > _NSIG) {
3514 err("trap: bad signal number");
3515 n = 0;
3516 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003517 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003518}
3519
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003520static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003521{
3522 if (n == 0)
3523 return;
3524 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3525 ourtrap[n] = 1;
3526 signal(n, f);
3527 }
3528}
3529
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003530static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003531{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003532 char *s;
3533 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003534
3535 s = as;
3536 m = 1;
3537 if (*s == '-') {
3538 m = -1;
3539 s++;
3540 }
3541 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003542 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003543 if (*s) {
3544 prs(as);
3545 err(": bad number");
3546 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003547 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003548}
3549
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003550static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003551{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003552 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003553}
3554
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003555static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003556{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003557 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003558}
3559
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003560static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003561{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003562 struct brkcon *bc;
3563 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003564
Eric Andersen8401eea2004-08-04 19:16:54 +00003565 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003566 if (nl <= 0)
3567 nl = 999;
3568 do {
3569 if ((bc = brklist) == NULL)
3570 break;
3571 brklist = bc->nextlev;
3572 } while (--nl);
3573 if (nl) {
3574 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003575 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003576 }
3577 isbreak = val;
3578 longjmp(bc->brkpt, 1);
3579 /* NOTREACHED */
3580}
3581
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003582static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003583{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003584 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003585
3586 execflg = 0;
3587 if ((cp = t->words[1]) != NULL)
3588 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003589
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003590 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003591
Eric Andersenff9eee42001-06-29 04:57:14 +00003592 leave();
3593 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003594 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003595}
3596
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003597static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003598{
Eric Andersen8401eea2004-08-04 19:16:54 +00003599 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003600 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003601}
3602
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003603static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003604{
Eric Andersen8401eea2004-08-04 19:16:54 +00003605 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003606 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003607}
3608
Eric Andersen8401eea2004-08-04 19:16:54 +00003609static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003610{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003611 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003612 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3613
Eric Andersenff9eee42001-06-29 04:57:14 +00003614 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003615 for (; *wp != NULL; wp++) {
3616 if (isassign(*wp)) {
3617 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003618
Matt Kraaif69bfc72001-07-12 19:39:59 +00003619 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003620 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003621 *cp = '\0';
3622 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003623 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003624 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003625 else
3626 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003627 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003628 } else
3629 putvlist(key, 1);
3630}
3631
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003632static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003633{
3634 prs(s);
3635 err(": bad identifier");
3636}
3637
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003638static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003639{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003640 struct var *vp;
3641 char *cp;
3642 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003643
3644 if ((cp = t->words[1]) == NULL) {
3645 for (vp = vlist; vp; vp = vp->next)
3646 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003647 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003648 }
3649 if (*cp == '-') {
3650 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003651 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003652 if (*++cp == 0)
3653 flag['x'] = flag['v'] = 0;
3654 else
3655 for (; *cp; cp++)
3656 switch (*cp) {
3657 case 'e':
3658 if (!interactive)
3659 flag['e']++;
3660 break;
3661
3662 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003663 if (*cp >= 'a' && *cp <= 'z')
3664 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003665 break;
3666 }
3667 setdash();
3668 }
3669 if (t->words[1]) {
3670 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003671 for (n = 1; t->words[n]; n++)
3672 setarea((char *) t->words[n], 0);
3673 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003674 dolv = t->words;
3675 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003676 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003677 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003678 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003679}
3680
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003681static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003682{
Matt Kraai69edfec2001-08-06 14:14:18 +00003683 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003684 write(out, s, strlen(s));
3685 write(out, "\n", 1);
3686 }
3687}
3688
3689
3690/*
3691 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3692 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003693 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003694static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003695{
3696 struct tms buf;
3697 long int clk_tck = sysconf(_SC_CLK_TCK);
3698
3699 times(&buf);
3700 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003701 (int) (buf.tms_utime / clk_tck / 60),
3702 ((double) buf.tms_utime) / clk_tck,
3703 (int) (buf.tms_stime / clk_tck / 60),
3704 ((double) buf.tms_stime) / clk_tck,
3705 (int) (buf.tms_cutime / clk_tck / 60),
3706 ((double) buf.tms_cutime) / clk_tck,
3707 (int) (buf.tms_cstime / clk_tck / 60),
3708 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003709 return 0;
3710}
3711
3712
Eric Andersen8401eea2004-08-04 19:16:54 +00003713static int (*inbuilt(char *s)) (struct op *) {
Eric Andersen1c039232001-07-07 00:05:55 +00003714 const struct builtincmd *bp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003715
Eric Andersen1c039232001-07-07 00:05:55 +00003716 for (bp = builtincmds; bp->name != NULL; bp++)
3717 if (strcmp(bp->name, s) == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003718 return bp->builtinfunc;
Eric Andersen1c039232001-07-07 00:05:55 +00003719
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003720 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003721}
3722
3723/* -------- eval.c -------- */
3724
3725/*
3726 * ${}
3727 * `command`
3728 * blank interpretation
3729 * quoting
3730 * glob
3731 */
3732
Eric Andersen8401eea2004-08-04 19:16:54 +00003733static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003734{
3735 struct wdblock *wb;
3736 char **wp;
3737 char **wf;
3738 jmp_buf ev;
3739
3740#if __GNUC__
3741 /* Avoid longjmp clobbering */
3742 (void) &wp;
3743 (void) &ap;
3744#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003745
3746 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3747
Eric Andersenff9eee42001-06-29 04:57:14 +00003748 wp = NULL;
3749 wb = NULL;
3750 wf = NULL;
3751 if (newenv(setjmp(errpt = ev)) == 0) {
3752 while (*ap && isassign(*ap))
3753 expand(*ap++, &wb, f & ~DOGLOB);
3754 if (flag['k']) {
3755 for (wf = ap; *wf; wf++) {
3756 if (isassign(*wf))
3757 expand(*wf, &wb, f & ~DOGLOB);
3758 }
3759 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003760 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003761 if (!flag['k'] || !isassign(*ap))
3762 expand(*ap, &wb, f & ~DOKEY);
3763 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003764 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003765 wp = getwords(wb);
3766 quitenv();
3767 } else
3768 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003769
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003770 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003771}
3772
3773/*
3774 * Make the exported environment from the exported
3775 * names in the dictionary. Keyword assignments
3776 * will already have been done.
3777 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003778static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003779{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003780 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003781
3782 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003783
Eric Andersenff9eee42001-06-29 04:57:14 +00003784 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003785 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003786 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003787 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003788 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003789}
3790
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003791static char *evalstr(char *cp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003792{
3793 struct wdblock *wb;
3794
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003795 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003796
Eric Andersenff9eee42001-06-29 04:57:14 +00003797 wb = NULL;
3798 if (expand(cp, &wb, f)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003799 if (wb == NULL || wb->w_nword == 0
3800 || (cp = wb->w_words[0]) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003801 cp = "";
3802 DELETE(wb);
3803 } else
3804 cp = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003805 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003806}
3807
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003808static int expand(char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003809{
3810 jmp_buf ev;
3811
3812#if __GNUC__
3813 /* Avoid longjmp clobbering */
3814 (void) &cp;
3815#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003816
3817 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3818
Eric Andersenff9eee42001-06-29 04:57:14 +00003819 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003820
Eric Andersenff9eee42001-06-29 04:57:14 +00003821 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003822 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003823
Eric Andersenff9eee42001-06-29 04:57:14 +00003824 if (!anys("$`'\"", cp) &&
Eric Andersen8401eea2004-08-04 19:16:54 +00003825 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003826 cp = strsave(cp, areanum);
3827 if (f & DOTRIM)
3828 unquote(cp);
3829 *wbp = addword(cp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003830 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003831 }
3832 if (newenv(setjmp(errpt = ev)) == 0) {
3833 PUSHIO(aword, cp, strchar);
3834 e.iobase = e.iop;
3835 while ((cp = blank(f)) && gflg == 0) {
3836 e.linep = cp;
3837 cp = strsave(cp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003838 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003839 if (f & DOTRIM)
3840 unquote(cp);
3841 *wbp = addword(cp, *wbp);
3842 } else
3843 *wbp = glob(cp, *wbp);
3844 }
3845 quitenv();
3846 } else
3847 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003848 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003849}
3850
3851/*
3852 * Blank interpretation and quoting
3853 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003854static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003855{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003856 int c, c1;
3857 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003858 int scanequals, foundequals;
3859
Eric Andersen12de6cf2004-08-04 19:19:10 +00003860 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3861
Eric Andersenff9eee42001-06-29 04:57:14 +00003862 sp = e.linep;
3863 scanequals = f & DOKEY;
3864 foundequals = 0;
3865
Eric Andersen8401eea2004-08-04 19:16:54 +00003866 loop:
Eric Andersenff9eee42001-06-29 04:57:14 +00003867 switch (c = subgetc('"', foundequals)) {
3868 case 0:
3869 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003870 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003871 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003872 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003873
3874 default:
3875 if (f & DOBLANK && any(c, ifs->value))
3876 goto loop;
3877 break;
3878
3879 case '"':
3880 case '\'':
3881 scanequals = 0;
3882 if (INSUB())
3883 break;
3884 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3885 if (c == 0)
3886 break;
3887 if (c == '\'' || !any(c, "$`\""))
3888 c |= QUOTE;
3889 *e.linep++ = c;
3890 }
3891 c = 0;
3892 }
3893 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003894 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003895 scanequals = 0;
3896 for (;;) {
3897 c = subgetc('"', foundequals);
3898 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003899 f & (DOBLANK && any(c, ifs->value)) ||
3900 (!INSUB() && any(c, "\"'"))) {
3901 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003902 unget(c);
3903 if (any(c, "\"'"))
3904 goto loop;
3905 break;
3906 }
3907 if (scanequals) {
3908 if (c == '=') {
3909 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003910 scanequals = 0;
3911 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003912 scanequals = 0;
3913 }
3914 *e.linep++ = c;
3915 }
3916 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003917 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003918}
3919
3920/*
3921 * Get characters, substituting for ` and $
3922 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003923static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003924{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003925 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003926
3927 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003928
Eric Andersen8401eea2004-08-04 19:16:54 +00003929 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003930 c = my_getc(ec);
3931 if (!INSUB() && ec != '\'') {
3932 if (c == '`') {
3933 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003934 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003935 e.iop->task = XGRAVE;
3936 goto again;
3937 }
3938 if (c == '$' && (c = dollar(quoted)) == 0) {
3939 e.iop->task = XDOLL;
3940 goto again;
3941 }
3942 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003943 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003944}
3945
3946/*
3947 * Prepare to generate the string returned by ${} substitution.
3948 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003949static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003950{
3951 int otask;
3952 struct io *oiop;
3953 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003954 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003955 struct var *vp;
3956
Eric Andersen12de6cf2004-08-04 19:19:10 +00003957 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3958
Eric Andersenff9eee42001-06-29 04:57:14 +00003959 c = readc();
3960 s = e.linep;
3961 if (c != '{') {
3962 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003963 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003964 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003965 if (e.linep < elinep)
3966 *e.linep++ = c;
3967 unget(c);
3968 }
3969 c = 0;
3970 } else {
3971 oiop = e.iop;
3972 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003973
Eric Andersenff9eee42001-06-29 04:57:14 +00003974 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003975 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003976 if (e.linep < elinep)
3977 *e.linep++ = c;
3978 if (oiop == e.iop)
3979 e.iop->task = otask;
3980 if (c != '}') {
3981 err("unclosed ${");
3982 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003983 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003984 }
3985 }
3986 if (e.linep >= elinep) {
3987 err("string in ${} too long");
3988 gflg++;
3989 e.linep -= 10;
3990 }
3991 *e.linep = 0;
3992 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003993 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003994 if (any(*cp, "=-+?")) {
3995 c = *cp;
3996 *cp++ = 0;
3997 break;
3998 }
3999 if (s[1] == 0 && (*s == '*' || *s == '@')) {
4000 if (dolc > 1) {
4001 /* currently this does not distinguish $* and $@ */
4002 /* should check dollar */
4003 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00004004 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004005 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004006 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00004007 s[0] = '1';
4008 s[1] = 0;
4009 }
4010 }
4011 vp = lookup(s);
4012 if ((dolp = vp->value) == null) {
4013 switch (c) {
4014 case '=':
4015 if (isdigit(*s)) {
4016 err("cannot use ${...=...} with $n");
4017 gflg++;
4018 break;
4019 }
4020 setval(vp, cp);
4021 dolp = vp->value;
4022 break;
4023
4024 case '-':
4025 dolp = strsave(cp, areanum);
4026 break;
4027
4028 case '?':
4029 if (*cp == 0) {
4030 prs("missing value for ");
4031 err(s);
4032 } else
4033 err(cp);
4034 gflg++;
4035 break;
4036 }
4037 } else if (c == '+')
4038 dolp = strsave(cp, areanum);
4039 if (flag['u'] && dolp == null) {
4040 prs("unset variable: ");
4041 err(s);
4042 gflg++;
4043 }
4044 e.linep = s;
4045 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004046 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004047}
4048
4049/*
4050 * Run the command in `...` and read its output.
4051 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004052
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004053static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004054{
Eric Andersenff9eee42001-06-29 04:57:14 +00004055 char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004056 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004057 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004058 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00004059 static char child_cmd[LINELIM];
4060 char *src;
4061 char *dest;
4062 int count;
4063 int ignore;
4064 int ignore_once;
4065 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004066 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004067
4068#if __GNUC__
4069 /* Avoid longjmp clobbering */
4070 (void) &cp;
4071#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004072
Eric Andersenff9eee42001-06-29 04:57:14 +00004073 for (cp = e.iop->argp->aword; *cp != '`'; cp++)
4074 if (*cp == 0) {
4075 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004076 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004077 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004078
4079 /* string copy with dollar expansion */
4080 src = e.iop->argp->aword;
4081 dest = child_cmd;
4082 count = 0;
4083 ignore = 0;
4084 ignore_once = 0;
4085 while ((*src != '`') && (count < LINELIM)) {
4086 if (*src == '\'')
4087 ignore = !ignore;
4088 if (*src == '\\')
4089 ignore_once = 1;
4090 if (*src == '$' && !ignore && !ignore_once) {
4091 struct var *vp;
4092 char var_name[LINELIM];
4093 char alt_value[LINELIM];
4094 int var_index = 0;
4095 int alt_index = 0;
4096 char operator = 0;
4097 int braces = 0;
4098 char *value;
4099
4100 src++;
4101 if (*src == '{') {
4102 braces = 1;
4103 src++;
4104 }
4105
4106 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004107 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004108 var_name[var_index++] = *src++;
4109 var_name[var_index] = 0;
4110
4111 if (braces) {
4112 switch (*src) {
4113 case '}':
4114 break;
4115 case '-':
4116 case '=':
4117 case '+':
4118 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004119 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004120 break;
4121 default:
4122 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004123 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004124 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004125 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004126 src++;
4127 while (*src && (*src != '}')) {
4128 alt_value[alt_index++] = *src++;
4129 }
4130 alt_value[alt_index] = 0;
4131 if (*src != '}') {
4132 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004133 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004134 }
4135 }
4136 src++;
4137 }
4138
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004139 if (isalpha(*var_name)) {
4140 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004141
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004142 char *namep = var_name;
4143
4144 *dest++ = '$';
4145 if (braces)
4146 *dest++ = '{';
4147 while (*namep)
4148 *dest++ = *namep++;
4149 if (operator) {
4150 char *altp = alt_value;
4151 *dest++ = operator;
4152 while (*altp)
4153 *dest++ = *altp++;
4154 }
4155 if (braces)
4156 *dest++ = '}';
4157
4158 wb = addword(lookup(var_name)->name, wb);
4159 } else {
4160 /* expand */
4161
4162 vp = lookup(var_name);
4163 if (vp->value != null)
4164 value = (operator == '+') ?
4165 alt_value : vp->value;
4166 else if (operator == '?') {
4167 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004168 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004169 } else if (alt_index && (operator != '+')) {
4170 value = alt_value;
4171 if (operator == '=')
4172 setval(vp, value);
4173 } else
4174 continue;
4175
4176 while (*value && (count < LINELIM)) {
4177 *dest++ = *value++;
4178 count++;
4179 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004180 }
4181 } else {
4182 *dest++ = *src++;
4183 count++;
4184 ignore_once = 0;
4185 }
4186 }
4187 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004188
Eric Andersenff9eee42001-06-29 04:57:14 +00004189 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004190 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004191
Eric Andersen8401eea2004-08-04 19:16:54 +00004192 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004193
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004194 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004195
Eric Andersen737f5fb2003-03-14 16:05:59 +00004196 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004197 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004198 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004199 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004200 }
4201 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004202 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004203 e.iop->argp->aword = ++cp;
4204 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004205 PUSHIO(afile, remap(pf[0]),
4206 (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
4207 gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004208 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004209 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004210 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004211 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004212 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004213 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4214 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004215
Eric Andersenff9eee42001-06-29 04:57:14 +00004216 dup2(pf[1], 1);
4217 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004218
Eric Andersen8401eea2004-08-04 19:16:54 +00004219 argument_list[0] = (char *) DEFAULT_SHELL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004220 argument_list[1] = "-c";
4221 argument_list[2] = child_cmd;
4222 argument_list[3] = 0;
4223
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004224 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004225 prs(argument_list[0]);
4226 prs(": ");
4227 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004228 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004229}
4230
Eric Andersen737f5fb2003-03-14 16:05:59 +00004231
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004232static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004233{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004234 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004235
4236 if ((s = as) != NULL)
4237 while (*s)
4238 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004239 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004240}
4241
4242/* -------- glob.c -------- */
4243
4244/*
4245 * glob
4246 */
4247
4248#define scopy(x) strsave((x), areanum)
4249#define BLKSIZ 512
4250#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4251
Eric Andersen8401eea2004-08-04 19:16:54 +00004252static struct wdblock *cl, *nl;
4253static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004254
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004255static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004256{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004257 int i;
4258 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004259
4260 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004261 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004262 i = 0;
4263 for (pp = cp; *pp; pp++)
4264 if (any(*pp, spcl))
4265 i++;
4266 else if (!any(*pp & ~QUOTE, spcl))
4267 *pp &= ~QUOTE;
4268 if (i != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004269 for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
4270 cl = nl) {
4271 nl = newword(cl->w_nword * 2);
4272 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004273 for (pp = cl->w_words[i]; *pp; pp++)
4274 if (any(*pp, spcl)) {
4275 globname(cl->w_words[i], pp);
4276 break;
4277 }
4278 if (*pp == '\0')
4279 nl = addword(scopy(cl->w_words[i]), nl);
4280 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004281 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004282 DELETE(cl->w_words[i]);
4283 DELETE(cl);
4284 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004285 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004286 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004287 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004288 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004289 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004290 wb = addword(cl->w_words[i], wb);
4291 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004292 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004293 }
4294 }
4295 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004296 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004297}
4298
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004299static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004300{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004301 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004302 char *name, *gp, *dp;
4303 int k;
4304 DIR *dirp;
4305 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004306 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004307 struct stat dbuf;
4308
4309 for (np = we; np != pp; pp--)
4310 if (pp[-1] == '/')
4311 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004312 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004313 *cp++ = *np++;
4314 *cp++ = '.';
4315 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004316 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004317 *cp++ = *np++;
4318 *cp = '\0';
4319 dirp = opendir(dp);
4320 if (dirp == 0) {
4321 DELETE(dp);
4322 DELETE(gp);
4323 return;
4324 }
4325 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004326 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004327 /* XXX Hmmm... What this could be? (abial) */
4328 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004329 if (ent[j].d_ino == 0)
4330 continue;
4331 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004332 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004333 if (dname[0] == '.')
4334 if (*gp != '.')
4335 continue;
4336 for (k = 0; k < NAME_MAX; k++)
4337 if (any(dname[k], spcl))
4338 dname[k] |= QUOTE;
4339 if (gmatch(dname, gp)) {
4340 name = generate(we, pp, dname, np);
4341 if (*np && !anys(np, spcl)) {
4342 if (stat(name, &dbuf)) {
4343 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004344 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004345 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004346 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004347 nl = addword(name, nl);
4348 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004349 }
4350 closedir(dirp);
4351 DELETE(dp);
4352 DELETE(gp);
4353}
4354
4355/*
4356 * generate a pathname as below.
4357 * start..end1 / middle end
4358 * the slashes come for free
4359 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004360static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004361{
4362 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004363 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004364
Eric Andersen8401eea2004-08-04 19:16:54 +00004365 p = op =
4366 space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004367 for (xp = start1; xp != end1;)
4368 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004369 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004370 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004371 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004372 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004373}
4374
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004375static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004376{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004377 int i;
4378 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004379
4380 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004381 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004382 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004383 return 1;
4384 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004385}
4386
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004387static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004388{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004389 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004390}
4391
4392/* -------- word.c -------- */
4393
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004394static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004395{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004396 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004397
Eric Andersen8401eea2004-08-04 19:16:54 +00004398 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004399 wb->w_bsize = nw;
4400 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004401 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004402}
4403
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004404static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004405{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004406 struct wdblock *wb2;
4407 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004408
4409 if (wb == NULL)
4410 wb = newword(NSTART);
4411 if ((nw = wb->w_nword) >= wb->w_bsize) {
4412 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004413 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4414 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004415 wb2->w_nword = nw;
4416 DELETE(wb);
4417 wb = wb2;
4418 }
4419 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004420 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004421}
Eric Andersen8401eea2004-08-04 19:16:54 +00004422
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004423static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004424char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004425{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004426 char **wd;
4427 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004428
4429 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004430 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004431 if (wb->w_nword == 0) {
4432 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004433 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004434 }
4435 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004436 memcpy((char *) wd, (char *) wb->w_words, nb);
4437 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004438 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004439}
4440
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004441static int (*func) (char *, char *);
4442static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004443
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004444static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004445{
4446 func = a3;
4447 globv = a2;
4448 glob1(a0, a0 + a1 * a2);
4449}
4450
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004451static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004452{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004453 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004454 int v2;
4455 char *lptr, *hptr;
4456 int c;
4457 unsigned n;
4458
4459
4460 v2 = globv;
4461
Eric Andersen8401eea2004-08-04 19:16:54 +00004462 top:
4463 if ((n = (int) (lim - base)) <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004464 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004465 n = v2 * (n / (2 * v2));
4466 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004467 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004468 j = lim - v2;
4469 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004470 if (i < lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004471 if ((c = (*func) (i, lptr)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004472 glob2(i, lptr -= v2);
4473 continue;
4474 }
4475 if (c < 0) {
4476 i += v2;
4477 continue;
4478 }
4479 }
4480
Eric Andersen8401eea2004-08-04 19:16:54 +00004481 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004482 if (j > hptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004483 if ((c = (*func) (hptr, j)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004484 glob2(hptr += v2, j);
4485 goto begin;
4486 }
4487 if (c > 0) {
4488 if (i == lptr) {
4489 glob3(i, hptr += v2, j);
4490 i = lptr += v2;
4491 goto begin;
4492 }
4493 glob2(i, j);
4494 j -= v2;
4495 i += v2;
4496 continue;
4497 }
4498 j -= v2;
4499 goto begin;
4500 }
4501
4502
4503 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004504 if (lptr - base >= lim - hptr) {
4505 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004506 lim = lptr;
4507 } else {
4508 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004509 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004510 }
4511 goto top;
4512 }
4513
4514
4515 glob3(j, lptr -= v2, i);
4516 j = hptr -= v2;
4517 }
4518}
4519
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004520static void glob2(char *i, char *j)
Eric Andersenff9eee42001-06-29 04:57:14 +00004521{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004522 char *index1, *index2, c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004523 int m;
4524
4525 m = globv;
4526 index1 = i;
4527 index2 = j;
4528 do {
4529 c = *index1;
4530 *index1++ = *index2;
4531 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004532 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004533}
4534
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004535static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004536{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004537 char *index1, *index2, *index3;
Eric Andersenff9eee42001-06-29 04:57:14 +00004538 int c;
4539 int m;
4540
4541 m = globv;
4542 index1 = i;
4543 index2 = j;
4544 index3 = k;
4545 do {
4546 c = *index1;
4547 *index1++ = *index3;
4548 *index3++ = *index2;
4549 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004550 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004551}
4552
4553/* -------- io.c -------- */
4554
4555/*
4556 * shell IO
4557 */
4558
Eric Andersen8401eea2004-08-04 19:16:54 +00004559static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004560{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004561 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004562
Eric Andersen8401eea2004-08-04 19:16:54 +00004563 if (e.linep > elinep) {
4564 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004565 err("input line too long");
4566 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004567 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004568 }
4569 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004570 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004571 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004572 c = readc();
4573 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004574 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004575 c |= QUOTE;
4576 }
4577 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004578 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004579}
4580
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004581static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004582{
4583 if (e.iop >= e.iobase)
4584 e.iop->peekc = c;
4585}
4586
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004587static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004588{
Eric Andersen8401eea2004-08-04 19:16:54 +00004589 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004590}
4591
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004592static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004593{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004594 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004595
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004596 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004597
4598 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004599 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Eric Andersenff9eee42001-06-29 04:57:14 +00004600 if ((c = e.iop->peekc) != '\0') {
4601 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004602 return c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004603 } else {
4604 if (e.iop->prev != 0) {
4605 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
4606 if (c == -1) {
4607 e.iop++;
4608 continue;
4609 }
4610 if (e.iop == iostack)
4611 ioecho(c);
4612 return (e.iop->prev = c);
4613 } else if (e.iop->task == XIO && e.iop->prev != '\n') {
4614 e.iop->prev = 0;
4615 if (e.iop == iostack)
4616 ioecho('\n');
4617 return '\n';
4618 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004619 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004620 if (e.iop->task == XIO) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004621 if (multiline) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004622 return e.iop->prev = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004623 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004624 if (interactive && e.iop == iostack + 1) {
4625#ifdef CONFIG_FEATURE_COMMAND_EDITING
4626 current_prompt = prompt->value;
4627#else
4628 prs(prompt->value);
4629#endif
4630 }
4631 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004632 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004633
4634 } /* FOR */
4635
4636 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004637 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004638 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004639 }
4640
4641 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004642 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004643
Eric Andersenff9eee42001-06-29 04:57:14 +00004644 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004645 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004646}
4647
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004648static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004649{
4650 if (flag['v'])
4651 write(2, &c, sizeof c);
4652}
4653
Eric Andersen12de6cf2004-08-04 19:19:10 +00004654
Eric Andersen8401eea2004-08-04 19:16:54 +00004655static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004656{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004657 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004658 argp->afid, e.iop));
4659
4660 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004661 if (++e.iop >= &iostack[NPUSH]) {
4662 e.iop--;
4663 err("Shell input nested too deeply");
4664 gflg++;
4665 return;
4666 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004667
4668 /* We did not overflow the NPUSH array spots so setup data structs */
4669
4670 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004671
4672 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004673 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004674 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004675
4676 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4677 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4678
4679 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4680
4681 if (e.iop == &iostack[0])
4682 e.iop->argp->afbuf = &mainbuf;
4683 else
4684 e.iop->argp->afbuf = &sharedbuf;
4685
4686 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4687 /* This line appears to be active when running scripts from command line */
4688 if ((isatty(e.iop->argp->afile) == 0)
4689 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004690 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004691 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4692 bufid = AFID_ID; /* AFID_ID = 0 */
4693
4694 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004695 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004696
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004697 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004698 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004699 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004700 &mainbuf, &sharedbuf, bufid, e.iop));
4701
Eric Andersenff9eee42001-06-29 04:57:14 +00004702 }
4703
Eric Andersen8401eea2004-08-04 19:16:54 +00004704 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004705 e.iop->peekc = 0;
4706 e.iop->xchar = 0;
4707 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004708
Eric Andersenff9eee42001-06-29 04:57:14 +00004709 if (fn == filechar || fn == linechar)
4710 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004711 else if (fn == (int (*)(struct ioarg *)) gravechar
4712 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004713 e.iop->task = XGRAVE;
4714 else
4715 e.iop->task = XOTHER;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004716
4717 return;
Eric Andersenff9eee42001-06-29 04:57:14 +00004718}
4719
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004720static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004721{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004722 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004723
4724 xp = e.iobase;
4725 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004726 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004727}
4728
4729/*
4730 * Input generating functions
4731 */
4732
4733/*
4734 * Produce the characters of a string, then a newline, then EOF.
4735 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004736static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004737{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004738 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004739
4740 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004741 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004742 if ((c = *ap->aword++) == 0) {
4743 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004744 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004745 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004746 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004747}
4748
4749/*
4750 * Given a list of words, produce the characters
4751 * in them, with a space after each word.
4752 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004753static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004754{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004755 char c;
4756 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004757
4758 if ((wl = ap->awordlist) == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004759 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004760 if (*wl != NULL) {
4761 if ((c = *(*wl)++) != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004762 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004763 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004764 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004765 }
4766 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004767 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004768}
4769
4770/*
4771 * Return the characters of a list of words,
4772 * producing a space between them.
4773 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004774static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004775{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004776 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004777
4778 if ((wp = *ap->awordlist++) != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004779 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004780 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004781 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004782 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004783}
4784
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004785static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004786{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004787 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004788
4789 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004790 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004791 if ((c = *ap->aword++) == '\0') {
4792 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004793 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004794 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004795 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004796}
4797
4798/*
4799 * Produce the characters from a single word (string).
4800 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004801static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004802{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004803 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004804
4805 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004806 return 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004807 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004808}
4809
4810/*
4811 * Produce quoted characters from a single word (string).
4812 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004813static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004814{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004815 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004816
4817 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004818 return 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004819 return c | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004820}
4821
4822/*
4823 * Return the characters from a file.
4824 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004825static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004826{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004827 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004828 char c;
4829 struct iobuf *bp = ap->afbuf;
4830
4831 if (ap->afid != AFID_NOBUF) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004832 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004833
Eric Andersen8401eea2004-08-04 19:16:54 +00004834 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004835 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004836
Eric Andersen8401eea2004-08-04 19:16:54 +00004837 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004838
Eric Andersen8401eea2004-08-04 19:16:54 +00004839 if (i <= 0) {
4840 closef(ap->afile);
4841 return 0;
4842 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004843
Eric Andersen8401eea2004-08-04 19:16:54 +00004844 bp->id = ap->afid;
4845 bp->ebufp = (bp->bufp = bp->buf) + i;
4846 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004847
Eric Andersen8401eea2004-08-04 19:16:54 +00004848 ap->afpos++;
4849 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004850 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004851#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004852 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004853 static char mycommand[BUFSIZ];
4854 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004855
Eric Andersen8401eea2004-08-04 19:16:54 +00004856 while (size == 0 || position >= size) {
4857 cmdedit_read_input(current_prompt, mycommand);
4858 size = strlen(mycommand);
4859 position = 0;
4860 }
4861 c = mycommand[position];
4862 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004863 return c;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004864 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00004865#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00004866
Eric Andersenff9eee42001-06-29 04:57:14 +00004867 {
Eric Andersen7467c8d2001-07-12 20:26:32 +00004868 i = safe_read(ap->afile, &c, sizeof(c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004869 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004870 }
4871}
4872
4873/*
4874 * Return the characters from a here temp file.
4875 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004876static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004877{
4878 char c;
4879
4880
4881 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4882 close(ap->afile);
4883 c = 0;
4884 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004885 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004886
4887}
4888
4889/*
4890 * Return the characters produced by a process (`...`).
4891 * Quote them if required, and remove any trailing newline characters.
4892 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004893static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004894{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004895 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004896
Eric Andersen8401eea2004-08-04 19:16:54 +00004897 if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004898 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004899 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004900}
4901
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004902static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004903{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004904 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004905
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004906 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004907
4908 if (iop->xchar) {
4909 if (iop->nlcount) {
4910 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004911 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004912 }
4913 c = iop->xchar;
4914 iop->xchar = 0;
4915 } else if ((c = filechar(ap)) == '\n') {
4916 iop->nlcount = 1;
4917 while ((c = filechar(ap)) == '\n')
4918 iop->nlcount++;
4919 iop->xchar = c;
4920 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004921 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004922 iop->nlcount--;
4923 c = '\n';
4924 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004925 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004926}
4927
4928/*
4929 * Return a single command (usually the first line) from a file.
4930 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004931static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004932{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004933 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004934
4935 if ((c = filechar(ap)) == '\n') {
4936 if (!multiline) {
4937 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004938 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004939 }
4940 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004941 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004942}
4943
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004944static void prs(const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00004945{
4946 if (*s)
4947 write(2, s, strlen(s));
4948}
4949
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004950static void prn(unsigned u)
Eric Andersenff9eee42001-06-29 04:57:14 +00004951{
Eric Andersen737f5fb2003-03-14 16:05:59 +00004952 prs(itoa(u));
Eric Andersenff9eee42001-06-29 04:57:14 +00004953}
4954
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004955static void closef(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00004956{
4957 if (i > 2)
4958 close(i);
4959}
4960
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004961static void closeall(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004962{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004963 int u;
Eric Andersenff9eee42001-06-29 04:57:14 +00004964
Eric Andersen8401eea2004-08-04 19:16:54 +00004965 for (u = NUFILE; u < NOFILE;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004966 close(u++);
4967}
4968
Eric Andersen12de6cf2004-08-04 19:19:10 +00004969
Eric Andersenff9eee42001-06-29 04:57:14 +00004970/*
4971 * remap fd into Shell's fd space
4972 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004973static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004974{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004975 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004976 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004977 int newfd;
4978
4979
4980 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004981
4982 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004983 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004984 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004985
Eric Andersenff9eee42001-06-29 04:57:14 +00004986 do {
4987 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004988 newfd = dup(fd);
4989 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004990 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004991
Eric Andersen8401eea2004-08-04 19:16:54 +00004992 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004993 if (map[i])
4994 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004995
Eric Andersenff9eee42001-06-29 04:57:14 +00004996 if (fd < 0)
4997 err("too many files open in shell");
4998 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004999
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005000 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00005001}
5002
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005003static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005004{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005005 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005006
5007 if ((i = pipe(pv)) < 0)
5008 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005009 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005010}
5011
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005012static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005013{
5014 if (pv != NULL) {
5015 close(*pv++);
5016 close(*pv);
5017 }
5018}
5019
5020/* -------- here.c -------- */
5021
5022/*
5023 * here documents
5024 */
5025
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005026static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00005027{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005028 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005029
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005030 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00005031
5032 h = (struct here *) space(sizeof(struct here));
5033 if (h == 0)
5034 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005035
Eric Andersenff9eee42001-06-29 04:57:14 +00005036 h->h_tag = evalstr(s, DOSUB);
5037 if (h->h_tag == 0)
5038 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005039
Eric Andersenff9eee42001-06-29 04:57:14 +00005040 h->h_iop = iop;
5041 iop->io_name = 0;
5042 h->h_next = NULL;
5043 if (inhere == 0)
5044 inhere = h;
5045 else
Eric Andersen8401eea2004-08-04 19:16:54 +00005046 for (lh = inhere; lh != NULL; lh = lh->h_next)
Eric Andersenff9eee42001-06-29 04:57:14 +00005047 if (lh->h_next == 0) {
5048 lh->h_next = h;
5049 break;
5050 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005051 iop->io_flag |= IOHERE | IOXHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005052 for (s = h->h_tag; *s; s++)
5053 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005054 iop->io_flag &= ~IOXHERE;
5055 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005056 }
5057 h->h_dosub = iop->io_flag & IOXHERE;
5058}
5059
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005060static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005061{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005062 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005063
5064 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005065
5066 /* Scan here files first leaving inhere list in place */
5067 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005068 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005069
5070 /* Make inhere list active - keep list intact for scraphere */
5071 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005072 hp->h_next = acthere;
5073 acthere = inhere;
5074 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005075 }
5076}
5077
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005078static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005079{
5080 int tf;
5081 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005082 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005083 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005084 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005085 char *thenext;
5086
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005087 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005088
Eric Andersenff9eee42001-06-29 04:57:14 +00005089 tf = mkstemp(tname);
5090 if (tf < 0)
5091 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005092
Eric Andersenff9eee42001-06-29 04:57:14 +00005093 *name = strsave(tname, areanum);
5094 if (newenv(setjmp(errpt = ev)) != 0)
5095 unlink(tname);
5096 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005097 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005098 e.iobase = e.iop;
5099 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005100 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005101#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005102 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005103#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005104 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005105#endif
5106 }
5107 thenext = myline;
5108 while ((c = my_getc(ec)) != '\n' && c) {
5109 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005110 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005111 if (thenext >= &myline[LINELIM]) {
5112 c = 0;
5113 break;
5114 }
5115 *thenext++ = c;
5116 }
5117 *thenext = 0;
5118 if (strcmp(s, myline) == 0 || c == 0)
5119 break;
5120 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005121 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005122 }
5123 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005124 prs("here document `");
5125 prs(s);
5126 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005127 }
5128 quitenv();
5129 }
5130 close(tf);
5131}
5132
5133/*
5134 * open here temp file.
5135 * if unquoted here, expand here temp file into second temp file.
5136 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005137static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005138{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005139 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005140 int tf;
5141
5142#if __GNUC__
5143 /* Avoid longjmp clobbering */
5144 (void) &tf;
5145#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005146 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005147 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005148
5149 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5150
Eric Andersenff9eee42001-06-29 04:57:14 +00005151 hf = open(hname, 0);
5152 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005153 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005154
Eric Andersenff9eee42001-06-29 04:57:14 +00005155 if (xdoll) {
5156 char c;
5157 char tname[30] = ".msh_XXXXXX";
5158 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005159
Eric Andersenff9eee42001-06-29 04:57:14 +00005160 tf = mkstemp(tname);
5161 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005162 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00005163 if (newenv(setjmp(errpt = ev)) == 0) {
5164 PUSHIO(afile, hf, herechar);
5165 setbase(e.iop);
5166 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005167 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005168 write(tf, &c, sizeof c);
5169 }
5170 quitenv();
5171 } else
5172 unlink(tname);
5173 close(tf);
5174 tf = open(tname, 0);
5175 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005176 return tf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005177 } else
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005178 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005179}
5180
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005181static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005182{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005183 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005184
5185 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005186
5187 for (h = inhere; h != NULL; h = h->h_next) {
5188 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005189 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005190 }
5191 inhere = NULL;
5192}
5193
5194/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005195static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005196{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005197 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005198
5199 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005200
5201 hl = NULL;
5202 for (h = acthere; h != NULL; h = h->h_next)
5203 if (getarea((char *) h) >= area) {
5204 if (h->h_iop->io_name != NULL)
5205 unlink(h->h_iop->io_name);
5206 if (hl == NULL)
5207 acthere = h->h_next;
5208 else
5209 hl->h_next = h->h_next;
5210 } else
5211 hl = h;
5212}
5213
5214
5215
5216/*
5217 * Copyright (c) 1987,1997, Prentice Hall
5218 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005219 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005220 * Redistribution and use of the MINIX operating system in source and
5221 * binary forms, with or without modification, are permitted provided
5222 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005223 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005224 * Redistributions of source code must retain the above copyright
5225 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005226 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005227 * Redistributions in binary form must reproduce the above
5228 * copyright notice, this list of conditions and the following
5229 * disclaimer in the documentation and/or other materials provided
5230 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005231 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005232 * Neither the name of Prentice Hall nor the names of the software
5233 * authors or contributors may be used to endorse or promote
5234 * products derived from this software without specific prior
5235 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005236 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005237 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5238 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5239 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5240 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5241 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5242 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5243 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5244 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5245 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5246 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5247 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5248 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5249 *
5250 */