blob: c88308f8f87bb9038f922f1a23579cb0766399d3 [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
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000141static const char *const 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
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000451//static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000452#define XOTHER 0 /* none of the below */
453#define XDOLL 1 /* expanding ${} */
454#define XGRAVE 2 /* expanding `'s */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000455#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 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000697
698#ifdef MSHDEBUG
699static struct var *mshdbg_var;
700#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000701static struct var *vlist; /* dictionary */
702static struct var *homedir; /* home directory */
703static struct var *prompt; /* main prompt */
704static struct var *cprompt; /* continuation prompt */
705static struct var *path; /* search path for commands */
706static struct var *shell; /* shell to interpret command files */
707static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000708
Eric Andersen8401eea2004-08-04 19:16:54 +0000709static int areanum; /* current allocation area */
710static int intr;
711static int inparse;
Eric Andersen8401eea2004-08-04 19:16:54 +0000712static char *null = "";
713static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000714static void (*qflag) (int) = SIG_IGN;
715static int startl;
716static int peeksym;
717static int nlseen;
718static int iounit = IODEFAULT;
719static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000720static char *elinep = line + sizeof(line) - 5;
721
722static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
723static struct ioarg ioargstack[NPUSH];
724static struct io iostack[NPUSH];
Eric Andersen8401eea2004-08-04 19:16:54 +0000725static struct iobuf sharedbuf = { AFID_NOBUF };
726static struct iobuf mainbuf = { AFID_NOBUF };
Eric Andersenff9eee42001-06-29 04:57:14 +0000727static unsigned bufid = AFID_ID; /* buffer id counter */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000728
Eric Andersen8401eea2004-08-04 19:16:54 +0000729static struct here *inhere; /* list of hear docs while parsing */
730static struct here *acthere; /* list of active here documents */
731static struct region *areabot; /* bottom of area */
732static struct region *areatop; /* top of area */
733static struct region *areanxt; /* starting point of scan */
734static void *brktop;
735static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000736
Eric Andersen12de6cf2004-08-04 19:19:10 +0000737static struct env e = {
738 line, /* linep: char ptr */
739 iostack, /* iobase: struct io ptr */
740 iostack - 1, /* iop: struct io ptr */
741 (xint *) NULL, /* errpt: void ptr for errors? */
742 FDBASE, /* iofd: file desc */
743 (struct env *) NULL /* oenv: struct env ptr */
744};
745
746#ifdef MSHDEBUG
747void print_t(struct op *t)
748{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000749 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
750 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000751
752 if (t->words) {
753 DBGPRINTF(("T: W1: %s", t->words[0]));
754 }
755
756 return;
757}
758
759void print_tree(struct op *head)
760{
761 if (head == NULL) {
762 DBGPRINTF(("PRINT_TREE: no tree\n"));
763 return;
764 }
765
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000766 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000767 head->right));
768
769 if (head->left)
770 print_tree(head->left);
771
772 if (head->right)
773 print_tree(head->right);
774
775 return;
776}
777#endif /* MSHDEBUG */
778
Eric Andersenff9eee42001-06-29 04:57:14 +0000779
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000780#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +0000781static char *current_prompt;
Eric Andersenff9eee42001-06-29 04:57:14 +0000782#endif
783
Eric Andersenff9eee42001-06-29 04:57:14 +0000784/* -------- sh.c -------- */
785/*
786 * shell
787 */
788
789
Rob Landleydfba7412006-03-06 20:47:33 +0000790int msh_main(int argc, char **argv)
Eric Andersenff9eee42001-06-29 04:57:14 +0000791{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000792 int f;
793 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +0000794 int cflag;
795 char *name, **ap;
Eric Andersen8401eea2004-08-04 19:16:54 +0000796 int (*iof) (struct ioarg *);
Eric Andersenff9eee42001-06-29 04:57:14 +0000797
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000798 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000799
Eric Andersenff9eee42001-06-29 04:57:14 +0000800 initarea();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000801 ap = environ;
802 if (ap != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +0000803 while (*ap)
804 assign(*ap++, !COPYV);
805 for (ap = environ; *ap;)
806 export(lookup(*ap++));
807 }
808 closeall();
809 areanum = 1;
810
811 shell = lookup("SHELL");
812 if (shell->value == null)
Eric Andersen78500142004-08-27 19:55:28 +0000813 setval(shell, (char *)DEFAULT_SHELL);
Eric Andersenff9eee42001-06-29 04:57:14 +0000814 export(shell);
815
816 homedir = lookup("HOME");
817 if (homedir->value == null)
818 setval(homedir, "/");
819 export(homedir);
820
Eric Andersen737f5fb2003-03-14 16:05:59 +0000821 setval(lookup("$"), putn(getpid()));
Eric Andersenff9eee42001-06-29 04:57:14 +0000822
823 path = lookup("PATH");
Eric Andersen737f5fb2003-03-14 16:05:59 +0000824 if (path->value == null) {
825 if (geteuid() == 0)
826 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
827 else
828 setval(path, "/bin:/usr/bin");
829 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000830 export(path);
831
832 ifs = lookup("IFS");
833 if (ifs->value == null)
834 setval(ifs, " \t\n");
835
Eric Andersen12de6cf2004-08-04 19:19:10 +0000836#ifdef MSHDEBUG
837 mshdbg_var = lookup("MSHDEBUG");
838 if (mshdbg_var->value == null)
839 setval(mshdbg_var, "0");
840#endif
841
Eric Andersenff9eee42001-06-29 04:57:14 +0000842 prompt = lookup("PS1");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000843#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000844 if (prompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000845#endif
Mike Frysinger2a131752006-06-06 06:26:12 +0000846 setval(prompt, DEFAULT_USER_PROMPT);
Eric Andersenff9eee42001-06-29 04:57:14 +0000847 if (geteuid() == 0) {
Mike Frysinger2a131752006-06-06 06:26:12 +0000848 setval(prompt, DEFAULT_ROOT_PROMPT);
Eric Andersenff9eee42001-06-29 04:57:14 +0000849 prompt->status &= ~EXPORT;
850 }
851 cprompt = lookup("PS2");
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000852#ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
Eric Andersenff9eee42001-06-29 04:57:14 +0000853 if (cprompt->value == null)
Eric Andersen1c039232001-07-07 00:05:55 +0000854#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000855 setval(cprompt, "> ");
856
857 iof = filechar;
858 cflag = 0;
859 name = *argv++;
860 if (--argc >= 1) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000861 if (argv[0][0] == '-' && argv[0][1] != '\0') {
862 for (s = argv[0] + 1; *s; s++)
Eric Andersenff9eee42001-06-29 04:57:14 +0000863 switch (*s) {
864 case 'c':
865 prompt->status &= ~EXPORT;
866 cprompt->status &= ~EXPORT;
867 setval(prompt, "");
868 setval(cprompt, "");
869 cflag = 1;
870 if (--argc > 0)
871 PUSHIO(aword, *++argv, iof = nlchar);
872 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000873
Eric Andersenff9eee42001-06-29 04:57:14 +0000874 case 'q':
875 qflag = SIG_DFL;
876 break;
877
878 case 's':
879 /* standard input */
880 break;
881
882 case 't':
883 prompt->status &= ~EXPORT;
884 setval(prompt, "");
885 iof = linechar;
886 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000887
Eric Andersenff9eee42001-06-29 04:57:14 +0000888 case 'i':
889 interactive++;
890 default:
Eric Andersen8401eea2004-08-04 19:16:54 +0000891 if (*s >= 'a' && *s <= 'z')
892 flag[(int) *s]++;
Eric Andersenff9eee42001-06-29 04:57:14 +0000893 }
894 } else {
895 argv--;
896 argc++;
897 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000898
Eric Andersenff9eee42001-06-29 04:57:14 +0000899 if (iof == filechar && --argc > 0) {
900 setval(prompt, "");
901 setval(cprompt, "");
902 prompt->status &= ~EXPORT;
903 cprompt->status &= ~EXPORT;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000904
905/* Shell is non-interactive, activate printf-based debug */
906#ifdef MSHDEBUG
907 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
908 if (mshdbg < 0)
909 mshdbg = 0;
910#endif
911 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
912
Eric Andersenff9eee42001-06-29 04:57:14 +0000913 if (newfile(name = *++argv))
Eric Andersen12de6cf2004-08-04 19:19:10 +0000914 exit(1); /* Exit on error */
Eric Andersenff9eee42001-06-29 04:57:14 +0000915 }
916 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000917
Eric Andersenff9eee42001-06-29 04:57:14 +0000918 setdash();
Eric Andersen12de6cf2004-08-04 19:19:10 +0000919
920 /* This won't be true if PUSHIO has been called, say from newfile() above */
Eric Andersenff9eee42001-06-29 04:57:14 +0000921 if (e.iop < iostack) {
922 PUSHIO(afile, 0, iof);
Eric Andersen1c039232001-07-07 00:05:55 +0000923 if (isatty(0) && isatty(1) && !cflag) {
Eric Andersenff9eee42001-06-29 04:57:14 +0000924 interactive++;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000925#ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
Eric Andersen12de6cf2004-08-04 19:19:10 +0000926#ifdef MSHDEBUG
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000927 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000928#else
"Vladimir N. Oleynik"dd1ccdd2006-02-16 15:40:24 +0000929 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000930#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000931 printf("Enter 'help' for a list of built-in commands.\n\n");
Eric Andersend63dee42001-10-19 00:22:23 +0000932#endif
Eric Andersen1c039232001-07-07 00:05:55 +0000933 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000934 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000935
Eric Andersenff9eee42001-06-29 04:57:14 +0000936 signal(SIGQUIT, qflag);
937 if (name && name[0] == '-') {
938 interactive++;
939 if ((f = open(".profile", 0)) >= 0)
940 next(remap(f));
941 if ((f = open("/etc/profile", 0)) >= 0)
942 next(remap(f));
943 }
944 if (interactive)
945 signal(SIGTERM, sig);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000946
Eric Andersenff9eee42001-06-29 04:57:14 +0000947 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
948 signal(SIGINT, onintr);
949 dolv = argv;
950 dolc = argc;
951 dolv[0] = name;
952 if (dolc > 1) {
953 for (ap = ++argv; --argc > 0;) {
954 if (assign(*ap = *argv++, !COPYV)) {
Eric Andersen8401eea2004-08-04 19:16:54 +0000955 dolc--; /* keyword */
Eric Andersenff9eee42001-06-29 04:57:14 +0000956 } else {
957 ap++;
958 }
959 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000960 }
Eric Andersenff9eee42001-06-29 04:57:14 +0000961 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
962
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000963 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 +0000964
Eric Andersenff9eee42001-06-29 04:57:14 +0000965 for (;;) {
966 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +0000967#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +0000968 current_prompt = prompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +0000969#else
970 prs(prompt->value);
971#endif
972 }
973 onecommand();
Eric Andersen1c315012002-04-26 23:40:09 +0000974 /* Ensure that getenv("PATH") stays current */
975 setenv("PATH", path->value, 1);
Eric Andersenff9eee42001-06-29 04:57:14 +0000976 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000977
978 DBGPRINTF(("MSH_MAIN: returning.\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +0000979}
980
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000981static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000982{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000983 char *cp;
984 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +0000985 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000986
987 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +0000988 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000989 if (flag[c])
Eric Andersenff9eee42001-06-29 04:57:14 +0000990 *cp++ = c;
991 *cp = 0;
992 setval(lookup("-"), m);
993}
994
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000995static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +0000996{
"Robert P. J. Day"68229832006-07-01 13:08:46 +0000997 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000998
999 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001000
Denis Vlasenko9f739442006-12-16 23:49:13 +00001001 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001002 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001003 f = open(s, 0);
1004 if (f < 0) {
1005 prs(s);
1006 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001007 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001008 }
1009 } else
1010 f = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001011
Eric Andersenff9eee42001-06-29 04:57:14 +00001012 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001013 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001014}
1015
Eric Andersen12de6cf2004-08-04 19:19:10 +00001016
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001017struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001018{
1019 struct op *dotnode;
1020
1021 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001022 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001023
1024 if (head->left != NULL) {
1025 dotnode = scantree(head->left);
1026 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001027 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001028 }
1029
1030 if (head->right != NULL) {
1031 dotnode = scantree(head->right);
1032 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001033 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001034 }
1035
1036 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001037 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001038
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001039 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001040
1041 if ((head->type != TDOT) && (strcmp(".", head->words[0]) == 0)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001042 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001043 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001044 }
1045
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001046 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001047}
1048
1049
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001050static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001051{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001052 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001053 jmp_buf m1;
1054
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001055 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001056
Eric Andersenff9eee42001-06-29 04:57:14 +00001057 while (e.oenv)
1058 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001059
Eric Andersenff9eee42001-06-29 04:57:14 +00001060 areanum = 1;
1061 freehere(areanum);
1062 freearea(areanum);
1063 garbage();
1064 wdlist = 0;
1065 iolist = 0;
1066 e.errpt = 0;
1067 e.linep = line;
1068 yynerrs = 0;
1069 multiline = 0;
1070 inparse = 1;
1071 intr = 0;
1072 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001073
Eric Andersen8401eea2004-08-04 19:16:54 +00001074 setjmp(failpt = m1); /* Bruce Evans' fix */
Eric Andersenff9eee42001-06-29 04:57:14 +00001075 if (setjmp(failpt = m1) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001076
1077 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1078
Eric Andersenff9eee42001-06-29 04:57:14 +00001079 while (e.oenv)
1080 quitenv();
1081 scraphere();
1082 if (!interactive && intr)
1083 leave();
1084 inparse = 0;
1085 intr = 0;
1086 return;
1087 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001088
Eric Andersenff9eee42001-06-29 04:57:14 +00001089 inparse = 0;
1090 brklist = 0;
1091 intr = 0;
1092 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001093
1094 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001095 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001096 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001097 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001098 }
1099
Eric Andersenff9eee42001-06-29 04:57:14 +00001100 if (!interactive && intr) {
1101 execflg = 0;
1102 leave();
1103 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001104
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001105 i = trapset;
1106 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001107 trapset = 0;
1108 runtrap(i);
1109 }
1110}
1111
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001112static void fail(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001113{
1114 longjmp(failpt, 1);
1115 /* NOTREACHED */
1116}
1117
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001118static void leave(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001119{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001120 DBGPRINTF(("LEAVE: leave called!\n"));
1121
Eric Andersenff9eee42001-06-29 04:57:14 +00001122 if (execflg)
1123 fail();
1124 scraphere();
1125 freehere(1);
1126 runtrap(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001127 _exit(exstat);
Eric Andersenff9eee42001-06-29 04:57:14 +00001128 /* NOTREACHED */
1129}
1130
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001131static void warn(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001132{
Eric Andersen8401eea2004-08-04 19:16:54 +00001133 if (*s) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001134 prs(s);
1135 exstat = -1;
1136 }
1137 prs("\n");
1138 if (flag['e'])
1139 leave();
1140}
1141
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001142static void err(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001143{
1144 warn(s);
1145 if (flag['n'])
1146 return;
1147 if (!interactive)
1148 leave();
1149 if (e.errpt)
1150 longjmp(e.errpt, 1);
1151 closeall();
1152 e.iop = e.iobase = iostack;
1153}
1154
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001155static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001156{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001157 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001158
1159 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001160
1161 if (f) {
1162 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001163 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001164 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001165
Eric Andersenff9eee42001-06-29 04:57:14 +00001166 ep = (struct env *) space(sizeof(*ep));
1167 if (ep == NULL) {
1168 while (e.oenv)
1169 quitenv();
1170 fail();
1171 }
1172 *ep = e;
1173 e.oenv = ep;
1174 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001175
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001176 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001177}
1178
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001179static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001180{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001181 struct env *ep;
1182 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001183
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001184 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001185
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001186 ep = e.oenv;
1187 if (ep != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001188 fd = e.iofd;
1189 e = *ep;
1190 /* should close `'d files */
1191 DELETE(ep);
1192 while (--fd >= e.iofd)
1193 close(fd);
1194 }
1195}
1196
1197/*
1198 * Is any character from s1 in s2?
1199 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001200static int anys(char *s1, char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001201{
1202 while (*s1)
1203 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001204 return 1;
1205 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001206}
1207
1208/*
1209 * Is character c in s?
1210 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001211static int any(int c, char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001212{
1213 while (*s)
1214 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001215 return 1;
1216 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001217}
1218
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001219static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001220{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001221 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001222}
1223
Eric Andersen8401eea2004-08-04 19:16:54 +00001224static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001225{
1226 PUSHIO(afile, f, filechar);
1227}
1228
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001229static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001230{
1231 signal(SIGINT, onintr);
1232 intr = 1;
1233 if (interactive) {
1234 if (inparse) {
1235 prs("\n");
1236 fail();
1237 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001238 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001239 execflg = 0;
1240 leave();
1241 }
1242}
1243
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001244static char *space(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001245{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001246 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001247
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001248 cp = getcell(n);
1249 if (cp == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00001250 err("out of string space");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001251 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001252}
1253
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001254static char *strsave(char *s, int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001255{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001256 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001257
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001258 cp = space(strlen(s) + 1);
1259 if (cp != NULL) {
1260 setarea(cp, a);
1261 strcpy(cp, s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001262 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001263 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001264 return "";
Eric Andersenff9eee42001-06-29 04:57:14 +00001265}
1266
1267/*
1268 * trap handling
1269 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001270static void sig(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00001271{
1272 trapset = i;
1273 signal(i, sig);
1274}
1275
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001276static void runtrap(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00001277{
1278 char *trapstr;
1279
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001280 trapstr = trap[i];
1281 if (trapstr == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00001282 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001283
Eric Andersenff9eee42001-06-29 04:57:14 +00001284 if (i == 0)
1285 trap[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001286
Eric Andersenff9eee42001-06-29 04:57:14 +00001287 RUN(aword, trapstr, nlchar);
1288}
1289
1290/* -------- var.c -------- */
1291
1292/*
1293 * Find the given name in the dictionary
1294 * and return its value. If the name was
1295 * not previously there, enter it now and
1296 * return a null value.
1297 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001298static struct var *lookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001299{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001300 struct var *vp;
1301 char *cp;
1302 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001303 static struct var dummy;
1304
1305 if (isdigit(*n)) {
1306 dummy.name = n;
1307 for (c = 0; isdigit(*n) && c < 1000; n++)
Eric Andersen8401eea2004-08-04 19:16:54 +00001308 c = c * 10 + *n - '0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001309 dummy.status = RONLY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001310 dummy.value = c <= dolc ? dolv[c] : null;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001311 return &dummy;
Eric Andersenff9eee42001-06-29 04:57:14 +00001312 }
1313 for (vp = vlist; vp; vp = vp->next)
1314 if (eqname(vp->name, n))
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001315 return vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001316 cp = findeq(n);
Eric Andersen8401eea2004-08-04 19:16:54 +00001317 vp = (struct var *) space(sizeof(*vp));
1318 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001319 dummy.name = dummy.value = "";
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001320 return &dummy;
Eric Andersenff9eee42001-06-29 04:57:14 +00001321 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001322 for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001323 if (*cp == 0)
1324 *cp = '=';
1325 *++cp = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00001326 setarea((char *) vp, 0);
1327 setarea((char *) vp->name, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001328 vp->value = null;
1329 vp->next = vlist;
1330 vp->status = GETCELL;
1331 vlist = vp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001332 return vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001333}
1334
1335/*
1336 * give variable at `vp' the value `val'.
1337 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001338static void setval(struct var *vp, char *val)
Eric Andersenff9eee42001-06-29 04:57:14 +00001339{
Eric Andersen8401eea2004-08-04 19:16:54 +00001340 nameval(vp, val, (char *) NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001341}
1342
1343/*
1344 * if name is not NULL, it must be
1345 * a prefix of the space `val',
1346 * and end with `='.
1347 * this is all so that exporting
1348 * values is reasonably painless.
1349 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001350static void nameval(struct var *vp, char *val, char *name)
Eric Andersenff9eee42001-06-29 04:57:14 +00001351{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001352 char *cp, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001353 char *nv;
1354 int fl;
1355
1356 if (vp->status & RONLY) {
1357 for (xp = vp->name; *xp && *xp != '=';)
1358 putc(*xp++, stderr);
1359 err(" is read-only");
1360 return;
1361 }
1362 fl = 0;
1363 if (name == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001364 xp = space(strlen(vp->name) + strlen(val) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00001365 if (xp == 0)
1366 return;
1367 /* make string: name=value */
Eric Andersen8401eea2004-08-04 19:16:54 +00001368 setarea((char *) xp, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001369 name = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001370 for (cp = vp->name; (*xp = *cp++) && *xp != '='; xp++);
Eric Andersenff9eee42001-06-29 04:57:14 +00001371 if (*xp++ == 0)
1372 xp[-1] = '=';
1373 nv = xp;
Eric Andersen8401eea2004-08-04 19:16:54 +00001374 for (cp = val; (*xp++ = *cp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00001375 val = nv;
1376 fl = GETCELL;
1377 }
1378 if (vp->status & GETCELL)
Eric Andersen8401eea2004-08-04 19:16:54 +00001379 freecell(vp->name); /* form new string `name=value' */
Eric Andersenff9eee42001-06-29 04:57:14 +00001380 vp->name = name;
1381 vp->value = val;
1382 vp->status |= fl;
1383}
1384
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001385static void export(struct var *vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001386{
1387 vp->status |= EXPORT;
1388}
1389
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001390static void ronly(struct var *vp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001391{
Matt Kraai69edfec2001-08-06 14:14:18 +00001392 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
Eric Andersenff9eee42001-06-29 04:57:14 +00001393 vp->status |= RONLY;
1394}
1395
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001396static int isassign(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001397{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001398 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1399
Eric Andersen8401eea2004-08-04 19:16:54 +00001400 if (!isalpha((int) *s) && *s != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001401 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001402 for (; *s != '='; s++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001403 if (*s == 0 || (!isalnum(*s) && *s != '_'))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001404 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001405
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001406 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001407}
1408
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001409static int assign(char *s, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001410{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001411 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001412 struct var *vp;
1413
Eric Andersen12de6cf2004-08-04 19:19:10 +00001414 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1415
Matt Kraai69edfec2001-08-06 14:14:18 +00001416 if (!isalpha(*s) && *s != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001417 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001418 for (cp = s; *cp != '='; cp++)
Matt Kraai69edfec2001-08-06 14:14:18 +00001419 if (*cp == 0 || (!isalnum(*cp) && *cp != '_'))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001420 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001421 vp = lookup(s);
Eric Andersen8401eea2004-08-04 19:16:54 +00001422 nameval(vp, ++cp, cf == COPYV ? (char *) NULL : s);
Eric Andersenff9eee42001-06-29 04:57:14 +00001423 if (cf != COPYV)
1424 vp->status &= ~GETCELL;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001425 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001426}
1427
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001428static int checkname(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001429{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001430 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1431
Eric Andersen8401eea2004-08-04 19:16:54 +00001432 if (!isalpha(*cp++) && *(cp - 1) != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001433 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001434 while (*cp)
Eric Andersen8401eea2004-08-04 19:16:54 +00001435 if (!isalnum(*cp++) && *(cp - 1) != '_')
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001436 return 0;
1437 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001438}
1439
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001440static void putvlist(int f, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00001441{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001442 struct var *vp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001443
1444 for (vp = vlist; vp; vp = vp->next)
Matt Kraai69edfec2001-08-06 14:14:18 +00001445 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001446 if (vp->status & EXPORT)
1447 write(out, "export ", 7);
1448 if (vp->status & RONLY)
1449 write(out, "readonly ", 9);
Eric Andersen8401eea2004-08-04 19:16:54 +00001450 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
Eric Andersenff9eee42001-06-29 04:57:14 +00001451 write(out, "\n", 1);
1452 }
1453}
1454
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001455static int eqname(char *n1, char *n2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001456{
1457 for (; *n1 != '=' && *n1 != 0; n1++)
1458 if (*n2++ != *n1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001459 return 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001460 return *n2 == 0 || *n2 == '=';
Eric Andersenff9eee42001-06-29 04:57:14 +00001461}
1462
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001463static char *findeq(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001464{
1465 while (*cp != '\0' && *cp != '=')
1466 cp++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001467 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00001468}
1469
1470/* -------- gmatch.c -------- */
1471/*
1472 * int gmatch(string, pattern)
1473 * char *string, *pattern;
1474 *
1475 * Match a pattern as in sh(1).
1476 */
1477
1478#define CMASK 0377
1479#define QUOTE 0200
1480#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001481#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001482
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001483static int gmatch(char *s, char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001484{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001485 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001486
1487 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001488 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001489 while ((pc = *p++ & CMASK) != '\0') {
1490 sc = *s++ & QMASK;
1491 switch (pc) {
1492 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001493 p = cclass(p, sc);
1494 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001495 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001496 break;
1497
1498 case '?':
1499 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001500 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001501 break;
1502
1503 case '*':
1504 s--;
1505 do {
1506 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001507 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001508 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001509 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001510
1511 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001512 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001513 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001514 }
1515 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001516 return *s == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001517}
1518
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001519static char *cclass(char *p, int sub)
Eric Andersenff9eee42001-06-29 04:57:14 +00001520{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001521 int c, d, not, found;
Eric Andersenff9eee42001-06-29 04:57:14 +00001522
1523 if ((not = *p == NOT) != 0)
1524 p++;
1525 found = not;
1526 do {
1527 if (*p == '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001528 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001529 c = *p & CMASK;
1530 if (p[1] == '-' && p[2] != ']') {
1531 d = p[2] & CMASK;
1532 p++;
1533 } else
1534 d = c;
1535 if (c == sub || (c <= sub && sub <= d))
1536 found = !not;
1537 } while (*++p != ']');
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001538 return found ? p + 1 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001539}
1540
1541
1542/* -------- area.c -------- */
1543
1544/*
1545 * All memory between (char *)areabot and (char *)(areatop+1) is
1546 * exclusively administered by the area management routines.
1547 * It is assumed that sbrk() and brk() manipulate the high end.
1548 */
1549
1550#define sbrk(X) ({ void * __q = (void *)-1; if (brkaddr + (int)(X) < brktop) { __q = brkaddr; brkaddr+=(int)(X); } __q;})
1551
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001552static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001553{
Mike Frysinger3132e9d2006-06-02 06:30:30 +00001554 brkaddr = xmalloc(AREASIZE);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001555 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +00001556
Eric Andersena68ea1c2006-01-30 22:48:39 +00001557 while ((long) sbrk(0) & ALIGN)
Eric Andersenff9eee42001-06-29 04:57:14 +00001558 sbrk(1);
Eric Andersen8401eea2004-08-04 19:16:54 +00001559 areabot = (struct region *) sbrk(REGSIZE);
Eric Andersenff9eee42001-06-29 04:57:14 +00001560
1561 areabot->next = areabot;
1562 areabot->area = BUSY;
1563 areatop = areabot;
1564 areanxt = areabot;
1565}
1566
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001567char *getcell(unsigned nbytes)
Eric Andersenff9eee42001-06-29 04:57:14 +00001568{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001569 int nregio;
1570 struct region *p, *q;
1571 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001572
1573 if (nbytes == 0) {
1574 puts("getcell(0)");
1575 abort();
Eric Andersen8401eea2004-08-04 19:16:54 +00001576 }
1577 /* silly and defeats the algorithm */
Eric Andersenff9eee42001-06-29 04:57:14 +00001578 /*
1579 * round upwards and add administration area
1580 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001581 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001582 for (p = areanxt;;) {
1583 if (p->area > areanum) {
1584 /*
1585 * merge free cells
1586 */
1587 while ((q = p->next)->area > areanum && q != areanxt)
1588 p->next = q->next;
1589 /*
1590 * exit loop if cell big enough
1591 */
1592 if (q >= p + nregio)
1593 goto found;
1594 }
1595 p = p->next;
1596 if (p == areanxt)
1597 break;
1598 }
1599 i = nregio >= GROWBY ? nregio : GROWBY;
Eric Andersen8401eea2004-08-04 19:16:54 +00001600 p = (struct region *) sbrk(i * REGSIZE);
1601 if (p == (struct region *) -1)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001602 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001603 p--;
1604 if (p != areatop) {
1605 puts("not contig");
Eric Andersen8401eea2004-08-04 19:16:54 +00001606 abort(); /* allocated areas are contiguous */
Eric Andersenff9eee42001-06-29 04:57:14 +00001607 }
1608 q = p + i;
1609 p->next = q;
1610 p->area = FREE;
1611 q->next = areabot;
1612 q->area = BUSY;
1613 areatop = q;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001614 found:
Eric Andersenff9eee42001-06-29 04:57:14 +00001615 /*
1616 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
1617 */
1618 areanxt = p + nregio;
1619 if (areanxt < q) {
1620 /*
1621 * split into requested area and rest
1622 */
Eric Andersen8401eea2004-08-04 19:16:54 +00001623 if (areanxt + 1 > q) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001624 puts("OOM");
Eric Andersen8401eea2004-08-04 19:16:54 +00001625 abort(); /* insufficient space left for admin */
Eric Andersenff9eee42001-06-29 04:57:14 +00001626 }
1627 areanxt->next = q;
1628 areanxt->area = FREE;
1629 p->next = areanxt;
1630 }
1631 p->area = areanum;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001632 return (char *) (p + 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00001633}
1634
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001635static void freecell(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001636{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001637 struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001638
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001639 p = (struct region *) cp;
1640 if (p != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001641 p--;
1642 if (p < areanxt)
1643 areanxt = p;
1644 p->area = FREE;
1645 }
1646}
1647
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001648static void freearea(int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001649{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001650 struct region *p, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001651
1652 top = areatop;
1653 for (p = areabot; p != top; p = p->next)
1654 if (p->area >= a)
1655 p->area = FREE;
1656}
1657
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001658static void setarea(char *cp, int a)
Eric Andersenff9eee42001-06-29 04:57:14 +00001659{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001660 struct region *p;
Eric Andersenff9eee42001-06-29 04:57:14 +00001661
Eric Andersen8401eea2004-08-04 19:16:54 +00001662 if ((p = (struct region *) cp) != NULL)
1663 (p - 1)->area = a;
Eric Andersenff9eee42001-06-29 04:57:14 +00001664}
1665
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001666int getarea(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00001667{
Eric Andersen8401eea2004-08-04 19:16:54 +00001668 return ((struct region *) cp - 1)->area;
Eric Andersenff9eee42001-06-29 04:57:14 +00001669}
1670
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001671static void garbage(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001672{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001673 struct region *p, *q, *top;
Eric Andersenff9eee42001-06-29 04:57:14 +00001674
1675 top = areatop;
1676 for (p = areabot; p != top; p = p->next) {
1677 if (p->area > areanum) {
1678 while ((q = p->next)->area > areanum)
1679 p->next = q->next;
1680 areanxt = p;
1681 }
1682 }
1683#ifdef SHRINKBY
1684 if (areatop >= q + SHRINKBY && q->area > areanum) {
Eric Andersen8401eea2004-08-04 19:16:54 +00001685 brk((char *) (q + 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00001686 q->next = areabot;
1687 q->area = BUSY;
1688 areatop = q;
1689 }
1690#endif
1691}
1692
1693/* -------- csyn.c -------- */
1694/*
1695 * shell: syntax (C version)
1696 */
1697
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001698int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001699{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001700 DBGPRINTF7(("YYPARSE: enter...\n"));
1701
Eric Andersen8401eea2004-08-04 19:16:54 +00001702 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001703 peeksym = 0;
1704 yynerrs = 0;
1705 outtree = c_list();
1706 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001707 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001708}
1709
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001710static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001711{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001712 struct op *t, *p;
1713 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001714
1715 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001716
1717 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001718
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001719 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001720
Eric Andersenff9eee42001-06-29 04:57:14 +00001721 if (t != NULL) {
1722 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001723 p = command(CONTIN);
1724 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001725 DBGPRINTF8(("PIPELINE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001726 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001727 }
1728
Eric Andersenff9eee42001-06-29 04:57:14 +00001729 if (t->type != TPAREN && t->type != TCOM) {
1730 /* shell statement */
1731 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1732 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001733
Eric Andersenff9eee42001-06-29 04:57:14 +00001734 t = block(TPIPE, t, p, NOWORDS);
1735 }
1736 peeksym = c;
1737 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001738
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001739 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001740 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001741}
1742
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001743static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001744{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001745 struct op *t, *p;
1746 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001747
1748 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001749
1750 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001751
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001752 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001753
Eric Andersenff9eee42001-06-29 04:57:14 +00001754 if (t != NULL) {
1755 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001756 p = pipeline(CONTIN);
1757 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001758 DBGPRINTF8(("ANDOR: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001759 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001760 }
1761
Eric Andersen8401eea2004-08-04 19:16:54 +00001762 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001763 } /* WHILE */
1764
Eric Andersenff9eee42001-06-29 04:57:14 +00001765 peeksym = c;
1766 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001767
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001768 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001769 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001770}
1771
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001772static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001773{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001774 struct op *t, *p;
1775 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001776
1777 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001778
1779 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001780
Eric Andersenff9eee42001-06-29 04:57:14 +00001781 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001782 peeksym = yylex(0);
1783 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001784 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001785
Eric Andersen8401eea2004-08-04 19:16:54 +00001786 while ((c = yylex(0)) == ';' || c == '&'
1787 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001788
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001789 p = andor();
1790 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001791 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001792
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001793 peeksym = yylex(0);
1794 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001795 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001796
Eric Andersenff9eee42001-06-29 04:57:14 +00001797 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001798 } /* WHILE */
1799
Eric Andersenff9eee42001-06-29 04:57:14 +00001800 peeksym = c;
1801 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001802 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001803 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001804 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001805}
1806
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001807static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001808{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001809 struct ioword *iop;
1810 int i;
1811 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001812
1813 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001814
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001815 c = yylex(cf);
1816 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001817 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001818 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001819 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001820
Eric Andersenff9eee42001-06-29 04:57:14 +00001821 i = yylval.i;
1822 musthave(WORD, 0);
1823 iop = io(iounit, i, yylval.cp);
1824 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001825
Eric Andersenff9eee42001-06-29 04:57:14 +00001826 if (i & IOHERE)
1827 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001828
1829 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001830 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001831}
1832
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001833static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001834{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001835 if ((peeksym = yylex(cf)) != c) {
1836 DBGPRINTF7(("MUSTHAVE: error!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001837 SYNTAXERR;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001838 }
1839
Eric Andersenff9eee42001-06-29 04:57:14 +00001840 peeksym = 0;
1841}
1842
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001843static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001844{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001845 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001846
1847 t = NULL;
1848 for (;;) {
1849 switch (peeksym = yylex(0)) {
1850 case '<':
1851 case '>':
1852 (void) synio(0);
1853 break;
1854
1855 case WORD:
1856 if (t == NULL) {
1857 t = newtp();
1858 t->type = TCOM;
1859 }
1860 peeksym = 0;
1861 word(yylval.cp);
1862 break;
1863
1864 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001865 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001866 }
1867 }
1868}
1869
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001870static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001871{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001872 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001873
1874 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001875
1876 multiline++;
1877 t = c_list();
1878 musthave(mark, 0);
1879 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001880 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001881}
1882
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001883static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001884{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001885 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001886 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001887 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001888
1889 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001890
1891 iosave = iolist;
1892 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001893
Eric Andersenff9eee42001-06-29 04:57:14 +00001894 if (multiline)
1895 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001896
Eric Andersenff9eee42001-06-29 04:57:14 +00001897 while (synio(cf))
1898 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001899
1900 c = yylex(cf);
1901
1902 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001903 default:
1904 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001905 t = simple();
1906 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001907 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001908 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001909 t = newtp();
1910 t->type = TCOM;
1911 }
1912 break;
1913
1914 case '(':
1915 t = nested(TPAREN, ')');
1916 break;
1917
1918 case '{':
1919 t = nested(TBRACE, '}');
1920 break;
1921
1922 case FOR:
1923 t = newtp();
1924 t->type = TFOR;
1925 musthave(WORD, 0);
1926 startl = 1;
1927 t->str = yylval.cp;
1928 multiline++;
1929 t->words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001930 c = yylex(0);
1931 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001932 peeksym = c;
1933 t->left = dogroup(0);
1934 multiline--;
1935 break;
1936
1937 case WHILE:
1938 case UNTIL:
1939 multiline++;
1940 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001941 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001942 t->left = c_list();
1943 t->right = dogroup(1);
1944 t->words = NULL;
1945 multiline--;
1946 break;
1947
1948 case CASE:
1949 t = newtp();
1950 t->type = TCASE;
1951 musthave(WORD, 0);
1952 t->str = yylval.cp;
1953 startl++;
1954 multiline++;
1955 musthave(IN, CONTIN);
1956 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001957
Eric Andersenff9eee42001-06-29 04:57:14 +00001958 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001959
Eric Andersenff9eee42001-06-29 04:57:14 +00001960 musthave(ESAC, 0);
1961 multiline--;
1962 break;
1963
1964 case IF:
1965 multiline++;
1966 t = newtp();
1967 t->type = TIF;
1968 t->left = c_list();
1969 t->right = thenpart();
1970 musthave(FI, 0);
1971 multiline--;
1972 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001973
1974 case DOT:
1975 t = newtp();
1976 t->type = TDOT;
1977
1978 musthave(WORD, 0); /* gets name of file */
1979 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1980
1981 word(yylval.cp); /* add word to wdlist */
1982 word(NOWORD); /* terminate wdlist */
1983 t->words = copyw(); /* dup wdlist */
1984 break;
1985
Eric Andersenff9eee42001-06-29 04:57:14 +00001986 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001987
Eric Andersen8401eea2004-08-04 19:16:54 +00001988 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001989
Eric Andersenff9eee42001-06-29 04:57:14 +00001990 t = namelist(t);
1991 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001992
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001993 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001994
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001995 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001996}
1997
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001998static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001999{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002000 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002001
2002 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
2003
2004 multiline++;
2005 t = c_list();
2006 multiline--;
2007 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002008 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002009 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002010}
2011
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002012static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00002013{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002014 int c;
2015 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002016
2017 c = yylex(CONTIN);
2018 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002019 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002020 if (c != DO)
2021 SYNTAXERR;
2022 mylist = c_list();
2023 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002024 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002025}
2026
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002027static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002028{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002029 int c;
2030 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002031
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002032 c = yylex(0);
2033 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002034 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002035 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002036 }
2037 t = newtp();
2038 t->type = 0;
2039 t->left = c_list();
2040 if (t->left == NULL)
2041 SYNTAXERR;
2042 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002043 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002044}
2045
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002046static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002047{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002048 int c;
2049 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002050
2051 switch (c = yylex(0)) {
2052 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002053 t = c_list();
2054 if (t == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002055 SYNTAXERR;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002056 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002057
2058 case ELIF:
2059 t = newtp();
2060 t->type = TELIF;
2061 t->left = c_list();
2062 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002063 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002064
2065 default:
2066 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002067 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002068 }
2069}
2070
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002071static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002072{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002073 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002074
2075 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002076 while ((peeksym = yylex(CONTIN)) != ESAC) {
2077 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00002078 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00002079 }
2080
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002081 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002082 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002083}
2084
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002085static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002086{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002087 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002088
2089 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002090
2091 t = newtp();
2092 t->type = TPAT;
2093 t->words = pattern();
2094 musthave(')', 0);
2095 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002096 peeksym = yylex(CONTIN);
2097 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00002098 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002099
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002100 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002101
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002102 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002103}
2104
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002105static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002106{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002107 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00002108
2109 cf = CONTIN;
2110 do {
2111 musthave(WORD, cf);
2112 word(yylval.cp);
2113 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002114 c = yylex(0);
2115 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00002116 peeksym = c;
2117 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002118
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002119 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002120}
2121
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002122static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002123{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002124 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002125
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002126 c = yylex(0);
2127 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002128 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002129 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002130 }
2131 startl = 0;
2132 while ((c = yylex(0)) == WORD)
2133 word(yylval.cp);
2134 word(NOWORD);
2135 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002136 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002137}
2138
2139/*
2140 * supporting functions
2141 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002142static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00002143{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002144 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002145
Eric Andersenff9eee42001-06-29 04:57:14 +00002146 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002147 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002148 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002149 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002150
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002151 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00002152}
2153
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002154static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002155{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002156 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002157
2158 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002159
2160 t = newtp();
2161 t->type = type;
2162 t->left = t1;
2163 t->right = t2;
2164 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002165
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002166 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002167 t2));
2168
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002169 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002170}
2171
Eric Andersen12de6cf2004-08-04 19:19:10 +00002172/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002173static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002174{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002175 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002176
2177 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002178
2179 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002180 if (strcmp(rp->r_name, n) == 0) {
2181 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002182 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002183 }
2184
2185 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002186 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002187}
2188
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002189static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002190{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002191 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002192
Eric Andersen8401eea2004-08-04 19:16:54 +00002193 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002194 t->type = 0;
2195 t->words = NULL;
2196 t->ioact = NULL;
2197 t->left = NULL;
2198 t->right = NULL;
2199 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002200
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002201 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002202
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002203 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002204}
2205
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002206static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002207{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002208
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002209 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002210 T_CMD_NAMES[t->type], iolist));
2211
Eric Andersenff9eee42001-06-29 04:57:14 +00002212 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002213 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002214 t->ioact = copyio();
2215 } else
2216 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002217
Eric Andersenff9eee42001-06-29 04:57:14 +00002218 if (t->type != TCOM) {
2219 if (t->type != TPAREN && t->ioact != NULL) {
2220 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2221 t->ioact = t->left->ioact;
2222 t->left->ioact = NULL;
2223 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002224 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002225 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002226
Eric Andersenff9eee42001-06-29 04:57:14 +00002227 word(NOWORD);
2228 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002229
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002230 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002231}
2232
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002233static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002234{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002235 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002236
2237 wd = getwords(wdlist);
2238 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002239 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002240}
2241
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002242static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002243{
2244 wdlist = addword(cp, wdlist);
2245}
2246
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002247static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002248{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002249 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002250
2251 iop = (struct ioword **) getwords(iolist);
2252 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002253 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002254}
2255
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002256static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002257{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002258 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002259
2260 iop = (struct ioword *) tree(sizeof(*iop));
2261 iop->io_unit = u;
2262 iop->io_flag = f;
2263 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002264 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002265 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002266}
2267
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002268static void zzerr(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002269{
2270 yyerror("syntax error");
2271}
2272
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002273static void yyerror(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00002274{
2275 yynerrs++;
2276 if (interactive && e.iop <= iostack) {
2277 multiline = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002278 while (eofc() == 0 && yylex(0) != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002279 }
2280 err(s);
2281 fail();
2282}
2283
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002284static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002285{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002286 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002287 int atstart;
2288
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002289 c = peeksym;
2290 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002291 peeksym = 0;
2292 if (c == '\n')
2293 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002294 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002295 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002296
2297
Eric Andersenff9eee42001-06-29 04:57:14 +00002298 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002299 atstart = startl;
2300 startl = 0;
2301 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002302 e.linep = line;
2303
2304/* MALAMO */
2305 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002306
Eric Andersen8401eea2004-08-04 19:16:54 +00002307 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002308 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2309 ;
2310
Eric Andersenff9eee42001-06-29 04:57:14 +00002311 switch (c) {
2312 default:
2313 if (any(c, "0123456789")) {
2314 unget(c1 = my_getc(0));
2315 if (c1 == '<' || c1 == '>') {
2316 iounit = c - '0';
2317 goto loop;
2318 }
2319 *e.linep++ = c;
2320 c = c1;
2321 }
2322 break;
2323
Eric Andersen12de6cf2004-08-04 19:19:10 +00002324 case '#': /* Comment, skip to next newline or End-of-string */
Eric Andersen8401eea2004-08-04 19:16:54 +00002325 while ((c = my_getc(0)) != 0 && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002326 unget(c);
2327 goto loop;
2328
2329 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002330 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002331 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002332
2333 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002334 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002335 *e.linep++ = c;
2336 if ((c = my_getc(0)) == '{') {
2337 if ((c = collect(c, '}')) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002338 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002339 goto pack;
2340 }
2341 break;
2342
2343 case '`':
2344 case '\'':
2345 case '"':
2346 if ((c = collect(c, c)) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002347 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002348 goto pack;
2349
2350 case '|':
2351 case '&':
2352 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002353 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002354 /* If more chars process them, else return NULL char */
2355 if ((c1 = dual(c)) != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002356 return c1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002357 else
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002358 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002359
Eric Andersenff9eee42001-06-29 04:57:14 +00002360 case '^':
2361 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002362 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002363 case '>':
2364 case '<':
2365 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002366 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002367
2368 case '\n':
2369 nlseen++;
2370 gethere();
2371 startl = 1;
2372 if (multiline || cf & CONTIN) {
2373 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002374#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002375 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002376#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002377 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002378#endif
2379 }
2380 if (cf & CONTIN)
2381 goto loop;
2382 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002383 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002384
2385 case '(':
2386 case ')':
2387 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002388 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002389 }
2390
2391 unget(c);
2392
Eric Andersen8401eea2004-08-04 19:16:54 +00002393 pack:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002394 while ((c = my_getc(0)) != 0 && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002395 if (e.linep >= elinep)
2396 err("word too long");
2397 else
2398 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002399 };
2400
Eric Andersenff9eee42001-06-29 04:57:14 +00002401 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002402
Eric Andersen8401eea2004-08-04 19:16:54 +00002403 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002404 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002405
Eric Andersenff9eee42001-06-29 04:57:14 +00002406 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002407
Eric Andersen8401eea2004-08-04 19:16:54 +00002408 if (atstart && (c = rlookup(line)) != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002409 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002410 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002411 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002412
Eric Andersenff9eee42001-06-29 04:57:14 +00002413 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002414 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002415}
2416
Eric Andersen12de6cf2004-08-04 19:19:10 +00002417
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002418static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002419{
2420 char s[2];
2421
Eric Andersen12de6cf2004-08-04 19:19:10 +00002422 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2423
Eric Andersenff9eee42001-06-29 04:57:14 +00002424 *e.linep++ = c;
2425 while ((c = my_getc(c1)) != c1) {
2426 if (c == 0) {
2427 unget(c);
2428 s[0] = c1;
2429 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002430 prs("no closing ");
2431 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002432 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002433 }
2434 if (interactive && c == '\n' && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00002435#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002436 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002437#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002438 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002439#endif
2440 }
2441 *e.linep++ = c;
2442 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002443
Eric Andersenff9eee42001-06-29 04:57:14 +00002444 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002445
2446 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2447
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002448 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002449}
2450
Eric Andersen12de6cf2004-08-04 19:19:10 +00002451/* "multiline commands" helper func */
2452/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002453static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002454{
2455 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002456 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002457
Eric Andersen12de6cf2004-08-04 19:19:10 +00002458 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2459
2460 *cp++ = c; /* c is the given "peek" char */
2461 *cp++ = my_getc(0); /* get next char of input */
2462 *cp = 0; /* add EOS marker */
2463
2464 c = rlookup(s); /* see if 2 chars form a shell multiline */
2465 if (c == 0)
2466 unget(*--cp); /* String is not a shell multiline, put peek char back */
2467
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002468 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002469}
2470
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002471static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002472{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002473 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002474
2475 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002476
2477 c = my_getc(0);
2478 if (c == '>' || c == '<') {
2479 if (c != ec)
2480 zzerr();
Eric Andersen8401eea2004-08-04 19:16:54 +00002481 yylval.i = ec == '>' ? IOWRITE | IOCAT : IOHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002482 c = my_getc(0);
2483 } else
Eric Andersen8401eea2004-08-04 19:16:54 +00002484 yylval.i = ec == '>' ? IOWRITE : IOREAD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002485 if (c != '&' || yylval.i == IOHERE)
2486 unget(c);
2487 else
2488 yylval.i |= IODUP;
2489}
2490
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002491static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002492{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002493 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002494
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002495 t = getcell(size);
2496 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002497 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002498 prs("command line too complicated\n");
2499 fail();
2500 /* NOTREACHED */
2501 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002502 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002503}
2504
2505/* VARARGS1 */
2506/* ARGSUSED */
2507
2508/* -------- exec.c -------- */
2509
2510/*
2511 * execute tree
2512 */
2513
2514
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002515static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002516{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002517 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002518 volatile int i, rv, a;
2519 char *cp, **wp, **wp2;
2520 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002521 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002522 struct brkcon bc;
2523
2524#if __GNUC__
2525 /* Avoid longjmp clobbering */
2526 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002527#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002528
Eric Andersen12de6cf2004-08-04 19:19:10 +00002529 if (t == NULL) {
2530 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002531 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002532 }
2533
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002534 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002535 t->type, T_CMD_NAMES[t->type],
2536 ((t->words == NULL) ? "NULL" : t->words[0])));
2537
Eric Andersenff9eee42001-06-29 04:57:14 +00002538 rv = 0;
2539 a = areanum++;
2540 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002541 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2542 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002543
Eric Andersen8401eea2004-08-04 19:16:54 +00002544 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002545 case TDOT:
2546 DBGPRINTF3(("EXECUTE: TDOT\n"));
2547
2548 outtree_save = outtree;
2549
2550 newfile(evalstr(t->words[0], DOALL));
2551
2552 t->left = dowholefile(TLIST, 0);
2553 t->right = NULL;
2554
2555 outtree = outtree_save;
2556
2557 if (t->left)
2558 rv = execute(t->left, pin, pout, 0);
2559 if (t->right)
2560 rv = execute(t->right, pin, pout, 0);
2561 break;
2562
Eric Andersenff9eee42001-06-29 04:57:14 +00002563 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002564 rv = execute(t->left, pin, pout, 0);
2565 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002566
Eric Andersenff9eee42001-06-29 04:57:14 +00002567 case TCOM:
Eric Andersen1c039232001-07-07 00:05:55 +00002568 {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002569 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002570 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002571 break;
2572
2573 case TPIPE:
2574 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002575 int pv[2];
2576
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002577 rv = openpipe(pv);
2578 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002579 break;
2580 pv[0] = remap(pv[0]);
2581 pv[1] = remap(pv[1]);
2582 (void) execute(t->left, pin, pv, 0);
2583 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002584 }
2585 break;
2586
2587 case TLIST:
2588 (void) execute(t->left, pin, pout, 0);
2589 rv = execute(t->right, pin, pout, 0);
2590 break;
2591
2592 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002593 {
2594 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002595
Eric Andersen12de6cf2004-08-04 19:19:10 +00002596 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2597
Eric Andersen8401eea2004-08-04 19:16:54 +00002598 i = vfork();
2599 if (i != 0) {
2600 interactive = hinteractive;
2601 if (i != -1) {
2602 setval(lookup("!"), putn(i));
2603 if (pin != NULL)
2604 closepipe(pin);
2605 if (interactive) {
2606 prs(putn(i));
2607 prs("\n");
2608 }
2609 } else
2610 rv = -1;
2611 setstatus(rv);
2612 } else {
2613 signal(SIGINT, SIG_IGN);
2614 signal(SIGQUIT, SIG_IGN);
2615 if (interactive)
2616 signal(SIGTERM, SIG_DFL);
2617 interactive = 0;
2618 if (pin == NULL) {
2619 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002620 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002621 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002622 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002623 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002624 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002625 break;
2626
2627 case TOR:
2628 case TAND:
2629 rv = execute(t->left, pin, pout, 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002630 t1 = t->right;
2631 if (t1 != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002632 rv = execute(t1, pin, pout, 0);
2633 break;
2634
2635 case TFOR:
2636 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002637 wp = dolv + 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002638 if ((i = dolc) < 0)
2639 i = 0;
2640 } else {
2641 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002642 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002643 }
2644 vp = lookup(t->str);
2645 while (setjmp(bc.brkpt))
2646 if (isbreak)
2647 goto broken;
2648 brkset(&bc);
2649 for (t1 = t->left; i-- && *wp != NULL;) {
2650 setval(vp, *wp++);
2651 rv = execute(t1, pin, pout, 0);
2652 }
2653 brklist = brklist->nextlev;
2654 break;
2655
2656 case TWHILE:
2657 case TUNTIL:
2658 while (setjmp(bc.brkpt))
2659 if (isbreak)
2660 goto broken;
2661 brkset(&bc);
2662 t1 = t->left;
2663 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2664 rv = execute(t->right, pin, pout, 0);
2665 brklist = brklist->nextlev;
2666 break;
2667
2668 case TIF:
2669 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002670 if (t->right != NULL) {
2671 rv = !execute(t->left, pin, pout, 0) ?
2672 execute(t->right->left, pin, pout, 0) :
2673 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002674 }
2675 break;
2676
2677 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002678 cp = evalstr(t->str, DOSUB | DOTRIM);
2679 if (cp == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002680 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002681
2682 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2683 ((t->str == NULL) ? "NULL" : t->str),
2684 ((cp == NULL) ? "NULL" : cp)));
2685
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002686 t1 = findcase(t->left, cp);
2687 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002688 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002689 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002690 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002691 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002692 break;
2693
2694 case TBRACE:
2695/*
2696 if (iopp = t->ioact)
2697 while (*iopp)
2698 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2699 rv = -1;
2700 break;
2701 }
2702*/
2703 if (rv >= 0 && (t1 = t->left))
2704 rv = execute(t1, pin, pout, 0);
2705 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002706
2707 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002708
Eric Andersen8401eea2004-08-04 19:16:54 +00002709 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002710 t->words = wp2;
2711 isbreak = 0;
2712 freehere(areanum);
2713 freearea(areanum);
2714 areanum = a;
2715 if (interactive && intr) {
2716 closeall();
2717 fail();
2718 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002719
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002720 i = trapset;
2721 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002722 trapset = 0;
2723 runtrap(i);
2724 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002725
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002726 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002727 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002728}
2729
2730static int
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002731forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002732{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002733 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002734 int i, rv;
Eric Andersen8401eea2004-08-04 19:16:54 +00002735 int (*shcom) (struct op *) = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002736 int f;
Eric Andersenff9eee42001-06-29 04:57:14 +00002737 char *cp = NULL;
2738 struct ioword **iopp;
2739 int resetsig;
2740 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002741 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002742
2743 int *hpin = pin;
2744 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002745 char *hwp;
2746 int hinteractive;
2747 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002748 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002749 int hexecflg;
2750
2751#if __GNUC__
2752 /* Avoid longjmp clobbering */
2753 (void) &pin;
2754 (void) &pout;
2755 (void) &wp;
2756 (void) &shcom;
2757 (void) &cp;
2758 (void) &resetsig;
2759 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002760#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002761
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002762 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002763 pout, act));
2764 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2765 ((t->words == NULL) ? "NULL" : t->words[0])));
2766
Eric Andersenff9eee42001-06-29 04:57:14 +00002767 owp = wp;
2768 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002769 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002770 if (t->type == TCOM) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002771 while ((cp = *wp++) != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002772 cp = *wp;
2773
2774 /* strip all initial assignments */
2775 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002776 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002777 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002778 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002779 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002780 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002781
Eric Andersenff9eee42001-06-29 04:57:14 +00002782 if (cp == NULL && t->ioact == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002783 while ((cp = *owp++) != NULL && assign(cp, COPYV));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002784 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002785 return setstatus(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002786 } else if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002787 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002788 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002789 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002790
Eric Andersenff9eee42001-06-29 04:57:14 +00002791 t->words = wp;
2792 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002793
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002794 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002795 f & FEXEC, owp));
2796
2797 if (shcom == NULL && (f & FEXEC) == 0) {
2798 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002799 hpin = pin;
2800 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002801 hwp = *wp;
2802 hinteractive = interactive;
2803 hintr = intr;
2804 hbrklist = brklist;
2805 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002806
Eric Andersen12de6cf2004-08-04 19:19:10 +00002807 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2808
2809 newpid = vfork();
2810
2811 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002812 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002813 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002814 }
2815
2816
2817 if (newpid > 0) { /* Parent */
2818
2819 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002820 pin = hpin;
2821 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002822 *wp = hwp;
2823 interactive = hinteractive;
2824 intr = hintr;
2825 brklist = hbrklist;
2826 execflg = hexecflg;
2827
Eric Andersen12de6cf2004-08-04 19:19:10 +00002828/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002829 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002830 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002831*/
2832
Eric Andersenff9eee42001-06-29 04:57:14 +00002833 if (pin != NULL)
2834 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002835
2836 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002837 }
2838
Eric Andersen12de6cf2004-08-04 19:19:10 +00002839 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002840 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002841
Eric Andersenff9eee42001-06-29 04:57:14 +00002842 if (interactive) {
2843 signal(SIGINT, SIG_IGN);
2844 signal(SIGQUIT, SIG_IGN);
2845 resetsig = 1;
2846 }
2847 interactive = 0;
2848 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002849 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002850 brklist = 0;
2851 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002852 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002853
2854
Eric Andersenff9eee42001-06-29 04:57:14 +00002855 if (owp != NULL)
2856 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2857 if (shcom == NULL)
2858 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002859
Eric Andersenff9eee42001-06-29 04:57:14 +00002860#ifdef COMPIPE
2861 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2862 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002863 if (forked)
2864 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002865 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002866 }
2867#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002868
Eric Andersenff9eee42001-06-29 04:57:14 +00002869 if (pin != NULL) {
2870 dup2(pin[0], 0);
2871 closepipe(pin);
2872 }
2873 if (pout != NULL) {
2874 dup2(pout[1], 1);
2875 closepipe(pout);
2876 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002877
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002878 iopp = t->ioact;
2879 if (iopp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002880 if (shcom != NULL && shcom != doexec) {
2881 prs(cp);
2882 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002883 if (forked)
2884 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002885 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002886 }
2887 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002888 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2889 if (forked)
2890 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002891 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002892 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002893 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002894
2895 if (shcom) {
2896 i = setstatus((*shcom) (t));
2897 if (forked)
2898 _exit(i);
2899 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002900 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002901 }
2902
Eric Andersenff9eee42001-06-29 04:57:14 +00002903 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002904 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002905 close(i);
2906 if (resetsig) {
2907 signal(SIGINT, SIG_DFL);
2908 signal(SIGQUIT, SIG_DFL);
2909 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002910
Eric Andersen12de6cf2004-08-04 19:19:10 +00002911 if (t->type == TPAREN)
2912 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2913 if (wp[0] == NULL)
2914 _exit(0);
2915
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002916 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002917 prs(wp[0]);
2918 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002919 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002920 if (!execflg)
2921 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002922
2923 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2924
Eric Andersenff9eee42001-06-29 04:57:14 +00002925 leave();
2926 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002927 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002928}
2929
2930/*
2931 * 0< 1> are ignored as required
2932 * within pipelines.
2933 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002934static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002935{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002936 int u = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002937 char *cp = NULL, *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002938
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002939 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002940 pipein, pipeout));
2941
Eric Andersenff9eee42001-06-29 04:57:14 +00002942 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002943 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002944
Eric Andersenff9eee42001-06-29 04:57:14 +00002945 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002946 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002947
Eric Andersenff9eee42001-06-29 04:57:14 +00002948 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002949 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002950
Eric Andersen8401eea2004-08-04 19:16:54 +00002951 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002952 if ((iop->io_flag & IOHERE) == 0) {
2953 cp = iop->io_name;
Eric Andersen8401eea2004-08-04 19:16:54 +00002954 if ((cp = evalstr(cp, DOSUB | DOTRIM)) == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002955 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002956 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002957
Eric Andersenff9eee42001-06-29 04:57:14 +00002958 if (iop->io_flag & IODUP) {
2959 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2960 prs(cp);
2961 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002962 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002963 }
2964 if (*cp == '-')
2965 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002966 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002967 }
2968 switch (iop->io_flag) {
2969 case IOREAD:
2970 u = open(cp, 0);
2971 break;
2972
2973 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002974 case IOHERE | IOXHERE:
2975 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002976 cp = "here file";
2977 break;
2978
Eric Andersen8401eea2004-08-04 19:16:54 +00002979 case IOWRITE | IOCAT:
Eric Andersenff9eee42001-06-29 04:57:14 +00002980 if ((u = open(cp, 1)) >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002981 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002982 break;
2983 }
2984 case IOWRITE:
2985 u = creat(cp, 0666);
2986 break;
2987
2988 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002989 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002990 break;
2991
2992 case IOCLOSE:
2993 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002994 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002995 }
2996 if (u < 0) {
2997 prs(cp);
2998 prs(": cannot ");
2999 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003000 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003001 } else {
3002 if (u != iop->io_unit) {
3003 dup2(u, iop->io_unit);
3004 close(u);
3005 }
3006 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003007 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003008}
3009
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003010static void echo(char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003011{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003012 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003013
3014 prs("+");
Eric Andersen8401eea2004-08-04 19:16:54 +00003015 for (i = 0; wp[i]; i++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003016 if (i)
3017 prs(" ");
3018 prs(wp[i]);
3019 }
3020 prs("\n");
3021}
3022
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003023static struct op **find1case(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003024{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003025 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003026 struct op **tp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003027 char **wp, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003028
Eric Andersen12de6cf2004-08-04 19:19:10 +00003029
3030 if (t == NULL) {
3031 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003032 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003033 }
3034
3035 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
3036 T_CMD_NAMES[t->type]));
3037
Eric Andersenff9eee42001-06-29 04:57:14 +00003038 if (t->type == TLIST) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003039 if ((tp = find1case(t->left, w)) != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003040 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003041 return tp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003042 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003043 t1 = t->right; /* TPAT */
Eric Andersenff9eee42001-06-29 04:57:14 +00003044 } else
3045 t1 = t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003046
Eric Andersenff9eee42001-06-29 04:57:14 +00003047 for (wp = t1->words; *wp;)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003048 if ((cp = evalstr(*wp++, DOSUB)) && gmatch(w, cp)) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003049 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003050 &t1->left));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003051 return &t1->left;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003052 }
3053
3054 DBGPRINTF(("FIND1CASE: returning NULL\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003055 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003056}
3057
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003058static struct op *findcase(struct op *t, char *w)
Eric Andersenff9eee42001-06-29 04:57:14 +00003059{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003060 struct op **tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003061
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003062 tp = find1case(t, w);
3063 return tp != NULL ? *tp : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003064}
3065
3066/*
3067 * Enter a new loop level (marked for break/continue).
3068 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003069static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00003070{
3071 bc->nextlev = brklist;
3072 brklist = bc;
3073}
3074
3075/*
3076 * Wait for the last process created.
3077 * Print a message for each process found
3078 * that was killed by a signal.
3079 * Ignore interrupt signals while waiting
3080 * unless `canintr' is true.
3081 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003082static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00003083{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003084 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003085 int s;
3086 int oheedint = heedint;
3087
3088 heedint = 0;
3089 rv = 0;
3090 do {
3091 pid = wait(&s);
3092 if (pid == -1) {
3093 if (errno != EINTR || canintr)
3094 break;
3095 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003096 rv = WAITSIG(s);
3097 if (rv != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003098 if (rv < NSIGNAL) {
3099 if (signame[rv] != NULL) {
3100 if (pid != lastpid) {
3101 prn(pid);
3102 prs(": ");
3103 }
3104 prs(signame[rv]);
3105 }
3106 } else {
3107 if (pid != lastpid) {
3108 prn(pid);
3109 prs(": ");
3110 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003111 prs("Signal ");
3112 prn(rv);
3113 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003114 }
3115 if (WAITCORE(s))
3116 prs(" - core dumped");
3117 if (rv >= NSIGNAL || signame[rv])
3118 prs("\n");
3119 rv = -1;
3120 } else
3121 rv = WAITVAL(s);
3122 }
3123 } while (pid != lastpid);
3124 heedint = oheedint;
3125 if (intr) {
3126 if (interactive) {
3127 if (canintr)
3128 intr = 0;
3129 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003130 if (exstat == 0)
3131 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003132 onintr(0);
3133 }
3134 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003135 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003136}
3137
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003138static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003139{
3140 exstat = s;
3141 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003142 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003143}
3144
3145/*
3146 * PATH-searching interface to execve.
3147 * If getenv("PATH") were kept up-to-date,
3148 * execvp might be used.
3149 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003150static char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003151{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003152 int i;
3153 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003154 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003155 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003156
Rob Landleya299efb2006-08-10 21:46:43 +00003157 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
3158 optind = 1;
3159 if (find_applet_by_name(name)) {
3160 /* We have to exec here since we vforked. Running
3161 * run_applet_by_name() won't work and bad things
3162 * will happen. */
3163 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
3164 }
Eric Andersen1c039232001-07-07 00:05:55 +00003165 }
Eric Andersen1c039232001-07-07 00:05:55 +00003166
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003167 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003168
Eric Andersen8401eea2004-08-04 19:16:54 +00003169 sp = any('/', c) ? "" : path->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00003170 asis = *sp == '\0';
3171 while (asis || *sp != '\0') {
3172 asis = 0;
3173 tp = e.linep;
3174 for (; *sp != '\0'; tp++)
3175 if ((*tp = *sp++) == ':') {
3176 asis = *sp == '\0';
3177 break;
3178 }
3179 if (tp != e.linep)
3180 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003181 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003182
Eric Andersen12de6cf2004-08-04 19:19:10 +00003183 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3184
Eric Andersenff9eee42001-06-29 04:57:14 +00003185 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003186
Eric Andersenff9eee42001-06-29 04:57:14 +00003187 switch (errno) {
3188 case ENOEXEC:
3189 *v = e.linep;
3190 tp = *--v;
3191 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003192 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003193 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003194 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003195
3196 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003197 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003198
3199 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003200 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003201
3202 case EACCES:
3203 eacces++;
3204 break;
3205 }
3206 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003207 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003208}
3209
3210/*
3211 * Run the command produced by generator `f'
3212 * applied to stream `arg'.
3213 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003214static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003215{
3216 struct op *otree;
3217 struct wdblock *swdlist;
3218 struct wdblock *siolist;
3219 jmp_buf ev, rt;
3220 xint *ofail;
3221 int rv;
3222
3223#if __GNUC__
3224 /* Avoid longjmp clobbering */
3225 (void) &rv;
3226#endif
3227
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003228 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003229 areanum, outtree, failpt));
3230
Eric Andersenff9eee42001-06-29 04:57:14 +00003231 areanum++;
3232 swdlist = wdlist;
3233 siolist = iolist;
3234 otree = outtree;
3235 ofail = failpt;
3236 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003237
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003238 errpt = ev;
3239 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003240 wdlist = 0;
3241 iolist = 0;
3242 pushio(argp, f);
3243 e.iobase = e.iop;
3244 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003245 failpt = rt;
3246 if (setjmp(failpt) == 0 && yyparse() == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003247 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3248 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003249 } else {
3250 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003251 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003252
Eric Andersenff9eee42001-06-29 04:57:14 +00003253 wdlist = swdlist;
3254 iolist = siolist;
3255 failpt = ofail;
3256 outtree = otree;
3257 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003258
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003259 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003260}
3261
3262/* -------- do.c -------- */
3263
3264/*
3265 * built-in commands: doX
3266 */
3267
Eric Andersen8401eea2004-08-04 19:16:54 +00003268static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003269{
3270 int col;
3271 const struct builtincmd *x;
3272
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003273 puts("\nBuilt-in commands:\n"
3274 "-------------------");
Eric Andersen1c039232001-07-07 00:05:55 +00003275
Eric Andersen8401eea2004-08-04 19:16:54 +00003276 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003277 if (!x->name)
3278 continue;
3279 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3280 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003281 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003282 col = 0;
3283 }
3284 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00003285#ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003286 {
3287 int i;
3288 const struct BB_applet *applet;
Eric Andersen1c039232001-07-07 00:05:55 +00003289
Eric Andersen8401eea2004-08-04 19:16:54 +00003290 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003291 if (!applet->name)
3292 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003293
Eric Andersen8401eea2004-08-04 19:16:54 +00003294 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003295 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003296 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003297 col = 0;
3298 }
3299 }
3300 }
3301#endif
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003302 puts("\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003303 return EXIT_SUCCESS;
3304}
3305
3306
3307
Eric Andersen8401eea2004-08-04 19:16:54 +00003308static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003309{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003310 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003311}
3312
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003313static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003314{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003315 char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003316
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003317 cp = t->words[1];
3318 if (cp == NULL && (cp = homedir->value) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003319 er = ": no home directory";
Eric Andersen8401eea2004-08-04 19:16:54 +00003320 else if (chdir(cp) < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003321 er = ": bad directory";
3322 else
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003323 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003324 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003325 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003326 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003327}
3328
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003329static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003330{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003331 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003332
Eric Andersen8401eea2004-08-04 19:16:54 +00003333 n = t->words[1] ? getn(t->words[1]) : 1;
3334 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003335 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003336 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003337 }
3338 dolv[n] = dolv[0];
3339 dolv += n;
3340 dolc -= n;
3341 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003342 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003343}
3344
3345/*
3346 * execute login and newgrp directly
3347 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003348static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003349{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003350 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003351
3352 if (interactive) {
3353 signal(SIGINT, SIG_DFL);
3354 signal(SIGQUIT, SIG_DFL);
3355 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003356 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003357 prs(t->words[0]);
3358 prs(": ");
3359 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003360 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003361}
3362
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003363static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003364{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003365 int i, n;
3366 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003367
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003368 cp = t->words[1];
3369 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003370 i = umask(0);
3371 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003372 for (n = 3 * 4; (n -= 3) >= 0;)
3373 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003374 putc('\n', stderr);
3375 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003376 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3377 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003378 umask(n);
3379 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003380 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003381}
3382
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003383static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003384{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003385 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003386 jmp_buf ex;
3387 xint *ofail;
3388
3389 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003390 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003391 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003392 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003393 execflg = 1;
3394 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003395 failpt = ex;
3396 if (setjmp(failpt) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003397 execute(t, NOPIPE, NOPIPE, FEXEC);
3398 failpt = ofail;
3399 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003400 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003401}
3402
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003403static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003404{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003405 int i;
3406 char *sp, *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003407 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003408 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003409
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003410 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 +00003411
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003412 cp = t->words[1];
3413 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003414 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003415 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003416 } else {
3417 DBGPRINTF(("DODOT: cp is %s\n", cp));
3418 }
3419
Eric Andersen8401eea2004-08-04 19:16:54 +00003420 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003421
3422 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3423 ((sp == NULL) ? "NULL" : sp),
3424 ((e.linep == NULL) ? "NULL" : e.linep)));
3425
Eric Andersenff9eee42001-06-29 04:57:14 +00003426 while (*sp) {
3427 tp = e.linep;
3428 while (*sp && (*tp = *sp++) != ':')
3429 tp++;
3430 if (tp != e.linep)
3431 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003432
Eric Andersen8401eea2004-08-04 19:16:54 +00003433 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003434
3435 /* Original code */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003436 i = open(e.linep, 0);
3437 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003438 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003439 maltmp = remap(i);
3440 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3441
3442 next(maltmp); /* Basically a PUSHIO */
3443
3444 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3445
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003446 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003447 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003448
3449 } /* While */
3450
Eric Andersenff9eee42001-06-29 04:57:14 +00003451 prs(cp);
3452 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003453
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003454 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003455}
3456
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003457static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003458{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003459 int i;
3460 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003461
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003462 cp = t->words[1];
3463 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003464 i = getn(cp);
3465 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003466 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003467 } else
3468 i = -1;
3469 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003470 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003471}
3472
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003473static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003474{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003475 char *cp, **wp;
3476 int nb = 0;
3477 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003478
3479 if (t->words[1] == NULL) {
3480 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003481 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003482 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003483 for (wp = t->words + 1; *wp; wp++) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003484 for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
3485 nb = read(0, cp, sizeof(*cp));
3486 if (nb != sizeof(*cp) || (nl = (*cp == '\n'))
3487 || (wp[1] && any(*cp, ifs->value))
3488 ) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003489 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003490 }
3491 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003492 *cp = 0;
3493 if (nb <= 0)
3494 break;
3495 setval(lookup(*wp), e.linep);
3496 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003497 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003498}
3499
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003500static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003501{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003502 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003503}
3504
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003505static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003506{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003507 int n, i;
3508 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003509
3510 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003511 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003512 if (trap[i]) {
3513 prn(i);
3514 prs(": ");
3515 prs(trap[i]);
3516 prs("\n");
3517 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003518 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003519 }
3520 resetsig = isdigit(*t->words[1]);
3521 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3522 n = getsig(t->words[i]);
3523 freecell(trap[n]);
3524 trap[n] = 0;
3525 if (!resetsig) {
3526 if (*t->words[1] != '\0') {
3527 trap[n] = strsave(t->words[1], 0);
3528 setsig(n, sig);
3529 } else
3530 setsig(n, SIG_IGN);
3531 } else {
3532 if (interactive)
3533 if (n == SIGINT)
3534 setsig(n, onintr);
3535 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003536 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Eric Andersenff9eee42001-06-29 04:57:14 +00003537 else
3538 setsig(n, SIG_DFL);
3539 }
3540 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003541 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003542}
3543
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003544static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003545{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003546 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003547
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003548 n = getn(s);
3549 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003550 err("trap: bad signal number");
3551 n = 0;
3552 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003553 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003554}
3555
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003556static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003557{
3558 if (n == 0)
3559 return;
3560 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3561 ourtrap[n] = 1;
3562 signal(n, f);
3563 }
3564}
3565
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003566static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003567{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003568 char *s;
3569 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003570
3571 s = as;
3572 m = 1;
3573 if (*s == '-') {
3574 m = -1;
3575 s++;
3576 }
3577 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003578 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003579 if (*s) {
3580 prs(as);
3581 err(": bad number");
3582 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003583 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003584}
3585
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003586static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003587{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003588 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003589}
3590
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003591static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003592{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003593 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003594}
3595
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003596static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003597{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003598 struct brkcon *bc;
3599 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003600
Eric Andersen8401eea2004-08-04 19:16:54 +00003601 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003602 if (nl <= 0)
3603 nl = 999;
3604 do {
3605 if ((bc = brklist) == NULL)
3606 break;
3607 brklist = bc->nextlev;
3608 } while (--nl);
3609 if (nl) {
3610 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003611 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003612 }
3613 isbreak = val;
3614 longjmp(bc->brkpt, 1);
3615 /* NOTREACHED */
3616}
3617
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003618static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003619{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003620 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003621
3622 execflg = 0;
3623 if ((cp = t->words[1]) != NULL)
3624 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003625
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003626 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003627
Eric Andersenff9eee42001-06-29 04:57:14 +00003628 leave();
3629 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003630 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003631}
3632
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003633static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003634{
Eric Andersen8401eea2004-08-04 19:16:54 +00003635 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003636 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003637}
3638
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003639static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003640{
Eric Andersen8401eea2004-08-04 19:16:54 +00003641 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003642 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003643}
3644
Eric Andersen8401eea2004-08-04 19:16:54 +00003645static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003646{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003647 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003648 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3649
Eric Andersenff9eee42001-06-29 04:57:14 +00003650 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003651 for (; *wp != NULL; wp++) {
3652 if (isassign(*wp)) {
3653 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003654
Matt Kraaif69bfc72001-07-12 19:39:59 +00003655 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003656 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003657 *cp = '\0';
3658 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003659 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003660 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003661 else
3662 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003663 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003664 } else
3665 putvlist(key, 1);
3666}
3667
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003668static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003669{
3670 prs(s);
3671 err(": bad identifier");
3672}
3673
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003674static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003675{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003676 struct var *vp;
3677 char *cp;
3678 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003679
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003680 cp = t->words[1];
3681 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003682 for (vp = vlist; vp; vp = vp->next)
3683 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003684 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003685 }
3686 if (*cp == '-') {
3687 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003688 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003689 if (*++cp == 0)
3690 flag['x'] = flag['v'] = 0;
3691 else
3692 for (; *cp; cp++)
3693 switch (*cp) {
3694 case 'e':
3695 if (!interactive)
3696 flag['e']++;
3697 break;
3698
3699 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003700 if (*cp >= 'a' && *cp <= 'z')
3701 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003702 break;
3703 }
3704 setdash();
3705 }
3706 if (t->words[1]) {
3707 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003708 for (n = 1; t->words[n]; n++)
3709 setarea((char *) t->words[n], 0);
3710 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003711 dolv = t->words;
3712 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003713 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003714 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003715 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003716}
3717
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003718static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003719{
Matt Kraai69edfec2001-08-06 14:14:18 +00003720 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003721 write(out, s, strlen(s));
3722 write(out, "\n", 1);
3723 }
3724}
3725
3726
3727/*
3728 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3729 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003730 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003731static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003732{
3733 struct tms buf;
3734 long int clk_tck = sysconf(_SC_CLK_TCK);
3735
3736 times(&buf);
3737 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003738 (int) (buf.tms_utime / clk_tck / 60),
3739 ((double) buf.tms_utime) / clk_tck,
3740 (int) (buf.tms_stime / clk_tck / 60),
3741 ((double) buf.tms_stime) / clk_tck,
3742 (int) (buf.tms_cutime / clk_tck / 60),
3743 ((double) buf.tms_cutime) / clk_tck,
3744 (int) (buf.tms_cstime / clk_tck / 60),
3745 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003746 return 0;
3747}
3748
3749
Eric Andersen8401eea2004-08-04 19:16:54 +00003750static int (*inbuilt(char *s)) (struct op *) {
Eric Andersen1c039232001-07-07 00:05:55 +00003751 const struct builtincmd *bp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003752
Eric Andersen1c039232001-07-07 00:05:55 +00003753 for (bp = builtincmds; bp->name != NULL; bp++)
3754 if (strcmp(bp->name, s) == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003755 return bp->builtinfunc;
Eric Andersen1c039232001-07-07 00:05:55 +00003756
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003757 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003758}
3759
3760/* -------- eval.c -------- */
3761
3762/*
3763 * ${}
3764 * `command`
3765 * blank interpretation
3766 * quoting
3767 * glob
3768 */
3769
Eric Andersen8401eea2004-08-04 19:16:54 +00003770static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003771{
3772 struct wdblock *wb;
3773 char **wp;
3774 char **wf;
3775 jmp_buf ev;
3776
3777#if __GNUC__
3778 /* Avoid longjmp clobbering */
3779 (void) &wp;
3780 (void) &ap;
3781#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003782
3783 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3784
Eric Andersenff9eee42001-06-29 04:57:14 +00003785 wp = NULL;
3786 wb = NULL;
3787 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003788 errpt = ev;
3789 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003790 while (*ap && isassign(*ap))
3791 expand(*ap++, &wb, f & ~DOGLOB);
3792 if (flag['k']) {
3793 for (wf = ap; *wf; wf++) {
3794 if (isassign(*wf))
3795 expand(*wf, &wb, f & ~DOGLOB);
3796 }
3797 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003798 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003799 if (!flag['k'] || !isassign(*ap))
3800 expand(*ap, &wb, f & ~DOKEY);
3801 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003802 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003803 wp = getwords(wb);
3804 quitenv();
3805 } else
3806 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003807
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003808 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003809}
3810
3811/*
3812 * Make the exported environment from the exported
3813 * names in the dictionary. Keyword assignments
3814 * will already have been done.
3815 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003816static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003817{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003818 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003819
3820 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003821
Eric Andersenff9eee42001-06-29 04:57:14 +00003822 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003823 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003824 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003825 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003826 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003827}
3828
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003829static char *evalstr(char *cp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003830{
3831 struct wdblock *wb;
3832
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003833 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003834
Eric Andersenff9eee42001-06-29 04:57:14 +00003835 wb = NULL;
3836 if (expand(cp, &wb, f)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003837 if (wb == NULL || wb->w_nword == 0
3838 || (cp = wb->w_words[0]) == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003839 cp = "";
3840 DELETE(wb);
3841 } else
3842 cp = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003843 return cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003844}
3845
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003846static int expand(char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003847{
3848 jmp_buf ev;
3849
3850#if __GNUC__
3851 /* Avoid longjmp clobbering */
3852 (void) &cp;
3853#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003854
3855 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3856
Eric Andersenff9eee42001-06-29 04:57:14 +00003857 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003858
Eric Andersenff9eee42001-06-29 04:57:14 +00003859 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003860 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003861
Eric Andersenff9eee42001-06-29 04:57:14 +00003862 if (!anys("$`'\"", cp) &&
Eric Andersen8401eea2004-08-04 19:16:54 +00003863 !anys(ifs->value, cp) && ((f & DOGLOB) == 0 || !anys("[*?", cp))) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003864 cp = strsave(cp, areanum);
3865 if (f & DOTRIM)
3866 unquote(cp);
3867 *wbp = addword(cp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003868 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003869 }
3870 if (newenv(setjmp(errpt = ev)) == 0) {
3871 PUSHIO(aword, cp, strchar);
3872 e.iobase = e.iop;
3873 while ((cp = blank(f)) && gflg == 0) {
3874 e.linep = cp;
3875 cp = strsave(cp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003876 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003877 if (f & DOTRIM)
3878 unquote(cp);
3879 *wbp = addword(cp, *wbp);
3880 } else
3881 *wbp = glob(cp, *wbp);
3882 }
3883 quitenv();
3884 } else
3885 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003886 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003887}
3888
3889/*
3890 * Blank interpretation and quoting
3891 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003892static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003893{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003894 int c, c1;
3895 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003896 int scanequals, foundequals;
3897
Eric Andersen12de6cf2004-08-04 19:19:10 +00003898 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3899
Eric Andersenff9eee42001-06-29 04:57:14 +00003900 sp = e.linep;
3901 scanequals = f & DOKEY;
3902 foundequals = 0;
3903
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003904 loop:
3905 c = subgetc('"', foundequals);
3906 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003907 case 0:
3908 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003909 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003910 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003911 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003912
3913 default:
3914 if (f & DOBLANK && any(c, ifs->value))
3915 goto loop;
3916 break;
3917
3918 case '"':
3919 case '\'':
3920 scanequals = 0;
3921 if (INSUB())
3922 break;
3923 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3924 if (c == 0)
3925 break;
3926 if (c == '\'' || !any(c, "$`\""))
3927 c |= QUOTE;
3928 *e.linep++ = c;
3929 }
3930 c = 0;
3931 }
3932 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003933 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003934 scanequals = 0;
3935 for (;;) {
3936 c = subgetc('"', foundequals);
3937 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003938 f & (DOBLANK && any(c, ifs->value)) ||
3939 (!INSUB() && any(c, "\"'"))) {
3940 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003941 unget(c);
3942 if (any(c, "\"'"))
3943 goto loop;
3944 break;
3945 }
3946 if (scanequals) {
3947 if (c == '=') {
3948 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003949 scanequals = 0;
3950 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003951 scanequals = 0;
3952 }
3953 *e.linep++ = c;
3954 }
3955 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003956 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003957}
3958
3959/*
3960 * Get characters, substituting for ` and $
3961 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003962static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003963{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003964 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003965
3966 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003967
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003968 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003969 c = my_getc(ec);
3970 if (!INSUB() && ec != '\'') {
3971 if (c == '`') {
3972 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003973 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003974 e.iop->task = XGRAVE;
3975 goto again;
3976 }
3977 if (c == '$' && (c = dollar(quoted)) == 0) {
3978 e.iop->task = XDOLL;
3979 goto again;
3980 }
3981 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003982 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003983}
3984
3985/*
3986 * Prepare to generate the string returned by ${} substitution.
3987 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003988static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003989{
3990 int otask;
3991 struct io *oiop;
3992 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003993 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003994 struct var *vp;
3995
Eric Andersen12de6cf2004-08-04 19:19:10 +00003996 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3997
Eric Andersenff9eee42001-06-29 04:57:14 +00003998 c = readc();
3999 s = e.linep;
4000 if (c != '{') {
4001 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00004002 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00004003 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00004004 if (e.linep < elinep)
4005 *e.linep++ = c;
4006 unget(c);
4007 }
4008 c = 0;
4009 } else {
4010 oiop = e.iop;
4011 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004012
Eric Andersenff9eee42001-06-29 04:57:14 +00004013 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00004014 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004015 if (e.linep < elinep)
4016 *e.linep++ = c;
4017 if (oiop == e.iop)
4018 e.iop->task = otask;
4019 if (c != '}') {
4020 err("unclosed ${");
4021 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004022 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004023 }
4024 }
4025 if (e.linep >= elinep) {
4026 err("string in ${} too long");
4027 gflg++;
4028 e.linep -= 10;
4029 }
4030 *e.linep = 0;
4031 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00004032 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004033 if (any(*cp, "=-+?")) {
4034 c = *cp;
4035 *cp++ = 0;
4036 break;
4037 }
4038 if (s[1] == 0 && (*s == '*' || *s == '@')) {
4039 if (dolc > 1) {
4040 /* currently this does not distinguish $* and $@ */
4041 /* should check dollar */
4042 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00004043 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004044 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00004045 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00004046 s[0] = '1';
4047 s[1] = 0;
4048 }
4049 }
4050 vp = lookup(s);
4051 if ((dolp = vp->value) == null) {
4052 switch (c) {
4053 case '=':
4054 if (isdigit(*s)) {
4055 err("cannot use ${...=...} with $n");
4056 gflg++;
4057 break;
4058 }
4059 setval(vp, cp);
4060 dolp = vp->value;
4061 break;
4062
4063 case '-':
4064 dolp = strsave(cp, areanum);
4065 break;
4066
4067 case '?':
4068 if (*cp == 0) {
4069 prs("missing value for ");
4070 err(s);
4071 } else
4072 err(cp);
4073 gflg++;
4074 break;
4075 }
4076 } else if (c == '+')
4077 dolp = strsave(cp, areanum);
4078 if (flag['u'] && dolp == null) {
4079 prs("unset variable: ");
4080 err(s);
4081 gflg++;
4082 }
4083 e.linep = s;
4084 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004085 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004086}
4087
4088/*
4089 * Run the command in `...` and read its output.
4090 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004091
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004092static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004093{
Eric Andersenff9eee42001-06-29 04:57:14 +00004094 char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004095 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004096 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004097 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00004098 static char child_cmd[LINELIM];
4099 char *src;
4100 char *dest;
4101 int count;
4102 int ignore;
4103 int ignore_once;
4104 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004105 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004106
4107#if __GNUC__
4108 /* Avoid longjmp clobbering */
4109 (void) &cp;
4110#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004111
Eric Andersenff9eee42001-06-29 04:57:14 +00004112 for (cp = e.iop->argp->aword; *cp != '`'; cp++)
4113 if (*cp == 0) {
4114 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004115 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004116 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004117
4118 /* string copy with dollar expansion */
4119 src = e.iop->argp->aword;
4120 dest = child_cmd;
4121 count = 0;
4122 ignore = 0;
4123 ignore_once = 0;
4124 while ((*src != '`') && (count < LINELIM)) {
4125 if (*src == '\'')
4126 ignore = !ignore;
4127 if (*src == '\\')
4128 ignore_once = 1;
4129 if (*src == '$' && !ignore && !ignore_once) {
4130 struct var *vp;
4131 char var_name[LINELIM];
4132 char alt_value[LINELIM];
4133 int var_index = 0;
4134 int alt_index = 0;
4135 char operator = 0;
4136 int braces = 0;
4137 char *value;
4138
4139 src++;
4140 if (*src == '{') {
4141 braces = 1;
4142 src++;
4143 }
4144
4145 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004146 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004147 var_name[var_index++] = *src++;
4148 var_name[var_index] = 0;
4149
4150 if (braces) {
4151 switch (*src) {
4152 case '}':
4153 break;
4154 case '-':
4155 case '=':
4156 case '+':
4157 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004158 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004159 break;
4160 default:
4161 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004162 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004163 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004164 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004165 src++;
4166 while (*src && (*src != '}')) {
4167 alt_value[alt_index++] = *src++;
4168 }
4169 alt_value[alt_index] = 0;
4170 if (*src != '}') {
4171 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004172 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004173 }
4174 }
4175 src++;
4176 }
4177
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004178 if (isalpha(*var_name)) {
4179 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004180
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004181 char *namep = var_name;
4182
4183 *dest++ = '$';
4184 if (braces)
4185 *dest++ = '{';
4186 while (*namep)
4187 *dest++ = *namep++;
4188 if (operator) {
4189 char *altp = alt_value;
4190 *dest++ = operator;
4191 while (*altp)
4192 *dest++ = *altp++;
4193 }
4194 if (braces)
4195 *dest++ = '}';
4196
4197 wb = addword(lookup(var_name)->name, wb);
4198 } else {
4199 /* expand */
4200
4201 vp = lookup(var_name);
4202 if (vp->value != null)
4203 value = (operator == '+') ?
4204 alt_value : vp->value;
4205 else if (operator == '?') {
4206 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004207 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004208 } else if (alt_index && (operator != '+')) {
4209 value = alt_value;
4210 if (operator == '=')
4211 setval(vp, value);
4212 } else
4213 continue;
4214
4215 while (*value && (count < LINELIM)) {
4216 *dest++ = *value++;
4217 count++;
4218 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004219 }
4220 } else {
4221 *dest++ = *src++;
4222 count++;
4223 ignore_once = 0;
4224 }
4225 }
4226 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004227
Eric Andersenff9eee42001-06-29 04:57:14 +00004228 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004229 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004230
Eric Andersen8401eea2004-08-04 19:16:54 +00004231 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004232
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004233 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004234
Eric Andersen737f5fb2003-03-14 16:05:59 +00004235 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004236 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004237 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004238 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004239 }
4240 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004241 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004242 e.iop->argp->aword = ++cp;
4243 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004244 PUSHIO(afile, remap(pf[0]),
4245 (int (*)(struct ioarg *)) ((quoted) ? qgravechar :
4246 gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004247 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004248 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004249 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004250 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004251 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004252 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4253 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004254
Eric Andersenff9eee42001-06-29 04:57:14 +00004255 dup2(pf[1], 1);
4256 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004257
Eric Andersen8401eea2004-08-04 19:16:54 +00004258 argument_list[0] = (char *) DEFAULT_SHELL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004259 argument_list[1] = "-c";
4260 argument_list[2] = child_cmd;
4261 argument_list[3] = 0;
4262
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004263 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004264 prs(argument_list[0]);
4265 prs(": ");
4266 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004267 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004268}
4269
Eric Andersen737f5fb2003-03-14 16:05:59 +00004270
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004271static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004272{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004273 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004274
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004275 s = as;
4276 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004277 while (*s)
4278 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004279 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004280}
4281
4282/* -------- glob.c -------- */
4283
4284/*
4285 * glob
4286 */
4287
4288#define scopy(x) strsave((x), areanum)
4289#define BLKSIZ 512
4290#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4291
Eric Andersen8401eea2004-08-04 19:16:54 +00004292static struct wdblock *cl, *nl;
4293static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004294
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004295static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004296{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004297 int i;
4298 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004299
4300 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004301 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004302 i = 0;
4303 for (pp = cp; *pp; pp++)
4304 if (any(*pp, spcl))
4305 i++;
4306 else if (!any(*pp & ~QUOTE, spcl))
4307 *pp &= ~QUOTE;
4308 if (i != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004309 for (cl = addword(scopy(cp), (struct wdblock *) 0); anyspcl(cl);
4310 cl = nl) {
4311 nl = newword(cl->w_nword * 2);
4312 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004313 for (pp = cl->w_words[i]; *pp; pp++)
4314 if (any(*pp, spcl)) {
4315 globname(cl->w_words[i], pp);
4316 break;
4317 }
4318 if (*pp == '\0')
4319 nl = addword(scopy(cl->w_words[i]), nl);
4320 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004321 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004322 DELETE(cl->w_words[i]);
4323 DELETE(cl);
4324 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004325 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004326 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004327 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004328 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004329 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004330 wb = addword(cl->w_words[i], wb);
4331 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004332 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004333 }
4334 }
4335 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004336 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004337}
4338
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004339static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004340{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004341 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004342 char *name, *gp, *dp;
4343 int k;
4344 DIR *dirp;
4345 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004346 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004347 struct stat dbuf;
4348
4349 for (np = we; np != pp; pp--)
4350 if (pp[-1] == '/')
4351 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004352 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004353 *cp++ = *np++;
4354 *cp++ = '.';
4355 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004356 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004357 *cp++ = *np++;
4358 *cp = '\0';
4359 dirp = opendir(dp);
4360 if (dirp == 0) {
4361 DELETE(dp);
4362 DELETE(gp);
4363 return;
4364 }
4365 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004366 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004367 /* XXX Hmmm... What this could be? (abial) */
4368 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004369 if (ent[j].d_ino == 0)
4370 continue;
4371 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004372 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004373 if (dname[0] == '.')
4374 if (*gp != '.')
4375 continue;
4376 for (k = 0; k < NAME_MAX; k++)
4377 if (any(dname[k], spcl))
4378 dname[k] |= QUOTE;
4379 if (gmatch(dname, gp)) {
4380 name = generate(we, pp, dname, np);
4381 if (*np && !anys(np, spcl)) {
4382 if (stat(name, &dbuf)) {
4383 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004384 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004385 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004386 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004387 nl = addword(name, nl);
4388 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004389 }
4390 closedir(dirp);
4391 DELETE(dp);
4392 DELETE(gp);
4393}
4394
4395/*
4396 * generate a pathname as below.
4397 * start..end1 / middle end
4398 * the slashes come for free
4399 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004400static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004401{
4402 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004403 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004404
Eric Andersen8401eea2004-08-04 19:16:54 +00004405 p = op =
4406 space((int) (end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004407 for (xp = start1; xp != end1;)
4408 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004409 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004410 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004411 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004412 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004413}
4414
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004415static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004416{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004417 int i;
4418 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004419
4420 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004421 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004422 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004423 return 1;
4424 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004425}
4426
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004427static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004428{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004429 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004430}
4431
4432/* -------- word.c -------- */
4433
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004434static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004435{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004436 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004437
Eric Andersen8401eea2004-08-04 19:16:54 +00004438 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004439 wb->w_bsize = nw;
4440 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004441 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004442}
4443
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004444static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004445{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004446 struct wdblock *wb2;
4447 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004448
4449 if (wb == NULL)
4450 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004451 nw = wb->w_nword;
4452 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004453 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004454 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4455 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004456 wb2->w_nword = nw;
4457 DELETE(wb);
4458 wb = wb2;
4459 }
4460 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004461 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004462}
Eric Andersen8401eea2004-08-04 19:16:54 +00004463
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004464static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004465char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004466{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004467 char **wd;
4468 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004469
4470 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004471 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004472 if (wb->w_nword == 0) {
4473 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004474 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004475 }
4476 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004477 memcpy((char *) wd, (char *) wb->w_words, nb);
4478 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004479 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004480}
4481
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004482static int (*func) (char *, char *);
4483static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004484
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004485static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004486{
4487 func = a3;
4488 globv = a2;
4489 glob1(a0, a0 + a1 * a2);
4490}
4491
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004492static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004493{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004494 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004495 int v2;
4496 char *lptr, *hptr;
4497 int c;
4498 unsigned n;
4499
Eric Andersenff9eee42001-06-29 04:57:14 +00004500 v2 = globv;
4501
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004502 top:
4503 n = (int) (lim - base);
4504 if (n <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004505 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004506 n = v2 * (n / (2 * v2));
4507 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004508 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004509 j = lim - v2;
4510 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004511 if (i < lptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004512 c = (*func) (i, lptr);
4513 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004514 glob2(i, lptr -= v2);
4515 continue;
4516 }
4517 if (c < 0) {
4518 i += v2;
4519 continue;
4520 }
4521 }
4522
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004523 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004524 if (j > hptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004525 c = (*func) (hptr, j);
4526 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004527 glob2(hptr += v2, j);
4528 goto begin;
4529 }
4530 if (c > 0) {
4531 if (i == lptr) {
4532 glob3(i, hptr += v2, j);
4533 i = lptr += v2;
4534 goto begin;
4535 }
4536 glob2(i, j);
4537 j -= v2;
4538 i += v2;
4539 continue;
4540 }
4541 j -= v2;
4542 goto begin;
4543 }
4544
4545
4546 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004547 if (lptr - base >= lim - hptr) {
4548 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004549 lim = lptr;
4550 } else {
4551 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004552 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004553 }
4554 goto top;
4555 }
4556
4557
4558 glob3(j, lptr -= v2, i);
4559 j = hptr -= v2;
4560 }
4561}
4562
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004563static void glob2(char *i, char *j)
Eric Andersenff9eee42001-06-29 04:57:14 +00004564{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004565 char *index1, *index2, c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004566 int m;
4567
4568 m = globv;
4569 index1 = i;
4570 index2 = j;
4571 do {
4572 c = *index1;
4573 *index1++ = *index2;
4574 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004575 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004576}
4577
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004578static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004579{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004580 char *index1, *index2, *index3;
Eric Andersenff9eee42001-06-29 04:57:14 +00004581 int c;
4582 int m;
4583
4584 m = globv;
4585 index1 = i;
4586 index2 = j;
4587 index3 = k;
4588 do {
4589 c = *index1;
4590 *index1++ = *index3;
4591 *index3++ = *index2;
4592 *index2++ = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004593 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004594}
4595
4596/* -------- io.c -------- */
4597
4598/*
4599 * shell IO
4600 */
4601
Eric Andersen8401eea2004-08-04 19:16:54 +00004602static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004603{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004604 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004605
Eric Andersen8401eea2004-08-04 19:16:54 +00004606 if (e.linep > elinep) {
4607 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004608 err("input line too long");
4609 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004610 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004611 }
4612 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004613 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004614 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004615 c = readc();
4616 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004617 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004618 c |= QUOTE;
4619 }
4620 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004621 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004622}
4623
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004624static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004625{
4626 if (e.iop >= e.iobase)
4627 e.iop->peekc = c;
4628}
4629
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004630static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004631{
Eric Andersen8401eea2004-08-04 19:16:54 +00004632 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004633}
4634
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004635static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004636{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004637 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004638
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004639 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004640
4641 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004642 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004643 c = e.iop->peekc;
4644 if (c != '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004645 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004646 return c;
Eric Andersen8401eea2004-08-04 19:16:54 +00004647 } else {
4648 if (e.iop->prev != 0) {
4649 if ((c = (*e.iop->iofn) (e.iop->argp, e.iop)) != '\0') {
4650 if (c == -1) {
4651 e.iop++;
4652 continue;
4653 }
4654 if (e.iop == iostack)
4655 ioecho(c);
4656 return (e.iop->prev = c);
4657 } else if (e.iop->task == XIO && e.iop->prev != '\n') {
4658 e.iop->prev = 0;
4659 if (e.iop == iostack)
4660 ioecho('\n');
4661 return '\n';
4662 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004663 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004664 if (e.iop->task == XIO) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004665 if (multiline) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004666 return e.iop->prev = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004667 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004668 if (interactive && e.iop == iostack + 1) {
4669#ifdef CONFIG_FEATURE_COMMAND_EDITING
4670 current_prompt = prompt->value;
4671#else
4672 prs(prompt->value);
4673#endif
4674 }
4675 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004676 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004677
4678 } /* FOR */
4679
4680 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004681 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004682 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004683 }
4684
4685 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004686 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004687
Eric Andersenff9eee42001-06-29 04:57:14 +00004688 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004689 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004690}
4691
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004692static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004693{
4694 if (flag['v'])
4695 write(2, &c, sizeof c);
4696}
4697
Eric Andersen12de6cf2004-08-04 19:19:10 +00004698
Eric Andersen8401eea2004-08-04 19:16:54 +00004699static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004700{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004701 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004702 argp->afid, e.iop));
4703
4704 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004705 if (++e.iop >= &iostack[NPUSH]) {
4706 e.iop--;
4707 err("Shell input nested too deeply");
4708 gflg++;
4709 return;
4710 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004711
4712 /* We did not overflow the NPUSH array spots so setup data structs */
4713
4714 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004715
4716 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004717 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004718 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004719
4720 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4721 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4722
4723 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4724
4725 if (e.iop == &iostack[0])
4726 e.iop->argp->afbuf = &mainbuf;
4727 else
4728 e.iop->argp->afbuf = &sharedbuf;
4729
4730 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4731 /* This line appears to be active when running scripts from command line */
4732 if ((isatty(e.iop->argp->afile) == 0)
4733 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004734 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004735 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4736 bufid = AFID_ID; /* AFID_ID = 0 */
4737
4738 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004739 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004740
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004741 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004742 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004743 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004744 &mainbuf, &sharedbuf, bufid, e.iop));
4745
Eric Andersenff9eee42001-06-29 04:57:14 +00004746 }
4747
Eric Andersen8401eea2004-08-04 19:16:54 +00004748 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004749 e.iop->peekc = 0;
4750 e.iop->xchar = 0;
4751 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004752
Eric Andersenff9eee42001-06-29 04:57:14 +00004753 if (fn == filechar || fn == linechar)
4754 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004755 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004756 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004757 e.iop->task = XGRAVE;
4758 else
4759 e.iop->task = XOTHER;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004760
4761 return;
Eric Andersenff9eee42001-06-29 04:57:14 +00004762}
4763
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004764static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004765{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004766 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004767
4768 xp = e.iobase;
4769 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004770 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004771}
4772
4773/*
4774 * Input generating functions
4775 */
4776
4777/*
4778 * Produce the characters of a string, then a newline, then EOF.
4779 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004780static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004781{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004782 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004783
4784 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004785 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004786 if ((c = *ap->aword++) == 0) {
4787 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004788 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004789 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004790 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004791}
4792
4793/*
4794 * Given a list of words, produce the characters
4795 * in them, with a space after each word.
4796 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004797static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004798{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004799 char c;
4800 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004801
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004802 wl = ap->awordlist;
4803 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004804 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004805 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004806 c = *(*wl)++;
4807 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004808 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004809 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004810 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004811 }
4812 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004813 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004814}
4815
4816/*
4817 * Return the characters of a list of words,
4818 * producing a space between them.
4819 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004820static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004821{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004822 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004823
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004824 wp = *ap->awordlist++;
4825 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004826 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004827 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004828 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004829 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004830}
4831
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004832static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004833{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004834 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004835
4836 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004837 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004838 c = *ap->aword++;
4839 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004840 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004841 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004842 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004843 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004844}
4845
4846/*
4847 * Produce the characters from a single word (string).
4848 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004849static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004850{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004851 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004852 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004853 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004854}
4855
4856/*
4857 * Produce quoted characters from a single word (string).
4858 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004859static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004860{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004861 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004862
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004863 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004864 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004865 c = *ap->aword++;
4866 if (c)
4867 c |= QUOTE;
4868 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004869}
4870
4871/*
4872 * Return the characters from a file.
4873 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004874static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004875{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004876 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004877 char c;
4878 struct iobuf *bp = ap->afbuf;
4879
4880 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004881 i = (ap->afid != bp->id);
4882 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004883 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004884 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004885
Eric Andersen8401eea2004-08-04 19:16:54 +00004886 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004887
Eric Andersen8401eea2004-08-04 19:16:54 +00004888 if (i <= 0) {
4889 closef(ap->afile);
4890 return 0;
4891 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004892
Eric Andersen8401eea2004-08-04 19:16:54 +00004893 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004894 bp->bufp = bp->buf;
4895 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004896 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004897
Eric Andersen8401eea2004-08-04 19:16:54 +00004898 ap->afpos++;
4899 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004900 }
Eric Andersenbdfd0d72001-10-24 05:00:29 +00004901#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004902 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004903 static char mycommand[BUFSIZ];
4904 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004905
Eric Andersen8401eea2004-08-04 19:16:54 +00004906 while (size == 0 || position >= size) {
4907 cmdedit_read_input(current_prompt, mycommand);
4908 size = strlen(mycommand);
4909 position = 0;
4910 }
4911 c = mycommand[position];
4912 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004913 return c;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004914 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00004915#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00004916
Eric Andersenff9eee42001-06-29 04:57:14 +00004917 {
Eric Andersen7467c8d2001-07-12 20:26:32 +00004918 i = safe_read(ap->afile, &c, sizeof(c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004919 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004920 }
4921}
4922
4923/*
4924 * Return the characters from a here temp file.
4925 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004926static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004927{
4928 char c;
4929
Eric Andersenff9eee42001-06-29 04:57:14 +00004930 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4931 close(ap->afile);
4932 c = 0;
4933 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004934 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004935
4936}
4937
4938/*
4939 * Return the characters produced by a process (`...`).
4940 * Quote them if required, and remove any trailing newline characters.
4941 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004942static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004943{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004944 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004945
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004946 c = qgravechar(ap, iop) & ~QUOTE;
4947 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004948 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004949 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004950}
4951
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004952static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004953{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004954 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004955
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004956 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004957
4958 if (iop->xchar) {
4959 if (iop->nlcount) {
4960 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004961 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004962 }
4963 c = iop->xchar;
4964 iop->xchar = 0;
4965 } else if ((c = filechar(ap)) == '\n') {
4966 iop->nlcount = 1;
4967 while ((c = filechar(ap)) == '\n')
4968 iop->nlcount++;
4969 iop->xchar = c;
4970 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004971 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004972 iop->nlcount--;
4973 c = '\n';
4974 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004975 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004976}
4977
4978/*
4979 * Return a single command (usually the first line) from a file.
4980 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004981static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004982{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004983 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004984
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004985 c = filechar(ap);
4986 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004987 if (!multiline) {
4988 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004989 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004990 }
4991 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004992 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004993}
4994
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004995static void prs(const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00004996{
4997 if (*s)
4998 write(2, s, strlen(s));
4999}
5000
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005001static void prn(unsigned u)
Eric Andersenff9eee42001-06-29 04:57:14 +00005002{
Eric Andersen737f5fb2003-03-14 16:05:59 +00005003 prs(itoa(u));
Eric Andersenff9eee42001-06-29 04:57:14 +00005004}
5005
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005006static void closef(int i)
Eric Andersenff9eee42001-06-29 04:57:14 +00005007{
5008 if (i > 2)
5009 close(i);
5010}
5011
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005012static void closeall(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005013{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005014 int u;
Eric Andersenff9eee42001-06-29 04:57:14 +00005015
Eric Andersen8401eea2004-08-04 19:16:54 +00005016 for (u = NUFILE; u < NOFILE;)
Eric Andersenff9eee42001-06-29 04:57:14 +00005017 close(u++);
5018}
5019
Eric Andersen12de6cf2004-08-04 19:19:10 +00005020
Eric Andersenff9eee42001-06-29 04:57:14 +00005021/*
5022 * remap fd into Shell's fd space
5023 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005024static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00005025{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005026 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005027 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00005028 int newfd;
5029
Eric Andersen12de6cf2004-08-04 19:19:10 +00005030 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00005031
5032 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005033 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00005034 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005035
Eric Andersenff9eee42001-06-29 04:57:14 +00005036 do {
5037 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005038 newfd = dup(fd);
5039 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00005040 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005041
Eric Andersen8401eea2004-08-04 19:16:54 +00005042 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00005043 if (map[i])
5044 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00005045
Eric Andersenff9eee42001-06-29 04:57:14 +00005046 if (fd < 0)
5047 err("too many files open in shell");
5048 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00005049
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005050 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00005051}
5052
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005053static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005054{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005055 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005056
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00005057 i = pipe(pv);
5058 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00005059 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005060 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00005061}
5062
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005063static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00005064{
5065 if (pv != NULL) {
5066 close(*pv++);
5067 close(*pv);
5068 }
5069}
5070
5071/* -------- here.c -------- */
5072
5073/*
5074 * here documents
5075 */
5076
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005077static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00005078{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005079 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005080
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005081 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00005082
5083 h = (struct here *) space(sizeof(struct here));
5084 if (h == 0)
5085 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005086
Eric Andersenff9eee42001-06-29 04:57:14 +00005087 h->h_tag = evalstr(s, DOSUB);
5088 if (h->h_tag == 0)
5089 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005090
Eric Andersenff9eee42001-06-29 04:57:14 +00005091 h->h_iop = iop;
5092 iop->io_name = 0;
5093 h->h_next = NULL;
5094 if (inhere == 0)
5095 inhere = h;
5096 else
Eric Andersen8401eea2004-08-04 19:16:54 +00005097 for (lh = inhere; lh != NULL; lh = lh->h_next)
Eric Andersenff9eee42001-06-29 04:57:14 +00005098 if (lh->h_next == 0) {
5099 lh->h_next = h;
5100 break;
5101 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005102 iop->io_flag |= IOHERE | IOXHERE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005103 for (s = h->h_tag; *s; s++)
5104 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005105 iop->io_flag &= ~IOXHERE;
5106 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005107 }
5108 h->h_dosub = iop->io_flag & IOXHERE;
5109}
5110
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005111static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005112{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005113 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005114
5115 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005116
5117 /* Scan here files first leaving inhere list in place */
5118 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005119 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005120
5121 /* Make inhere list active - keep list intact for scraphere */
5122 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005123 hp->h_next = acthere;
5124 acthere = inhere;
5125 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005126 }
5127}
5128
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005129static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005130{
5131 int tf;
5132 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005133 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005134 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005135 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005136 char *thenext;
5137
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005138 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005139
Eric Andersenff9eee42001-06-29 04:57:14 +00005140 tf = mkstemp(tname);
5141 if (tf < 0)
5142 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005143
Eric Andersenff9eee42001-06-29 04:57:14 +00005144 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00005145 errpt = ev;
5146 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00005147 unlink(tname);
5148 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005149 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005150 e.iobase = e.iop;
5151 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005152 if (interactive && e.iop <= iostack) {
Eric Andersenbdfd0d72001-10-24 05:00:29 +00005153#ifdef CONFIG_FEATURE_COMMAND_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005154 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005155#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005156 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005157#endif
5158 }
5159 thenext = myline;
5160 while ((c = my_getc(ec)) != '\n' && c) {
5161 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005162 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005163 if (thenext >= &myline[LINELIM]) {
5164 c = 0;
5165 break;
5166 }
5167 *thenext++ = c;
5168 }
5169 *thenext = 0;
5170 if (strcmp(s, myline) == 0 || c == 0)
5171 break;
5172 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005173 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005174 }
5175 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005176 prs("here document `");
5177 prs(s);
5178 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005179 }
5180 quitenv();
5181 }
5182 close(tf);
5183}
5184
5185/*
5186 * open here temp file.
5187 * if unquoted here, expand here temp file into second temp file.
5188 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005189static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005190{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005191 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005192 int tf;
5193
5194#if __GNUC__
5195 /* Avoid longjmp clobbering */
5196 (void) &tf;
5197#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005198 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005199 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005200
5201 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5202
Eric Andersenff9eee42001-06-29 04:57:14 +00005203 hf = open(hname, 0);
5204 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005205 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005206
Eric Andersenff9eee42001-06-29 04:57:14 +00005207 if (xdoll) {
5208 char c;
5209 char tname[30] = ".msh_XXXXXX";
5210 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005211
Eric Andersenff9eee42001-06-29 04:57:14 +00005212 tf = mkstemp(tname);
5213 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005214 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00005215 if (newenv(setjmp(errpt = ev)) == 0) {
5216 PUSHIO(afile, hf, herechar);
5217 setbase(e.iop);
5218 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005219 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005220 write(tf, &c, sizeof c);
5221 }
5222 quitenv();
5223 } else
5224 unlink(tname);
5225 close(tf);
5226 tf = open(tname, 0);
5227 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005228 return tf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005229 } else
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005230 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005231}
5232
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005233static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005234{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005235 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005236
5237 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005238
5239 for (h = inhere; h != NULL; h = h->h_next) {
5240 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005241 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005242 }
5243 inhere = NULL;
5244}
5245
5246/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005247static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005248{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005249 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005250
5251 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005252
5253 hl = NULL;
5254 for (h = acthere; h != NULL; h = h->h_next)
5255 if (getarea((char *) h) >= area) {
5256 if (h->h_iop->io_name != NULL)
5257 unlink(h->h_iop->io_name);
5258 if (hl == NULL)
5259 acthere = h->h_next;
5260 else
5261 hl->h_next = h->h_next;
5262 } else
5263 hl = h;
5264}
5265
5266
5267
5268/*
5269 * Copyright (c) 1987,1997, Prentice Hall
5270 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005271 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005272 * Redistribution and use of the MINIX operating system in source and
5273 * binary forms, with or without modification, are permitted provided
5274 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005275 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005276 * Redistributions of source code must retain the above copyright
5277 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005278 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005279 * Redistributions in binary form must reproduce the above
5280 * copyright notice, this list of conditions and the following
5281 * disclaimer in the documentation and/or other materials provided
5282 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005283 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005284 * Neither the name of Prentice Hall nor the names of the software
5285 * authors or contributors may be used to endorse or promote
5286 * products derived from this software without specific prior
5287 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005288 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005289 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5290 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5291 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5292 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5293 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5294 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5295 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5296 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5297 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5298 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5299 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5300 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5301 *
5302 */