blob: 8f58e945722176f95ad45c93a07ae10cdb7d09cc [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)
1025 return (NULL);
1026
1027 if (head->left != NULL) {
1028 dotnode = scantree(head->left);
1029 if (dotnode)
1030 return (dotnode);
1031 }
1032
1033 if (head->right != NULL) {
1034 dotnode = scantree(head->right);
1035 if (dotnode)
1036 return (dotnode);
1037 }
1038
1039 if (head->words == NULL)
1040 return (NULL);
1041
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));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001046 return (head);
1047 }
1048
1049 return (NULL);
1050}
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{
Eric Andersen8401eea2004-08-04 19:16:54 +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");
Eric Andersen8401eea2004-08-04 19:16:54 +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';);
1261 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00001262 }
Eric Andersen8401eea2004-08-04 19:16:54 +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;
1309 return (&dummy);
Eric Andersenff9eee42001-06-29 04:57:14 +00001310 }
1311 for (vp = vlist; vp; vp = vp->next)
1312 if (eqname(vp->name, n))
Eric Andersen8401eea2004-08-04 19:16:54 +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 = "";
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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++;
Eric Andersen8401eea2004-08-04 19:16:54 +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 }
Eric Andersen8401eea2004-08-04 19:16:54 +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')
Eric Andersen8401eea2004-08-04 19:16:54 +00001525 return ((char *) 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 != ']');
Eric Andersen8401eea2004-08-04 19:16:54 +00001535 return (found ? p + 1 : (char *) 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)
1599 return ((char *) 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;
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +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)
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +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:
Eric Andersen8401eea2004-08-04 19:16:54 +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--;
Eric Andersen8401eea2004-08-04 19:16:54 +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)
Eric Andersen8401eea2004-08-04 19:16:54 +00001897 return ((struct op *) 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
1983 return (t);
1984}
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));
Eric Andersen8401eea2004-08-04 19:16:54 +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)
Eric Andersen8401eea2004-08-04 19:16:54 +00002007 return ((struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002008 if (c != DO)
2009 SYNTAXERR;
2010 mylist = c_list();
2011 musthave(DONE, 0);
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +00002022 return ((struct op *) 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();
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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();
Eric Andersen8401eea2004-08-04 19:16:54 +00002049 return (t);
Eric Andersenff9eee42001-06-29 04:57:14 +00002050
2051 default:
2052 peeksym = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00002053 return ((struct op *) 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));
Eric Andersen8401eea2004-08-04 19:16:54 +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
Eric Andersen8401eea2004-08-04 19:16:54 +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
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +00002112 return ((char **) 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;
Eric Andersen8401eea2004-08-04 19:16:54 +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)
Eric Andersen8401eea2004-08-04 19:16:54 +00002130 return (t2);
Eric Andersenff9eee42001-06-29 04:57:14 +00002131 if (t2 == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00002132 return (t1);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002133
Eric Andersen8401eea2004-08-04 19:16:54 +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
Eric Andersen8401eea2004-08-04 19:16:54 +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));
2165 return (rp->r_val); /* Return numeric code for shell multiline */
2166 }
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
Eric Andersen8401eea2004-08-04 19:16:54 +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 }
Eric Andersen8401eea2004-08-04 19:16:54 +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
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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);
2249 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;
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +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')
Eric Andersen8401eea2004-08-04 19:16:54 +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')
Eric Andersen8401eea2004-08-04 19:16:54 +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')
2339 return (c1);
2340 else
2341 return (c);
2342
Eric Andersenff9eee42001-06-29 04:57:14 +00002343 case '^':
2344 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002345 return ('|');
Eric Andersenff9eee42001-06-29 04:57:14 +00002346 case '>':
2347 case '<':
2348 diag(c);
Eric Andersen8401eea2004-08-04 19:16:54 +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 }
Eric Andersen8401eea2004-08-04 19:16:54 +00002366 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00002367
2368 case '(':
2369 case ')':
2370 startl = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +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;
Eric Andersen8401eea2004-08-04 19:16:54 +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);
Eric Andersen8401eea2004-08-04 19:16:54 +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);
2415 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
2451 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 }
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +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"));
Eric Andersen8401eea2004-08-04 19:16:54 +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);
Eric Andersen8401eea2004-08-04 19:16:54 +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));
2876 return (i);
2877 }
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"));
Eric Andersen8401eea2004-08-04 19:16:54 +00003008 return ((struct op **) 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));
Eric Andersen8401eea2004-08-04 19:16:54 +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));
Eric Andersen8401eea2004-08-04 19:16:54 +00003027 return (&t1->left);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003028 }
3029
3030 DBGPRINTF(("FIND1CASE: returning NULL\n"));
Eric Andersen8401eea2004-08-04 19:16:54 +00003031 return ((struct op **) 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
Eric Andersen8401eea2004-08-04 19:16:54 +00003038 return ((tp = find1case(t, w)) != NULL ? *tp : (struct op *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003039}
3040
3041/*
3042 * Enter a new loop level (marked for break/continue).
3043 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003044static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00003045{
3046 bc->nextlev = brklist;
3047 brklist = bc;
3048}
3049
3050/*
3051 * Wait for the last process created.
3052 * Print a message for each process found
3053 * that was killed by a signal.
3054 * Ignore interrupt signals while waiting
3055 * unless `canintr' is true.
3056 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003057static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00003058{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003059 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003060 int s;
3061 int oheedint = heedint;
3062
3063 heedint = 0;
3064 rv = 0;
3065 do {
3066 pid = wait(&s);
3067 if (pid == -1) {
3068 if (errno != EINTR || canintr)
3069 break;
3070 } else {
3071 if ((rv = WAITSIG(s)) != 0) {
3072 if (rv < NSIGNAL) {
3073 if (signame[rv] != NULL) {
3074 if (pid != lastpid) {
3075 prn(pid);
3076 prs(": ");
3077 }
3078 prs(signame[rv]);
3079 }
3080 } else {
3081 if (pid != lastpid) {
3082 prn(pid);
3083 prs(": ");
3084 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003085 prs("Signal ");
3086 prn(rv);
3087 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003088 }
3089 if (WAITCORE(s))
3090 prs(" - core dumped");
3091 if (rv >= NSIGNAL || signame[rv])
3092 prs("\n");
3093 rv = -1;
3094 } else
3095 rv = WAITVAL(s);
3096 }
3097 } while (pid != lastpid);
3098 heedint = oheedint;
3099 if (intr) {
3100 if (interactive) {
3101 if (canintr)
3102 intr = 0;
3103 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003104 if (exstat == 0)
3105 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003106 onintr(0);
3107 }
3108 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003109 return (rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00003110}
3111
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003112static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003113{
3114 exstat = s;
3115 setval(lookup("?"), putn(s));
Eric Andersen8401eea2004-08-04 19:16:54 +00003116 return (s);
Eric Andersenff9eee42001-06-29 04:57:14 +00003117}
3118
3119/*
3120 * PATH-searching interface to execve.
3121 * If getenv("PATH") were kept up-to-date,
3122 * execvp might be used.
3123 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003124static char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003125{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003126 int i;
3127 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003128 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003129 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003130
Rob Landleya299efb2006-08-10 21:46:43 +00003131 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
3132 optind = 1;
3133 if (find_applet_by_name(name)) {
3134 /* We have to exec here since we vforked. Running
3135 * run_applet_by_name() won't work and bad things
3136 * will happen. */
3137 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
3138 }
Eric Andersen1c039232001-07-07 00:05:55 +00003139 }
Eric Andersen1c039232001-07-07 00:05:55 +00003140
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003141 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003142
Eric Andersen8401eea2004-08-04 19:16:54 +00003143 sp = any('/', c) ? "" : path->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00003144 asis = *sp == '\0';
3145 while (asis || *sp != '\0') {
3146 asis = 0;
3147 tp = e.linep;
3148 for (; *sp != '\0'; tp++)
3149 if ((*tp = *sp++) == ':') {
3150 asis = *sp == '\0';
3151 break;
3152 }
3153 if (tp != e.linep)
3154 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003155 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003156
Eric Andersen12de6cf2004-08-04 19:19:10 +00003157 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3158
Eric Andersenff9eee42001-06-29 04:57:14 +00003159 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003160
Eric Andersenff9eee42001-06-29 04:57:14 +00003161 switch (errno) {
3162 case ENOEXEC:
3163 *v = e.linep;
3164 tp = *--v;
3165 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003166 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003167 *v = tp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003168 return ("no Shell");
Eric Andersenff9eee42001-06-29 04:57:14 +00003169
3170 case ENOMEM:
Eric Andersen8401eea2004-08-04 19:16:54 +00003171 return ((char *) bb_msg_memory_exhausted);
Eric Andersenff9eee42001-06-29 04:57:14 +00003172
3173 case E2BIG:
Eric Andersen8401eea2004-08-04 19:16:54 +00003174 return ("argument list too long");
Eric Andersenff9eee42001-06-29 04:57:14 +00003175
3176 case EACCES:
3177 eacces++;
3178 break;
3179 }
3180 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003181 return (errno == ENOENT ? "not found" : "cannot execute");
Eric Andersenff9eee42001-06-29 04:57:14 +00003182}
3183
3184/*
3185 * Run the command produced by generator `f'
3186 * applied to stream `arg'.
3187 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003188static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003189{
3190 struct op *otree;
3191 struct wdblock *swdlist;
3192 struct wdblock *siolist;
3193 jmp_buf ev, rt;
3194 xint *ofail;
3195 int rv;
3196
3197#if __GNUC__
3198 /* Avoid longjmp clobbering */
3199 (void) &rv;
3200#endif
3201
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003202 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003203 areanum, outtree, failpt));
3204
Eric Andersenff9eee42001-06-29 04:57:14 +00003205 areanum++;
3206 swdlist = wdlist;
3207 siolist = iolist;
3208 otree = outtree;
3209 ofail = failpt;
3210 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003211
Eric Andersenff9eee42001-06-29 04:57:14 +00003212 if (newenv(setjmp(errpt = ev)) == 0) {
3213 wdlist = 0;
3214 iolist = 0;
3215 pushio(argp, f);
3216 e.iobase = e.iop;
3217 yynerrs = 0;
3218 if (setjmp(failpt = rt) == 0 && yyparse() == 0)
3219 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3220 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003221 } else {
3222 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003223 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003224
Eric Andersenff9eee42001-06-29 04:57:14 +00003225 wdlist = swdlist;
3226 iolist = siolist;
3227 failpt = ofail;
3228 outtree = otree;
3229 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003230
Eric Andersen8401eea2004-08-04 19:16:54 +00003231 return (rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00003232}
3233
3234/* -------- do.c -------- */
3235
3236/*
3237 * built-in commands: doX
3238 */
3239
Eric Andersen8401eea2004-08-04 19:16:54 +00003240static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003241{
3242 int col;
3243 const struct builtincmd *x;
3244
3245 printf("\nBuilt-in commands:\n");
3246 printf("-------------------\n");
3247
Eric Andersen8401eea2004-08-04 19:16:54 +00003248 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003249 if (!x->name)
3250 continue;
3251 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3252 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003253 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003254 col = 0;
3255 }
3256 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003257#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003258 {
3259 int i;
3260 const struct BB_applet *applet;
3261 extern const struct BB_applet applets[];
3262 extern const size_t NUM_APPLETS;
3263
Eric Andersen8401eea2004-08-04 19:16:54 +00003264 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003265 if (!applet->name)
3266 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003267
Eric Andersen8401eea2004-08-04 19:16:54 +00003268 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003269 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003270 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003271 col = 0;
3272 }
3273 }
3274 }
3275#endif
3276 printf("\n\n");
3277 return EXIT_SUCCESS;
3278}
3279
3280
3281
Eric Andersen8401eea2004-08-04 19:16:54 +00003282static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003283{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003284 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003285}
3286
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003287static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003288{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003289 char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003290
3291 if ((cp = t->words[1]) == NULL && (cp = homedir->value) == NULL)
3292 er = ": no home directory";
Eric Andersen8401eea2004-08-04 19:16:54 +00003293 else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003294 er = ": bad directory";
3295 else
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003296 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003297 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003298 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003299 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003300}
3301
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003302static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003303{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003304 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003305
Eric Andersen8401eea2004-08-04 19:16:54 +00003306 n = t->words[1] ? getn(t->words[1]) : 1;
3307 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003308 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003309 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003310 }
3311 dolv[n] = dolv[0];
3312 dolv += n;
3313 dolc -= n;
3314 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003315 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003316}
3317
3318/*
3319 * execute login and newgrp directly
3320 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003321static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003322{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003323 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003324
3325 if (interactive) {
3326 signal(SIGINT, SIG_DFL);
3327 signal(SIGQUIT, SIG_DFL);
3328 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003329 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003330 prs(t->words[0]);
3331 prs(": ");
3332 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003333 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003334}
3335
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003336static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003337{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003338 int i, n;
3339 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003340
3341 if ((cp = t->words[1]) == NULL) {
3342 i = umask(0);
3343 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003344 for (n = 3 * 4; (n -= 3) >= 0;)
3345 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003346 putc('\n', stderr);
3347 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003348 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3349 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003350 umask(n);
3351 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003352 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003353}
3354
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003355static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003356{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003357 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003358 jmp_buf ex;
3359 xint *ofail;
3360
3361 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003362 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003363 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003364 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003365 execflg = 1;
3366 ofail = failpt;
3367 if (setjmp(failpt = ex) == 0)
3368 execute(t, NOPIPE, NOPIPE, FEXEC);
3369 failpt = ofail;
3370 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003371 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003372}
3373
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003374static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003375{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003376 int i;
3377 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003378 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003379 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003380
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003381 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 +00003382
3383 if ((cp = t->words[1]) == NULL) {
3384 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003385 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003386 } else {
3387 DBGPRINTF(("DODOT: cp is %s\n", cp));
3388 }
3389
Eric Andersen8401eea2004-08-04 19:16:54 +00003390 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003391
3392 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3393 ((sp == NULL) ? "NULL" : sp),
3394 ((e.linep == NULL) ? "NULL" : e.linep)));
3395
Eric Andersenff9eee42001-06-29 04:57:14 +00003396 while (*sp) {
3397 tp = e.linep;
3398 while (*sp && (*tp = *sp++) != ':')
3399 tp++;
3400 if (tp != e.linep)
3401 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003402
Eric Andersen8401eea2004-08-04 19:16:54 +00003403 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003404
3405 /* Original code */
Eric Andersenff9eee42001-06-29 04:57:14 +00003406 if ((i = open(e.linep, 0)) >= 0) {
3407 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003408 maltmp = remap(i);
3409 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3410
3411 next(maltmp); /* Basically a PUSHIO */
3412
3413 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3414
Eric Andersen8401eea2004-08-04 19:16:54 +00003415 return (exstat);
Eric Andersenff9eee42001-06-29 04:57:14 +00003416 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003417
3418 } /* While */
3419
Eric Andersenff9eee42001-06-29 04:57:14 +00003420 prs(cp);
3421 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003422
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003423 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003424}
3425
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003426static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003427{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003428 int i;
3429 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003430
3431 if ((cp = t->words[1]) != NULL) {
3432 i = getn(cp);
3433 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003434 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003435 } else
3436 i = -1;
3437 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003438 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003439}
3440
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003441static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003442{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003443 char *cp, **wp;
3444 int nb = 0;
3445 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003446
3447 if (t->words[1] == NULL) {
3448 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003449 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003450 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003451 for (wp = t->words + 1; *wp; wp++) {
3452 for (cp = e.linep; !nl && cp < elinep - 1; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003453 if ((nb = read(0, cp, sizeof(*cp))) != sizeof(*cp) ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003454 (nl = (*cp == '\n')) || (wp[1] && any(*cp, ifs->value)))
Eric Andersenff9eee42001-06-29 04:57:14 +00003455 break;
3456 *cp = 0;
3457 if (nb <= 0)
3458 break;
3459 setval(lookup(*wp), e.linep);
3460 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003461 return (nb <= 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003462}
3463
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003464static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003465{
Eric Andersen8401eea2004-08-04 19:16:54 +00003466 return (RUN(awordlist, t->words + 1, wdchar));
Eric Andersenff9eee42001-06-29 04:57:14 +00003467}
3468
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003469static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003470{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003471 int n, i;
3472 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003473
3474 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003475 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003476 if (trap[i]) {
3477 prn(i);
3478 prs(": ");
3479 prs(trap[i]);
3480 prs("\n");
3481 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003482 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003483 }
3484 resetsig = isdigit(*t->words[1]);
3485 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3486 n = getsig(t->words[i]);
3487 freecell(trap[n]);
3488 trap[n] = 0;
3489 if (!resetsig) {
3490 if (*t->words[1] != '\0') {
3491 trap[n] = strsave(t->words[1], 0);
3492 setsig(n, sig);
3493 } else
3494 setsig(n, SIG_IGN);
3495 } else {
3496 if (interactive)
3497 if (n == SIGINT)
3498 setsig(n, onintr);
3499 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003500 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003501 else
3502 setsig(n, SIG_DFL);
3503 }
3504 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003505 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003506}
3507
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003508static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003509{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003510 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003511
3512 if ((n = getn(s)) < 0 || n > _NSIG) {
3513 err("trap: bad signal number");
3514 n = 0;
3515 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003516 return (n);
Eric Andersenff9eee42001-06-29 04:57:14 +00003517}
3518
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003519static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003520{
3521 if (n == 0)
3522 return;
3523 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3524 ourtrap[n] = 1;
3525 signal(n, f);
3526 }
3527}
3528
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003529static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003530{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003531 char *s;
3532 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003533
3534 s = as;
3535 m = 1;
3536 if (*s == '-') {
3537 m = -1;
3538 s++;
3539 }
3540 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003541 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003542 if (*s) {
3543 prs(as);
3544 err(": bad number");
3545 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003546 return (n * m);
Eric Andersenff9eee42001-06-29 04:57:14 +00003547}
3548
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003549static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003550{
Eric Andersen8401eea2004-08-04 19:16:54 +00003551 return (brkcontin(t->words[1], 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00003552}
3553
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003554static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003555{
Eric Andersen8401eea2004-08-04 19:16:54 +00003556 return (brkcontin(t->words[1], 0));
Eric Andersenff9eee42001-06-29 04:57:14 +00003557}
3558
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003559static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003560{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003561 struct brkcon *bc;
3562 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003563
Eric Andersen8401eea2004-08-04 19:16:54 +00003564 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003565 if (nl <= 0)
3566 nl = 999;
3567 do {
3568 if ((bc = brklist) == NULL)
3569 break;
3570 brklist = bc->nextlev;
3571 } while (--nl);
3572 if (nl) {
3573 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003574 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003575 }
3576 isbreak = val;
3577 longjmp(bc->brkpt, 1);
3578 /* NOTREACHED */
3579}
3580
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003581static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003582{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003583 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003584
3585 execflg = 0;
3586 if ((cp = t->words[1]) != NULL)
3587 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003588
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003589 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003590
Eric Andersenff9eee42001-06-29 04:57:14 +00003591 leave();
3592 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003593 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003594}
3595
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003596static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003597{
Eric Andersen8401eea2004-08-04 19:16:54 +00003598 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003599 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003600}
3601
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003602static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003603{
Eric Andersen8401eea2004-08-04 19:16:54 +00003604 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003605 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003606}
3607
Eric Andersen8401eea2004-08-04 19:16:54 +00003608static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003609{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003610 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003611 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3612
Eric Andersenff9eee42001-06-29 04:57:14 +00003613 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003614 for (; *wp != NULL; wp++) {
3615 if (isassign(*wp)) {
3616 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003617
Matt Kraaif69bfc72001-07-12 19:39:59 +00003618 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003619 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003620 *cp = '\0';
3621 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003622 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003623 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003624 else
3625 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003626 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003627 } else
3628 putvlist(key, 1);
3629}
3630
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003631static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003632{
3633 prs(s);
3634 err(": bad identifier");
3635}
3636
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003637static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003638{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003639 struct var *vp;
3640 char *cp;
3641 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003642
3643 if ((cp = t->words[1]) == NULL) {
3644 for (vp = vlist; vp; vp = vp->next)
3645 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003646 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003647 }
3648 if (*cp == '-') {
3649 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003650 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003651 if (*++cp == 0)
3652 flag['x'] = flag['v'] = 0;
3653 else
3654 for (; *cp; cp++)
3655 switch (*cp) {
3656 case 'e':
3657 if (!interactive)
3658 flag['e']++;
3659 break;
3660
3661 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003662 if (*cp >= 'a' && *cp <= 'z')
3663 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003664 break;
3665 }
3666 setdash();
3667 }
3668 if (t->words[1]) {
3669 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003670 for (n = 1; t->words[n]; n++)
3671 setarea((char *) t->words[n], 0);
3672 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003673 dolv = t->words;
3674 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003675 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003676 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003677 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003678}
3679
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003680static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003681{
Matt Kraai69edfec2001-08-06 14:14:18 +00003682 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003683 write(out, s, strlen(s));
3684 write(out, "\n", 1);
3685 }
3686}
3687
3688
3689/*
3690 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3691 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003692 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003693static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003694{
3695 struct tms buf;
3696 long int clk_tck = sysconf(_SC_CLK_TCK);
3697
3698 times(&buf);
3699 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003700 (int) (buf.tms_utime / clk_tck / 60),
3701 ((double) buf.tms_utime) / clk_tck,
3702 (int) (buf.tms_stime / clk_tck / 60),
3703 ((double) buf.tms_stime) / clk_tck,
3704 (int) (buf.tms_cutime / clk_tck / 60),
3705 ((double) buf.tms_cutime) / clk_tck,
3706 (int) (buf.tms_cstime / clk_tck / 60),
3707 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003708 return 0;
3709}
3710
3711
Eric Andersen8401eea2004-08-04 19:16:54 +00003712static int (*inbuilt(char *s)) (struct op *) {
Eric Andersen1c039232001-07-07 00:05:55 +00003713 const struct builtincmd *bp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003714
Eric Andersen1c039232001-07-07 00:05:55 +00003715 for (bp = builtincmds; bp->name != NULL; bp++)
3716 if (strcmp(bp->name, s) == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00003717 return (bp->builtinfunc);
Eric Andersen1c039232001-07-07 00:05:55 +00003718
Eric Andersen8401eea2004-08-04 19:16:54 +00003719 return (NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003720}
3721
3722/* -------- eval.c -------- */
3723
3724/*
3725 * ${}
3726 * `command`
3727 * blank interpretation
3728 * quoting
3729 * glob
3730 */
3731
Eric Andersen8401eea2004-08-04 19:16:54 +00003732static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003733{
3734 struct wdblock *wb;
3735 char **wp;
3736 char **wf;
3737 jmp_buf ev;
3738
3739#if __GNUC__
3740 /* Avoid longjmp clobbering */
3741 (void) &wp;
3742 (void) &ap;
3743#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003744
3745 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3746
Eric Andersenff9eee42001-06-29 04:57:14 +00003747 wp = NULL;
3748 wb = NULL;
3749 wf = NULL;
3750 if (newenv(setjmp(errpt = ev)) == 0) {
3751 while (*ap && isassign(*ap))
3752 expand(*ap++, &wb, f & ~DOGLOB);
3753 if (flag['k']) {
3754 for (wf = ap; *wf; wf++) {
3755 if (isassign(*wf))
3756 expand(*wf, &wb, f & ~DOGLOB);
3757 }
3758 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003759 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003760 if (!flag['k'] || !isassign(*ap))
3761 expand(*ap, &wb, f & ~DOKEY);
3762 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003763 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003764 wp = getwords(wb);
3765 quitenv();
3766 } else
3767 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003768
Eric Andersen8401eea2004-08-04 19:16:54 +00003769 return (gflg ? (char **) NULL : wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003770}
3771
3772/*
3773 * Make the exported environment from the exported
3774 * names in the dictionary. Keyword assignments
3775 * will already have been done.
3776 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003777static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003778{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003779 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003780
3781 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003782
Eric Andersenff9eee42001-06-29 04:57:14 +00003783 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003784 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003785 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003786 wb = addword((char *) 0, wb);
3787 return (getwords(wb));
Eric Andersenff9eee42001-06-29 04:57:14 +00003788}
3789
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003790static char *evalstr(char *cp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003791{
3792 struct wdblock *wb;
3793
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003794 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003795
Eric Andersenff9eee42001-06-29 04:57:14 +00003796 wb = NULL;
3797 if (expand(cp, &wb, f)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003798 if (wb == NULL || wb->w_nword == 0
3799 || (cp = wb->w_words[0]) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003800 cp = "";
3801 DELETE(wb);
3802 } else
3803 cp = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003804 return (cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003805}
3806
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003807static int expand(char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003808{
3809 jmp_buf ev;
3810
3811#if __GNUC__
3812 /* Avoid longjmp clobbering */
3813 (void) &cp;
3814#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003815
3816 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3817
Eric Andersenff9eee42001-06-29 04:57:14 +00003818 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003819
Eric Andersenff9eee42001-06-29 04:57:14 +00003820 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003821 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003822
Eric Andersenff9eee42001-06-29 04:57:14 +00003823 if (!anys("$`'\"", cp) &&
Eric Andersen8401eea2004-08-04 19:16:54 +00003824 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003825 cp = strsave(cp, areanum);
3826 if (f & DOTRIM)
3827 unquote(cp);
3828 *wbp = addword(cp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003829 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003830 }
3831 if (newenv(setjmp(errpt = ev)) == 0) {
3832 PUSHIO(aword, cp, strchar);
3833 e.iobase = e.iop;
3834 while ((cp = blank(f)) && gflg == 0) {
3835 e.linep = cp;
3836 cp = strsave(cp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003837 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003838 if (f & DOTRIM)
3839 unquote(cp);
3840 *wbp = addword(cp, *wbp);
3841 } else
3842 *wbp = glob(cp, *wbp);
3843 }
3844 quitenv();
3845 } else
3846 gflg = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003847 return (gflg == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003848}
3849
3850/*
3851 * Blank interpretation and quoting
3852 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003853static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003854{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003855 int c, c1;
3856 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003857 int scanequals, foundequals;
3858
Eric Andersen12de6cf2004-08-04 19:19:10 +00003859 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3860
Eric Andersenff9eee42001-06-29 04:57:14 +00003861 sp = e.linep;
3862 scanequals = f & DOKEY;
3863 foundequals = 0;
3864
Eric Andersen8401eea2004-08-04 19:16:54 +00003865 loop:
Eric Andersenff9eee42001-06-29 04:57:14 +00003866 switch (c = subgetc('"', foundequals)) {
3867 case 0:
3868 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003869 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003870 *e.linep++ = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003871 return (sp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003872
3873 default:
3874 if (f & DOBLANK && any(c, ifs->value))
3875 goto loop;
3876 break;
3877
3878 case '"':
3879 case '\'':
3880 scanequals = 0;
3881 if (INSUB())
3882 break;
3883 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3884 if (c == 0)
3885 break;
3886 if (c == '\'' || !any(c, "$`\""))
3887 c |= QUOTE;
3888 *e.linep++ = c;
3889 }
3890 c = 0;
3891 }
3892 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003893 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003894 scanequals = 0;
3895 for (;;) {
3896 c = subgetc('"', foundequals);
3897 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003898 f & (DOBLANK && any(c, ifs->value)) ||
3899 (!INSUB() && any(c, "\"'"))) {
3900 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003901 unget(c);
3902 if (any(c, "\"'"))
3903 goto loop;
3904 break;
3905 }
3906 if (scanequals) {
3907 if (c == '=') {
3908 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003909 scanequals = 0;
3910 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003911 scanequals = 0;
3912 }
3913 *e.linep++ = c;
3914 }
3915 *e.linep++ = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003916 return (sp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003917}
3918
3919/*
3920 * Get characters, substituting for ` and $
3921 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003922static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003923{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003924 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003925
3926 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003927
Eric Andersen8401eea2004-08-04 19:16:54 +00003928 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003929 c = my_getc(ec);
3930 if (!INSUB() && ec != '\'') {
3931 if (c == '`') {
3932 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003933 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003934 e.iop->task = XGRAVE;
3935 goto again;
3936 }
3937 if (c == '$' && (c = dollar(quoted)) == 0) {
3938 e.iop->task = XDOLL;
3939 goto again;
3940 }
3941 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003942 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00003943}
3944
3945/*
3946 * Prepare to generate the string returned by ${} substitution.
3947 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003948static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003949{
3950 int otask;
3951 struct io *oiop;
3952 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003953 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003954 struct var *vp;
3955
Eric Andersen12de6cf2004-08-04 19:19:10 +00003956 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3957
Eric Andersenff9eee42001-06-29 04:57:14 +00003958 c = readc();
3959 s = e.linep;
3960 if (c != '{') {
3961 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003962 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003963 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003964 if (e.linep < elinep)
3965 *e.linep++ = c;
3966 unget(c);
3967 }
3968 c = 0;
3969 } else {
3970 oiop = e.iop;
3971 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003972
Eric Andersenff9eee42001-06-29 04:57:14 +00003973 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003974 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003975 if (e.linep < elinep)
3976 *e.linep++ = c;
3977 if (oiop == e.iop)
3978 e.iop->task = otask;
3979 if (c != '}') {
3980 err("unclosed ${");
3981 gflg++;
Eric Andersen8401eea2004-08-04 19:16:54 +00003982 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00003983 }
3984 }
3985 if (e.linep >= elinep) {
3986 err("string in ${} too long");
3987 gflg++;
3988 e.linep -= 10;
3989 }
3990 *e.linep = 0;
3991 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003992 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003993 if (any(*cp, "=-+?")) {
3994 c = *cp;
3995 *cp++ = 0;
3996 break;
3997 }
3998 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3999 if (dolc > 1) {
4000 /* currently this does not distinguish $* and $@ */
4001 /* should check dollar */
4002 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00004003 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004004 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004005 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00004006 s[0] = '1';
4007 s[1] = 0;
4008 }
4009 }
4010 vp = lookup(s);
4011 if ((dolp = vp->value) == null) {
4012 switch (c) {
4013 case '=':
4014 if (isdigit(*s)) {
4015 err("cannot use ${...=...} with $n");
4016 gflg++;
4017 break;
4018 }
4019 setval(vp, cp);
4020 dolp = vp->value;
4021 break;
4022
4023 case '-':
4024 dolp = strsave(cp, areanum);
4025 break;
4026
4027 case '?':
4028 if (*cp == 0) {
4029 prs("missing value for ");
4030 err(s);
4031 } else
4032 err(cp);
4033 gflg++;
4034 break;
4035 }
4036 } else if (c == '+')
4037 dolp = strsave(cp, areanum);
4038 if (flag['u'] && dolp == null) {
4039 prs("unset variable: ");
4040 err(s);
4041 gflg++;
4042 }
4043 e.linep = s;
4044 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004045 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004046}
4047
4048/*
4049 * Run the command in `...` and read its output.
4050 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004051
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004052static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004053{
Eric Andersenff9eee42001-06-29 04:57:14 +00004054 char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004055 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004056 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004057 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00004058 static char child_cmd[LINELIM];
4059 char *src;
4060 char *dest;
4061 int count;
4062 int ignore;
4063 int ignore_once;
4064 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004065 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004066
4067#if __GNUC__
4068 /* Avoid longjmp clobbering */
4069 (void) &cp;
4070#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004071
Eric Andersenff9eee42001-06-29 04:57:14 +00004072 for (cp = e.iop->argp->aword; *cp != '`'; cp++)
4073 if (*cp == 0) {
4074 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004075 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004076 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004077
4078 /* string copy with dollar expansion */
4079 src = e.iop->argp->aword;
4080 dest = child_cmd;
4081 count = 0;
4082 ignore = 0;
4083 ignore_once = 0;
4084 while ((*src != '`') && (count < LINELIM)) {
4085 if (*src == '\'')
4086 ignore = !ignore;
4087 if (*src == '\\')
4088 ignore_once = 1;
4089 if (*src == '$' && !ignore && !ignore_once) {
4090 struct var *vp;
4091 char var_name[LINELIM];
4092 char alt_value[LINELIM];
4093 int var_index = 0;
4094 int alt_index = 0;
4095 char operator = 0;
4096 int braces = 0;
4097 char *value;
4098
4099 src++;
4100 if (*src == '{') {
4101 braces = 1;
4102 src++;
4103 }
4104
4105 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004106 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004107 var_name[var_index++] = *src++;
4108 var_name[var_index] = 0;
4109
4110 if (braces) {
4111 switch (*src) {
4112 case '}':
4113 break;
4114 case '-':
4115 case '=':
4116 case '+':
4117 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004118 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004119 break;
4120 default:
4121 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004122 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004123 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004124 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004125 src++;
4126 while (*src && (*src != '}')) {
4127 alt_value[alt_index++] = *src++;
4128 }
4129 alt_value[alt_index] = 0;
4130 if (*src != '}') {
4131 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004132 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004133 }
4134 }
4135 src++;
4136 }
4137
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004138 if (isalpha(*var_name)) {
4139 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004140
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004141 char *namep = var_name;
4142
4143 *dest++ = '$';
4144 if (braces)
4145 *dest++ = '{';
4146 while (*namep)
4147 *dest++ = *namep++;
4148 if (operator) {
4149 char *altp = alt_value;
4150 *dest++ = operator;
4151 while (*altp)
4152 *dest++ = *altp++;
4153 }
4154 if (braces)
4155 *dest++ = '}';
4156
4157 wb = addword(lookup(var_name)->name, wb);
4158 } else {
4159 /* expand */
4160
4161 vp = lookup(var_name);
4162 if (vp->value != null)
4163 value = (operator == '+') ?
4164 alt_value : vp->value;
4165 else if (operator == '?') {
4166 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004167 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004168 } else if (alt_index && (operator != '+')) {
4169 value = alt_value;
4170 if (operator == '=')
4171 setval(vp, value);
4172 } else
4173 continue;
4174
4175 while (*value && (count < LINELIM)) {
4176 *dest++ = *value++;
4177 count++;
4178 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004179 }
4180 } else {
4181 *dest++ = *src++;
4182 count++;
4183 ignore_once = 0;
4184 }
4185 }
4186 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004187
Eric Andersenff9eee42001-06-29 04:57:14 +00004188 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004189 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004190
Eric Andersen8401eea2004-08-04 19:16:54 +00004191 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004192
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004193 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004194
Eric Andersen737f5fb2003-03-14 16:05:59 +00004195 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004196 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004197 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004198 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004199 }
4200 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004201 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004202 e.iop->argp->aword = ++cp;
4203 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004204 PUSHIO(afile, remap(pf[0]),
4205 (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
4206 gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004207 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004208 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004209 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004210 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004211 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004212 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4213 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004214
Eric Andersenff9eee42001-06-29 04:57:14 +00004215 dup2(pf[1], 1);
4216 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004217
Eric Andersen8401eea2004-08-04 19:16:54 +00004218 argument_list[0] = (char *) DEFAULT_SHELL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004219 argument_list[1] = "-c";
4220 argument_list[2] = child_cmd;
4221 argument_list[3] = 0;
4222
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004223 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004224 prs(argument_list[0]);
4225 prs(": ");
4226 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004227 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004228}
4229
Eric Andersen737f5fb2003-03-14 16:05:59 +00004230
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004231static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004232{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004233 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004234
4235 if ((s = as) != NULL)
4236 while (*s)
4237 *s++ &= ~QUOTE;
Eric Andersen8401eea2004-08-04 19:16:54 +00004238 return (as);
Eric Andersenff9eee42001-06-29 04:57:14 +00004239}
4240
4241/* -------- glob.c -------- */
4242
4243/*
4244 * glob
4245 */
4246
4247#define scopy(x) strsave((x), areanum)
4248#define BLKSIZ 512
4249#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4250
Eric Andersen8401eea2004-08-04 19:16:54 +00004251static struct wdblock *cl, *nl;
4252static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004253
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004254static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004255{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004256 int i;
4257 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004258
4259 if (cp == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004260 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004261 i = 0;
4262 for (pp = cp; *pp; pp++)
4263 if (any(*pp, spcl))
4264 i++;
4265 else if (!any(*pp & ~QUOTE, spcl))
4266 *pp &= ~QUOTE;
4267 if (i != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004268 for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
4269 cl = nl) {
4270 nl = newword(cl->w_nword * 2);
4271 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004272 for (pp = cl->w_words[i]; *pp; pp++)
4273 if (any(*pp, spcl)) {
4274 globname(cl->w_words[i], pp);
4275 break;
4276 }
4277 if (*pp == '\0')
4278 nl = addword(scopy(cl->w_words[i]), nl);
4279 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004280 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004281 DELETE(cl->w_words[i]);
4282 DELETE(cl);
4283 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004284 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004285 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004286 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004287 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004288 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004289 wb = addword(cl->w_words[i], wb);
4290 DELETE(cl);
Eric Andersen8401eea2004-08-04 19:16:54 +00004291 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004292 }
4293 }
4294 wb = addword(unquote(cp), wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00004295 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004296}
4297
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004298static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004299{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004300 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004301 char *name, *gp, *dp;
4302 int k;
4303 DIR *dirp;
4304 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004305 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004306 struct stat dbuf;
4307
4308 for (np = we; np != pp; pp--)
4309 if (pp[-1] == '/')
4310 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004311 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004312 *cp++ = *np++;
4313 *cp++ = '.';
4314 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004315 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004316 *cp++ = *np++;
4317 *cp = '\0';
4318 dirp = opendir(dp);
4319 if (dirp == 0) {
4320 DELETE(dp);
4321 DELETE(gp);
4322 return;
4323 }
4324 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004325 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004326 /* XXX Hmmm... What this could be? (abial) */
4327 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004328 if (ent[j].d_ino == 0)
4329 continue;
4330 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004331 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004332 if (dname[0] == '.')
4333 if (*gp != '.')
4334 continue;
4335 for (k = 0; k < NAME_MAX; k++)
4336 if (any(dname[k], spcl))
4337 dname[k] |= QUOTE;
4338 if (gmatch(dname, gp)) {
4339 name = generate(we, pp, dname, np);
4340 if (*np && !anys(np, spcl)) {
4341 if (stat(name, &dbuf)) {
4342 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004343 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004344 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004345 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004346 nl = addword(name, nl);
4347 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004348 }
4349 closedir(dirp);
4350 DELETE(dp);
4351 DELETE(gp);
4352}
4353
4354/*
4355 * generate a pathname as below.
4356 * start..end1 / middle end
4357 * the slashes come for free
4358 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004359static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004360{
4361 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004362 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004363
Eric Andersen8401eea2004-08-04 19:16:54 +00004364 p = op =
4365 space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004366 for (xp = start1; xp != end1;)
4367 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004368 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004369 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004370 for (xp = end; (*op++ = *xp++) != '\0';);
4371 return (p);
Eric Andersenff9eee42001-06-29 04:57:14 +00004372}
4373
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004374static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004375{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004376 int i;
4377 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004378
4379 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004380 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004381 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004382 return 1;
4383 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004384}
4385
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004386static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004387{
Eric Andersen8401eea2004-08-04 19:16:54 +00004388 return (strcmp(*(char **) p1, *(char **) p2));
Eric Andersenff9eee42001-06-29 04:57:14 +00004389}
4390
4391/* -------- word.c -------- */
4392
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004393static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004394{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004395 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004396
Eric Andersen8401eea2004-08-04 19:16:54 +00004397 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004398 wb->w_bsize = nw;
4399 wb->w_nword = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004400 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004401}
4402
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004403static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004404{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004405 struct wdblock *wb2;
4406 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004407
4408 if (wb == NULL)
4409 wb = newword(NSTART);
4410 if ((nw = wb->w_nword) >= wb->w_bsize) {
4411 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004412 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4413 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004414 wb2->w_nword = nw;
4415 DELETE(wb);
4416 wb = wb2;
4417 }
4418 wb->w_words[wb->w_nword++] = wd;
Eric Andersen8401eea2004-08-04 19:16:54 +00004419 return (wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00004420}
Eric Andersen8401eea2004-08-04 19:16:54 +00004421
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004422static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004423char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004424{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004425 char **wd;
4426 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004427
4428 if (wb == NULL)
Eric Andersen8401eea2004-08-04 19:16:54 +00004429 return ((char **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00004430 if (wb->w_nword == 0) {
4431 DELETE(wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00004432 return ((char **) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00004433 }
4434 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004435 memcpy((char *) wd, (char *) wb->w_words, nb);
4436 DELETE(wb); /* perhaps should done by caller */
4437 return (wd);
Eric Andersenff9eee42001-06-29 04:57:14 +00004438}
4439
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004440static int (*func) (char *, char *);
4441static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004442
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004443static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004444{
4445 func = a3;
4446 globv = a2;
4447 glob1(a0, a0 + a1 * a2);
4448}
4449
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004450static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004451{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004452 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004453 int v2;
4454 char *lptr, *hptr;
4455 int c;
4456 unsigned n;
4457
4458
4459 v2 = globv;
4460
Eric Andersen8401eea2004-08-04 19:16:54 +00004461 top:
4462 if ((n = (int) (lim - base)) <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004463 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004464 n = v2 * (n / (2 * v2));
4465 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004466 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004467 j = lim - v2;
4468 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004469 if (i < lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004470 if ((c = (*func) (i, lptr)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004471 glob2(i, lptr -= v2);
4472 continue;
4473 }
4474 if (c < 0) {
4475 i += v2;
4476 continue;
4477 }
4478 }
4479
Eric Andersen8401eea2004-08-04 19:16:54 +00004480 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004481 if (j > hptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004482 if ((c = (*func) (hptr, j)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004483 glob2(hptr += v2, j);
4484 goto begin;
4485 }
4486 if (c > 0) {
4487 if (i == lptr) {
4488 glob3(i, hptr += v2, j);
4489 i = lptr += v2;
4490 goto begin;
4491 }
4492 glob2(i, j);
4493 j -= v2;
4494 i += v2;
4495 continue;
4496 }
4497 j -= v2;
4498 goto begin;
4499 }
4500
4501
4502 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004503 if (lptr - base >= lim - hptr) {
4504 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004505 lim = lptr;
4506 } else {
4507 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004508 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004509 }
4510 goto top;
4511 }
4512
4513
4514 glob3(j, lptr -= v2, i);
4515 j = hptr -= v2;
4516 }
4517}
4518
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004519static void glob2(char *i, char *j)
Eric Andersenff9eee42001-06-29 04:57:14 +00004520{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004521 char *index1, *index2, c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004522 int m;
4523
4524 m = globv;
4525 index1 = i;
4526 index2 = j;
4527 do {
4528 c = *index1;
4529 *index1++ = *index2;
4530 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004531 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004532}
4533
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004534static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004535{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004536 char *index1, *index2, *index3;
Eric Andersenff9eee42001-06-29 04:57:14 +00004537 int c;
4538 int m;
4539
4540 m = globv;
4541 index1 = i;
4542 index2 = j;
4543 index3 = k;
4544 do {
4545 c = *index1;
4546 *index1++ = *index3;
4547 *index3++ = *index2;
4548 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004549 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004550}
4551
4552/* -------- io.c -------- */
4553
4554/*
4555 * shell IO
4556 */
4557
Eric Andersen8401eea2004-08-04 19:16:54 +00004558static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004559{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004560 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004561
Eric Andersen8401eea2004-08-04 19:16:54 +00004562 if (e.linep > elinep) {
4563 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004564 err("input line too long");
4565 gflg++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004566 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004567 }
4568 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004569 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004570 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004571 c = readc();
4572 if (c == '\n' && ec != '\"')
Eric Andersen8401eea2004-08-04 19:16:54 +00004573 return (my_getc(ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00004574 c |= QUOTE;
4575 }
4576 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004577 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004578}
4579
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004580static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004581{
4582 if (e.iop >= e.iobase)
4583 e.iop->peekc = c;
4584}
4585
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004586static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004587{
Eric Andersen8401eea2004-08-04 19:16:54 +00004588 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004589}
4590
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004591static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004592{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004593 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004594
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004595 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004596
4597 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004598 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Eric Andersenff9eee42001-06-29 04:57:14 +00004599 if ((c = e.iop->peekc) != '\0') {
4600 e.iop->peekc = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004601 return (c);
4602 } else {
4603 if (e.iop->prev != 0) {
4604 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
4605 if (c == -1) {
4606 e.iop++;
4607 continue;
4608 }
4609 if (e.iop == iostack)
4610 ioecho(c);
4611 return (e.iop->prev = c);
4612 } else if (e.iop->task == XIO && e.iop->prev != '\n') {
4613 e.iop->prev = 0;
4614 if (e.iop == iostack)
4615 ioecho('\n');
4616 return '\n';
4617 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004618 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004619 if (e.iop->task == XIO) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004620 if (multiline) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004621 return e.iop->prev = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004622 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004623 if (interactive && e.iop == iostack + 1) {
4624#ifdef CONFIG_FEATURE_COMMAND_EDITING
4625 current_prompt = prompt->value;
4626#else
4627 prs(prompt->value);
4628#endif
4629 }
4630 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004631 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004632
4633 } /* FOR */
4634
4635 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004636 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004637 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004638 }
4639
4640 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004641 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004642
Eric Andersenff9eee42001-06-29 04:57:14 +00004643 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004644 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004645}
4646
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004647static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004648{
4649 if (flag['v'])
4650 write(2, &c, sizeof c);
4651}
4652
Eric Andersen12de6cf2004-08-04 19:19:10 +00004653
Eric Andersen8401eea2004-08-04 19:16:54 +00004654static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004655{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004656 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004657 argp->afid, e.iop));
4658
4659 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004660 if (++e.iop >= &iostack[NPUSH]) {
4661 e.iop--;
4662 err("Shell input nested too deeply");
4663 gflg++;
4664 return;
4665 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004666
4667 /* We did not overflow the NPUSH array spots so setup data structs */
4668
4669 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004670
4671 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004672 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004673 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004674
4675 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4676 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4677
4678 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4679
4680 if (e.iop == &iostack[0])
4681 e.iop->argp->afbuf = &mainbuf;
4682 else
4683 e.iop->argp->afbuf = &sharedbuf;
4684
4685 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4686 /* This line appears to be active when running scripts from command line */
4687 if ((isatty(e.iop->argp->afile) == 0)
4688 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004689 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004690 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4691 bufid = AFID_ID; /* AFID_ID = 0 */
4692
4693 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004694 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004695
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004696 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004697 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004698 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004699 &mainbuf, &sharedbuf, bufid, e.iop));
4700
Eric Andersenff9eee42001-06-29 04:57:14 +00004701 }
4702
Eric Andersen8401eea2004-08-04 19:16:54 +00004703 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004704 e.iop->peekc = 0;
4705 e.iop->xchar = 0;
4706 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004707
Eric Andersenff9eee42001-06-29 04:57:14 +00004708 if (fn == filechar || fn == linechar)
4709 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004710 else if (fn == (int (*)(struct ioarg *)) gravechar
4711 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004712 e.iop->task = XGRAVE;
4713 else
4714 e.iop->task = XOTHER;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004715
4716 return;
Eric Andersenff9eee42001-06-29 04:57:14 +00004717}
4718
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004719static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004720{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004721 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004722
4723 xp = e.iobase;
4724 e.iobase = ip;
Eric Andersen8401eea2004-08-04 19:16:54 +00004725 return (xp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004726}
4727
4728/*
4729 * Input generating functions
4730 */
4731
4732/*
4733 * Produce the characters of a string, then a newline, then EOF.
4734 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004735static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004736{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004737 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004738
4739 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004740 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004741 if ((c = *ap->aword++) == 0) {
4742 ap->aword = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00004743 return ('\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00004744 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004745 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004746}
4747
4748/*
4749 * Given a list of words, produce the characters
4750 * in them, with a space after each word.
4751 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004752static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004753{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004754 char c;
4755 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004756
4757 if ((wl = ap->awordlist) == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004758 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004759 if (*wl != NULL) {
4760 if ((c = *(*wl)++) != 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004761 return (c & 0177);
Eric Andersenff9eee42001-06-29 04:57:14 +00004762 ap->awordlist++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004763 return (' ');
Eric Andersenff9eee42001-06-29 04:57:14 +00004764 }
4765 ap->awordlist = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00004766 return ('\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00004767}
4768
4769/*
4770 * Return the characters of a list of words,
4771 * producing a space between them.
4772 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004773static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004774{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004775 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004776
4777 if ((wp = *ap->awordlist++) != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004778 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004779 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004780 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004781 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004782}
4783
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004784static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004785{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004786 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004787
4788 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004789 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004790 if ((c = *ap->aword++) == '\0') {
4791 ap->aword = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00004792 return (' ');
Eric Andersenff9eee42001-06-29 04:57:14 +00004793 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004794 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004795}
4796
4797/*
4798 * Produce the characters from a single word (string).
4799 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004800static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004801{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004802 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004803
4804 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004805 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004806 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004807}
4808
4809/*
4810 * Produce quoted characters from a single word (string).
4811 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004812static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004813{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004814 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004815
4816 if (ap->aword == NULL || (c = *ap->aword++) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004817 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004818 return (c | QUOTE);
Eric Andersenff9eee42001-06-29 04:57:14 +00004819}
4820
4821/*
4822 * Return the characters from a file.
4823 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004824static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004825{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004826 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004827 char c;
4828 struct iobuf *bp = ap->afbuf;
4829
4830 if (ap->afid != AFID_NOBUF) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004831 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004832
Eric Andersen8401eea2004-08-04 19:16:54 +00004833 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004834 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004835
Eric Andersen8401eea2004-08-04 19:16:54 +00004836 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004837
Eric Andersen8401eea2004-08-04 19:16:54 +00004838 if (i <= 0) {
4839 closef(ap->afile);
4840 return 0;
4841 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004842
Eric Andersen8401eea2004-08-04 19:16:54 +00004843 bp->id = ap->afid;
4844 bp->ebufp = (bp->bufp = bp->buf) + i;
4845 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004846
Eric Andersen8401eea2004-08-04 19:16:54 +00004847 ap->afpos++;
4848 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004849 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004850#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004851 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004852 static char mycommand[BUFSIZ];
4853 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004854
Eric Andersen8401eea2004-08-04 19:16:54 +00004855 while (size == 0 || position >= size) {
4856 cmdedit_read_input(current_prompt, mycommand);
4857 size = strlen(mycommand);
4858 position = 0;
4859 }
4860 c = mycommand[position];
4861 position++;
4862 return (c);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004863 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00004864#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00004865
Eric Andersenff9eee42001-06-29 04:57:14 +00004866 {
Eric Andersen7467c8d2001-07-12 20:26:32 +00004867 i = safe_read(ap->afile, &c, sizeof(c));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004868 return (i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0));
Eric Andersenff9eee42001-06-29 04:57:14 +00004869 }
4870}
4871
4872/*
4873 * Return the characters from a here temp file.
4874 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004875static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004876{
4877 char c;
4878
4879
4880 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4881 close(ap->afile);
4882 c = 0;
4883 }
4884 return (c);
4885
4886}
4887
4888/*
4889 * Return the characters produced by a process (`...`).
4890 * Quote them if required, and remove any trailing newline characters.
4891 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004892static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004893{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004894 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004895
Eric Andersen8401eea2004-08-04 19:16:54 +00004896 if ((c = qgravechar(ap, iop) & ~QUOTE) == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004897 c = ' ';
Eric Andersen8401eea2004-08-04 19:16:54 +00004898 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004899}
4900
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004901static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004902{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004903 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004904
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004905 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004906
4907 if (iop->xchar) {
4908 if (iop->nlcount) {
4909 iop->nlcount--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004910 return ('\n' | QUOTE);
Eric Andersenff9eee42001-06-29 04:57:14 +00004911 }
4912 c = iop->xchar;
4913 iop->xchar = 0;
4914 } else if ((c = filechar(ap)) == '\n') {
4915 iop->nlcount = 1;
4916 while ((c = filechar(ap)) == '\n')
4917 iop->nlcount++;
4918 iop->xchar = c;
4919 if (c == 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00004920 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004921 iop->nlcount--;
4922 c = '\n';
4923 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004924 return (c != 0 ? c | QUOTE : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004925}
4926
4927/*
4928 * Return a single command (usually the first line) from a file.
4929 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004930static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004931{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004932 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004933
4934 if ((c = filechar(ap)) == '\n') {
4935 if (!multiline) {
4936 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004937 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004938 }
4939 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004940 return (c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004941}
4942
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004943static void prs(const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00004944{
4945 if (*s)
4946 write(2, s, strlen(s));
4947}
4948
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004949static void prn(unsigned u)
Eric Andersenff9eee42001-06-29 04:57:14 +00004950{
Eric Andersen737f5fb2003-03-14 16:05:59 +00004951 prs(itoa(u));
Eric Andersenff9eee42001-06-29 04:57:14 +00004952}
4953
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004954static void closef(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00004955{
4956 if (i > 2)
4957 close(i);
4958}
4959
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004960static void closeall(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004961{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004962 int u;
Eric Andersenff9eee42001-06-29 04:57:14 +00004963
Eric Andersen8401eea2004-08-04 19:16:54 +00004964 for (u = NUFILE; u < NOFILE;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004965 close(u++);
4966}
4967
Eric Andersen12de6cf2004-08-04 19:19:10 +00004968
Eric Andersenff9eee42001-06-29 04:57:14 +00004969/*
4970 * remap fd into Shell's fd space
4971 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004972static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004973{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004974 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004975 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004976 int newfd;
4977
4978
4979 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004980
4981 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004982 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004983 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004984
Eric Andersenff9eee42001-06-29 04:57:14 +00004985 do {
4986 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004987 newfd = dup(fd);
4988 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004989 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004990
Eric Andersen8401eea2004-08-04 19:16:54 +00004991 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004992 if (map[i])
4993 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004994
Eric Andersenff9eee42001-06-29 04:57:14 +00004995 if (fd < 0)
4996 err("too many files open in shell");
4997 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004998
Eric Andersen8401eea2004-08-04 19:16:54 +00004999 return (fd);
Eric Andersenff9eee42001-06-29 04:57:14 +00005000}
5001
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005002static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005003{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005004 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005005
5006 if ((i = pipe(pv)) < 0)
5007 err("can't create pipe - try again");
Eric Andersen8401eea2004-08-04 19:16:54 +00005008 return (i);
Eric Andersenff9eee42001-06-29 04:57:14 +00005009}
5010
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005011static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005012{
5013 if (pv != NULL) {
5014 close(*pv++);
5015 close(*pv);
5016 }
5017}
5018
5019/* -------- here.c -------- */
5020
5021/*
5022 * here documents
5023 */
5024
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005025static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00005026{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005027 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005028
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005029 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00005030
5031 h = (struct here *) space(sizeof(struct here));
5032 if (h == 0)
5033 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005034
Eric Andersenff9eee42001-06-29 04:57:14 +00005035 h->h_tag = evalstr(s, DOSUB);
5036 if (h->h_tag == 0)
5037 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005038
Eric Andersenff9eee42001-06-29 04:57:14 +00005039 h->h_iop = iop;
5040 iop->io_name = 0;
5041 h->h_next = NULL;
5042 if (inhere == 0)
5043 inhere = h;
5044 else
Eric Andersen8401eea2004-08-04 19:16:54 +00005045 for (lh = inhere; lh != NULL; lh = lh->h_next)
Eric Andersenff9eee42001-06-29 04:57:14 +00005046 if (lh->h_next == 0) {
5047 lh->h_next = h;
5048 break;
5049 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005050 iop->io_flag |= IOHERE | IOXHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005051 for (s = h->h_tag; *s; s++)
5052 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005053 iop->io_flag &= ~IOXHERE;
5054 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005055 }
5056 h->h_dosub = iop->io_flag & IOXHERE;
5057}
5058
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005059static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005060{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005061 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005062
5063 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005064
5065 /* Scan here files first leaving inhere list in place */
5066 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005067 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005068
5069 /* Make inhere list active - keep list intact for scraphere */
5070 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005071 hp->h_next = acthere;
5072 acthere = inhere;
5073 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005074 }
5075}
5076
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005077static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005078{
5079 int tf;
5080 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005081 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005082 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005083 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005084 char *thenext;
5085
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005086 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005087
Eric Andersenff9eee42001-06-29 04:57:14 +00005088 tf = mkstemp(tname);
5089 if (tf < 0)
5090 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005091
Eric Andersenff9eee42001-06-29 04:57:14 +00005092 *name = strsave(tname, areanum);
5093 if (newenv(setjmp(errpt = ev)) != 0)
5094 unlink(tname);
5095 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005096 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005097 e.iobase = e.iop;
5098 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005099 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005100#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005101 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005102#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005103 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005104#endif
5105 }
5106 thenext = myline;
5107 while ((c = my_getc(ec)) != '\n' && c) {
5108 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005109 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005110 if (thenext >= &myline[LINELIM]) {
5111 c = 0;
5112 break;
5113 }
5114 *thenext++ = c;
5115 }
5116 *thenext = 0;
5117 if (strcmp(s, myline) == 0 || c == 0)
5118 break;
5119 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005120 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005121 }
5122 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005123 prs("here document `");
5124 prs(s);
5125 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005126 }
5127 quitenv();
5128 }
5129 close(tf);
5130}
5131
5132/*
5133 * open here temp file.
5134 * if unquoted here, expand here temp file into second temp file.
5135 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005136static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005137{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005138 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005139 int tf;
5140
5141#if __GNUC__
5142 /* Avoid longjmp clobbering */
5143 (void) &tf;
5144#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005145 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005146 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005147
5148 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5149
Eric Andersenff9eee42001-06-29 04:57:14 +00005150 hf = open(hname, 0);
5151 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005152 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005153
Eric Andersenff9eee42001-06-29 04:57:14 +00005154 if (xdoll) {
5155 char c;
5156 char tname[30] = ".msh_XXXXXX";
5157 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005158
Eric Andersenff9eee42001-06-29 04:57:14 +00005159 tf = mkstemp(tname);
5160 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005161 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00005162 if (newenv(setjmp(errpt = ev)) == 0) {
5163 PUSHIO(afile, hf, herechar);
5164 setbase(e.iop);
5165 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005166 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005167 write(tf, &c, sizeof c);
5168 }
5169 quitenv();
5170 } else
5171 unlink(tname);
5172 close(tf);
5173 tf = open(tname, 0);
5174 unlink(tname);
5175 return (tf);
5176 } else
5177 return (hf);
5178}
5179
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005180static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005181{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005182 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005183
5184 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005185
5186 for (h = inhere; h != NULL; h = h->h_next) {
5187 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005188 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005189 }
5190 inhere = NULL;
5191}
5192
5193/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005194static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005195{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005196 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005197
5198 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005199
5200 hl = NULL;
5201 for (h = acthere; h != NULL; h = h->h_next)
5202 if (getarea((char *) h) >= area) {
5203 if (h->h_iop->io_name != NULL)
5204 unlink(h->h_iop->io_name);
5205 if (hl == NULL)
5206 acthere = h->h_next;
5207 else
5208 hl->h_next = h->h_next;
5209 } else
5210 hl = h;
5211}
5212
5213
5214
5215/*
5216 * Copyright (c) 1987,1997, Prentice Hall
5217 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005218 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005219 * Redistribution and use of the MINIX operating system in source and
5220 * binary forms, with or without modification, are permitted provided
5221 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005222 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005223 * Redistributions of source code must retain the above copyright
5224 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005225 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005226 * Redistributions in binary form must reproduce the above
5227 * copyright notice, this list of conditions and the following
5228 * disclaimer in the documentation and/or other materials provided
5229 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005230 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005231 * Neither the name of Prentice Hall nor the names of the software
5232 * authors or contributors may be used to endorse or promote
5233 * products derived from this software without specific prior
5234 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005235 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005236 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5237 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5238 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5239 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5240 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5241 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5242 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5243 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5244 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5245 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5246 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5247 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5248 *
5249 */