blob: d9dd3efb21bdc7eb0e1c8cdecfc81a0f604ccdd5 [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
Mike Frysinger67a32ad2007-03-09 08:25:24 +000016#ifdef STANDALONE
17# ifndef _GNU_SOURCE
18# define _GNU_SOURCE
19# endif
20# include <setjmp.h>
21# include <sys/times.h>
22# include <sys/types.h>
23# include <sys/stat.h>
24# include <sys/wait.h>
25# include <signal.h>
26# include <stdio.h>
27# include <stdlib.h>
28# include <unistd.h>
29# include <string.h>
30# include <errno.h>
31# include <dirent.h>
32# include <fcntl.h>
33# include <ctype.h>
34# include <assert.h>
35# define bb_dev_null "/dev/null"
36# define DEFAULT_SHELL "/proc/self/exe"
37# define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"
38# define BB_BANNER "busybox standalone"
39# define ENABLE_FEATURE_SH_STANDALONE_SHELL 0
40# define bb_msg_memory_exhausted "memory exhausted"
41# define xmalloc(size) malloc(size)
42# define msh_main(argc,argv) main(argc,argv)
43# define safe_read(fd,buf,count) read(fd,buf,count)
44# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
45# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
46# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
47static char *find_applet_by_name(const char *applet)
48{
49 return NULL;
50}
51static void utoa_to_buf(unsigned n, char *buf, unsigned buflen)
52{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000053 unsigned i, out, res;
54 assert(sizeof(unsigned) == 4);
55 if (buflen) {
56 out = 0;
57 for (i = 1000000000; i; i /= 10) {
58 res = n / i;
59 if (res || out || i == 1) {
60 if (!--buflen) break;
61 out++;
62 n -= res*i;
63 *buf++ = '0' + res;
64 }
65 }
66 *buf = '\0';
67 }
Mike Frysinger67a32ad2007-03-09 08:25:24 +000068}
69static void itoa_to_buf(int n, char *buf, unsigned buflen)
70{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000071 if (buflen && n < 0) {
72 n = -n;
73 *buf++ = '-';
74 buflen--;
75 }
76 utoa_to_buf((unsigned)n, buf, buflen);
Mike Frysinger67a32ad2007-03-09 08:25:24 +000077}
78static char local_buf[12];
79static char *itoa(int n)
80{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000081 itoa_to_buf(n, local_buf, sizeof(local_buf));
82 return local_buf;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000083}
84#else
85# include <setjmp.h>
86# include <sys/times.h>
87# include "busybox.h"
Denis Vlasenko489f93e2007-02-01 01:43:16 +000088extern char **environ;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000089#endif
Eric Andersenff9eee42001-06-29 04:57:14 +000090
Mike Frysinger17811882006-05-05 20:33:07 +000091/*#define MSHDEBUG 1*/
Eric Andersen12de6cf2004-08-04 19:19:10 +000092
93#ifdef MSHDEBUG
Mike Frysinger14ff19b2006-06-20 20:37:01 +000094int mshdbg = MSHDEBUG;
Eric Andersen12de6cf2004-08-04 19:19:10 +000095
96#define DBGPRINTF(x) if(mshdbg>0)printf x
97#define DBGPRINTF0(x) if(mshdbg>0)printf x
98#define DBGPRINTF1(x) if(mshdbg>1)printf x
99#define DBGPRINTF2(x) if(mshdbg>2)printf x
100#define DBGPRINTF3(x) if(mshdbg>3)printf x
101#define DBGPRINTF4(x) if(mshdbg>4)printf x
102#define DBGPRINTF5(x) if(mshdbg>5)printf x
103#define DBGPRINTF6(x) if(mshdbg>6)printf x
104#define DBGPRINTF7(x) if(mshdbg>7)printf x
105#define DBGPRINTF8(x) if(mshdbg>8)printf x
106#define DBGPRINTF9(x) if(mshdbg>9)printf x
107
108int mshdbg_rc = 0;
109
110#define RCPRINTF(x) if(mshdbg_rc)printf x
111
112#else
113
114#define DBGPRINTF(x)
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000115#define DBGPRINTF0(x) ((void)0)
116#define DBGPRINTF1(x) ((void)0)
117#define DBGPRINTF2(x) ((void)0)
118#define DBGPRINTF3(x) ((void)0)
119#define DBGPRINTF4(x) ((void)0)
120#define DBGPRINTF5(x) ((void)0)
121#define DBGPRINTF6(x) ((void)0)
122#define DBGPRINTF7(x) ((void)0)
123#define DBGPRINTF8(x) ((void)0)
124#define DBGPRINTF9(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000125
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000126#define RCPRINTF(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000127
128#endif /* MSHDEBUG */
129
130
Denis Vlasenko38f63192007-01-22 09:03:07 +0000131#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger2a131752006-06-06 06:26:12 +0000132# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
133# define DEFAULT_USER_PROMPT "\\u:\\w$ "
134#else
135# define DEFAULT_ROOT_PROMPT "# "
136# define DEFAULT_USER_PROMPT "$ "
137#endif
138
139
Eric Andersenff9eee42001-06-29 04:57:14 +0000140/* -------- sh.h -------- */
141/*
142 * shell
143 */
144
Eric Andersen12de6cf2004-08-04 19:19:10 +0000145#define LINELIM 2100
146#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +0000147
Eric Andersen392947c2002-12-11 07:42:46 +0000148#undef NOFILE
Eric Andersen12de6cf2004-08-04 19:19:10 +0000149#define NOFILE 20 /* Number of open files */
150#define NUFILE 10 /* Number of user-accessible files */
151#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000152
153/*
154 * values returned by wait
155 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000156#define WAITSIG(s) ((s)&0177)
157#define WAITVAL(s) (((s)>>8)&0377)
Eric Andersenff9eee42001-06-29 04:57:14 +0000158#define WAITCORE(s) (((s)&0200)!=0)
159
160/*
Eric Andersenaff114c2004-04-14 17:51:38 +0000161 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +0000162 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000163typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +0000164
165/*
166 * shell components
167 */
168
169#define QUOTE 0200
170
171#define NOBLOCK ((struct op *)NULL)
172#define NOWORD ((char *)NULL)
173#define NOWORDS ((char **)NULL)
174#define NOPIPE ((int *)NULL)
175
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000176
177/*
178 * redirection
179 */
180struct ioword {
181 short io_unit; /* unit affected */
182 short io_flag; /* action (below) */
183 char *io_name; /* file name */
184};
185
186#define IOREAD 1 /* < */
187#define IOHERE 2 /* << (here file) */
188#define IOWRITE 4 /* > */
189#define IOCAT 8 /* >> */
190#define IOXHERE 16 /* ${}, ` in << */
191#define IODUP 32 /* >&digit */
192#define IOCLOSE 64 /* >&- */
193
194#define IODEFAULT (-1) /* token for default IO unit */
195
196
Eric Andersenff9eee42001-06-29 04:57:14 +0000197/*
198 * Description of a command or an operation on commands.
199 * Might eventually use a union.
200 */
201struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000202 int type; /* operation type, see below */
203 char **words; /* arguments to a command */
204 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000205 struct op *left;
206 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000207 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000208};
209
Eric Andersen8401eea2004-08-04 19:16:54 +0000210#define TCOM 1 /* command */
211#define TPAREN 2 /* (c-list) */
212#define TPIPE 3 /* a | b */
213#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000214#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000215#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000216#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000217#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000218#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000219#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000220#define TWHILE 11
221#define TUNTIL 12
222#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000223#define TPAT 14 /* pattern in case */
224#define TBRACE 15 /* {c-list} */
225#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000226/* Added to support "." file expansion */
227#define TDOT 17
228
229/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000230#ifdef MSHDEBUG
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000231static const char *const T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000232 "PLACEHOLDER",
233 "TCOM",
234 "TPAREN",
235 "TPIPE",
236 "TLIST",
237 "TOR",
238 "TAND",
239 "TFOR",
240 "TDO",
241 "TCASE",
242 "TIF",
243 "TWHILE",
244 "TUNTIL",
245 "TELIF",
246 "TPAT",
247 "TBRACE",
248 "TASYNC",
249 "TDOT",
250};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000251#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000252
253/*
254 * actions determining the environment of a process
255 */
256#define BIT(i) (1<<(i))
Eric Andersen8401eea2004-08-04 19:16:54 +0000257#define FEXEC BIT(0) /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000258
Eric Andersen12de6cf2004-08-04 19:19:10 +0000259#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000260
Eric Andersenff9eee42001-06-29 04:57:14 +0000261/*
262 * flags to control evaluation of words
263 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000264#define DOSUB 1 /* interpret $, `, and quotes */
265#define DOBLANK 2 /* perform blank interpretation */
266#define DOGLOB 4 /* interpret [?* */
267#define DOKEY 8 /* move words with `=' to 2nd arg. list */
268#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000269
270#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
271
Eric Andersenff9eee42001-06-29 04:57:14 +0000272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000273/* PROTOTYPES */
Eric Andersenff9eee42001-06-29 04:57:14 +0000274static int newfile(char *s);
Eric Andersenff9eee42001-06-29 04:57:14 +0000275
276
Eric Andersen8401eea2004-08-04 19:16:54 +0000277struct brkcon {
278 jmp_buf brkpt;
279 struct brkcon *nextlev;
280};
Eric Andersenff9eee42001-06-29 04:57:14 +0000281
Eric Andersen12de6cf2004-08-04 19:19:10 +0000282
Eric Andersenff9eee42001-06-29 04:57:14 +0000283/*
Eric Andersenff9eee42001-06-29 04:57:14 +0000284 * flags:
285 * -e: quit on error
286 * -k: look for name=value everywhere on command line
287 * -n: no execution
288 * -t: exit after reading and executing one command
289 * -v: echo as read
290 * -x: trace
291 * -u: unset variables net diagnostic
292 */
Mike Frysinger3672fe92006-11-15 21:52:10 +0000293static char flags['z' - 'a' + 1];
294/* this looks weird, but is OK ... we index flag with 'a'...'z' */
295static char *flag = flags - 'a';
Eric Andersenff9eee42001-06-29 04:57:14 +0000296
Eric Andersen8401eea2004-08-04 19:16:54 +0000297static char *null; /* null value for variable */
298static int intr; /* interrupt pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000299
Eric Andersen8401eea2004-08-04 19:16:54 +0000300static char *trap[_NSIG + 1];
301static char ourtrap[_NSIG + 1];
302static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000303
Eric Andersen8401eea2004-08-04 19:16:54 +0000304static int heedint; /* heed interrupt signals */
Eric Andersenff9eee42001-06-29 04:57:14 +0000305
Eric Andersen8401eea2004-08-04 19:16:54 +0000306static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000307
Eric Andersen8401eea2004-08-04 19:16:54 +0000308static char line[LINELIM];
309static char *elinep;
Eric Andersenff9eee42001-06-29 04:57:14 +0000310
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000311#if ENABLE_FEATURE_EDITING
312static char *current_prompt;
313static line_input_t *line_input_state;
314#endif
315
316static int areanum; /* current allocation area */
317
Eric Andersen12de6cf2004-08-04 19:19:10 +0000318
Eric Andersenff9eee42001-06-29 04:57:14 +0000319/*
320 * other functions
321 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000322static const char *rexecve(char *c, char **v, char **envp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000323static char *evalstr(char *cp, int f);
324static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000325static char *unquote(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000326static int rlookup(char *n);
327static struct wdblock *glob(char *cp, struct wdblock *wb);
328static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000329static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000330static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000331static char **eval(char **ap, int f);
332static int setstatus(int s);
333static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000334
Eric Andersen8401eea2004-08-04 19:16:54 +0000335static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000336
Eric Andersen8401eea2004-08-04 19:16:54 +0000337static int newenv(int f);
338static void quitenv(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000339static void next(int f);
340static void setdash(void);
341static void onecommand(void);
342static void runtrap(int i);
Eric Andersenff9eee42001-06-29 04:57:14 +0000343
Eric Andersen12de6cf2004-08-04 19:19:10 +0000344
Eric Andersenff9eee42001-06-29 04:57:14 +0000345/* -------- area stuff -------- */
346
Eric Andersen12de6cf2004-08-04 19:19:10 +0000347#define REGSIZE sizeof(struct region)
348#define GROWBY (256)
349/* #define SHRINKBY (64) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000350#undef SHRINKBY
Tim Rikerc1ef7bd2006-01-25 00:08:53 +0000351#define FREE (32767)
352#define BUSY (0)
353#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000354
355
356struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000357 struct region *next;
358 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000359};
360
361
Eric Andersenff9eee42001-06-29 04:57:14 +0000362/* -------- grammar stuff -------- */
363typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000364 char *cp;
365 char **wp;
366 int i;
367 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000368} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000369
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000370#define WORD 256
371#define LOGAND 257
372#define LOGOR 258
373#define BREAK 259
374#define IF 260
375#define THEN 261
376#define ELSE 262
377#define ELIF 263
378#define FI 264
379#define CASE 265
380#define ESAC 266
381#define FOR 267
382#define WHILE 268
383#define UNTIL 269
384#define DO 270
385#define DONE 271
386#define IN 272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000387/* Added for "." file expansion */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000388#define DOT 273
Eric Andersen12de6cf2004-08-04 19:19:10 +0000389
Eric Andersenff9eee42001-06-29 04:57:14 +0000390#define YYERRCODE 300
391
392/* flags to yylex */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000393#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000394
Eric Andersen8401eea2004-08-04 19:16:54 +0000395static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000396static struct op *andor(void);
397static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000398static int synio(int cf);
399static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000400static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000401static struct op *nested(int type, int mark);
402static struct op *command(int cf);
403static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000404static struct op *thenpart(void);
405static struct op *elsepart(void);
406static struct op *caselist(void);
407static struct op *casepart(void);
408static char **pattern(void);
409static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000410static struct op *list(struct op *t1, struct op *t2);
411static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000412static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000413static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000414static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000415static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000416static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000417static struct ioword *io(int u, int f, char *cp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000418static int yylex(int cf);
419static int collect(int c, int c1);
420static int dual(int c);
421static void diag(int ec);
422static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000423
424/* -------- var.h -------- */
425
Eric Andersen8401eea2004-08-04 19:16:54 +0000426struct var {
427 char *value;
428 char *name;
429 struct var *next;
430 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000431};
Eric Andersenff9eee42001-06-29 04:57:14 +0000432
Eric Andersen8401eea2004-08-04 19:16:54 +0000433#define COPYV 1 /* flag to setval, suggesting copy */
434#define RONLY 01 /* variable is read-only */
435#define EXPORT 02 /* variable is to be exported */
436#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000437
Eric Andersen8401eea2004-08-04 19:16:54 +0000438static int yyparse(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000439
440static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000441
Eric Andersen12de6cf2004-08-04 19:19:10 +0000442
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000443#define AFID_NOBUF (~0)
444#define AFID_ID 0
445
446
Eric Andersenff9eee42001-06-29 04:57:14 +0000447/* -------- io.h -------- */
448/* io buffer */
449struct iobuf {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000450 unsigned id; /* buffer id */
451 char buf[512]; /* buffer */
452 char *bufp; /* pointer into buffer */
453 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000454};
455
456/* possible arguments to an IO function */
457struct ioarg {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000458 const char *aword;
Eric Andersen8401eea2004-08-04 19:16:54 +0000459 char **awordlist;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000460 int afile; /* file descriptor */
461 unsigned afid; /* buffer id */
462 long afpos; /* file position */
463 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000464};
Eric Andersen8401eea2004-08-04 19:16:54 +0000465
Eric Andersenff9eee42001-06-29 04:57:14 +0000466/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000467struct io {
468 int (*iofn) (struct ioarg *, struct io *);
469 struct ioarg *argp;
470 int peekc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000471 char prev; /* previous character read by readc() */
472 char nlcount; /* for `'s */
473 char xchar; /* for `'s */
474 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000475};
Eric Andersen8401eea2004-08-04 19:16:54 +0000476
Eric Andersen8401eea2004-08-04 19:16:54 +0000477#define XOTHER 0 /* none of the below */
478#define XDOLL 1 /* expanding ${} */
479#define XGRAVE 2 /* expanding `'s */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000480#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000481
482/* in substitution */
483#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
484
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000485static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
486static struct ioarg ioargstack[NPUSH];
487static struct io iostack[NPUSH];
488static struct iobuf sharedbuf = { AFID_NOBUF };
489static struct iobuf mainbuf = { AFID_NOBUF };
490static unsigned bufid = AFID_ID; /* buffer id counter */
491
492#define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen)))
493#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
494
495
496/*
497 * parsing & execution environment
498 */
499static struct env {
500 char *linep;
501 struct io *iobase;
502 struct io *iop;
503 xint *errpt; /* void * */
504 int iofd;
505 struct env *oenv;
506} e;
507
Eric Andersen12de6cf2004-08-04 19:19:10 +0000508
Eric Andersenff9eee42001-06-29 04:57:14 +0000509/*
510 * input generators for IO structure
511 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000512static int nlchar(struct ioarg *ap);
513static int strchar(struct ioarg *ap);
514static int qstrchar(struct ioarg *ap);
515static int filechar(struct ioarg *ap);
516static int herechar(struct ioarg *ap);
517static int linechar(struct ioarg *ap);
518static int gravechar(struct ioarg *ap, struct io *iop);
519static int qgravechar(struct ioarg *ap, struct io *iop);
520static int dolchar(struct ioarg *ap);
521static int wdchar(struct ioarg *ap);
522static void scraphere(void);
523static void freehere(int area);
524static void gethere(void);
525static void markhere(char *s, struct ioword *iop);
526static int herein(char *hname, int xdoll);
527static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000528
Eric Andersen12de6cf2004-08-04 19:19:10 +0000529
Eric Andersen8401eea2004-08-04 19:16:54 +0000530static int eofc(void);
531static int readc(void);
532static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000533static void ioecho(char c);
Eric Andersenff9eee42001-06-29 04:57:14 +0000534
Eric Andersen12de6cf2004-08-04 19:19:10 +0000535
Eric Andersenff9eee42001-06-29 04:57:14 +0000536/*
537 * IO control
538 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000539static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
540static int remap(int fd);
541static int openpipe(int *pv);
542static void closepipe(int *pv);
543static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000544
Eric Andersenff9eee42001-06-29 04:57:14 +0000545/* -------- word.h -------- */
546
Eric Andersen8401eea2004-08-04 19:16:54 +0000547#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000548
Eric Andersen8401eea2004-08-04 19:16:54 +0000549struct wdblock {
550 short w_bsize;
551 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000552 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000553 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000554};
555
Eric Andersen8401eea2004-08-04 19:16:54 +0000556static struct wdblock *addword(char *wd, struct wdblock *wb);
557static struct wdblock *newword(int nw);
558static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000559
Eric Andersenff9eee42001-06-29 04:57:14 +0000560/* -------- misc stuff -------- */
561
Eric Andersen12de6cf2004-08-04 19:19:10 +0000562static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000563static int iosetup(struct ioword *iop, int pipein, int pipeout);
Eric Andersen8401eea2004-08-04 19:16:54 +0000564static void brkset(struct brkcon *bc);
565static int dolabel(struct op *t);
566static int dohelp(struct op *t);
567static int dochdir(struct op *t);
568static int doshift(struct op *t);
569static int dologin(struct op *t);
570static int doumask(struct op *t);
571static int doexec(struct op *t);
572static int dodot(struct op *t);
573static int dowait(struct op *t);
574static int doread(struct op *t);
575static int doeval(struct op *t);
576static int dotrap(struct op *t);
577static int getsig(char *s);
578static void setsig(int n, sighandler_t f);
579static int getn(char *as);
580static int dobreak(struct op *t);
581static int docontinue(struct op *t);
582static int brkcontin(char *cp, int val);
583static int doexit(struct op *t);
584static int doexport(struct op *t);
585static int doreadonly(struct op *t);
586static void rdexp(char **wp, void (*f) (struct var *), int key);
587static void badid(char *s);
588static int doset(struct op *t);
589static void varput(char *s, int out);
590static int dotimes(struct op *t);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000591static int expand(const char *cp, struct wdblock **wbp, int f);
Eric Andersen8401eea2004-08-04 19:16:54 +0000592static char *blank(int f);
593static int dollar(int quoted);
594static int grave(int quoted);
595static void globname(char *we, char *pp);
596static char *generate(char *start1, char *end1, char *middle, char *end);
597static int anyspcl(struct wdblock *wb);
598static int xstrcmp(char *p1, char *p2);
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000599static void glob0(char *a0, unsigned a1, int a2,
Eric Andersen8401eea2004-08-04 19:16:54 +0000600 int (*a3) (char *, char *));
Eric Andersen8401eea2004-08-04 19:16:54 +0000601static void readhere(char **name, char *s, int ec);
602static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
603static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000604
Eric Andersen8401eea2004-08-04 19:16:54 +0000605struct here {
606 char *h_tag;
607 int h_dosub;
608 struct ioword *h_iop;
609 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000610};
611
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000612static const char * const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000613 "Signal 0",
614 "Hangup",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000615 NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000616 "Quit",
617 "Illegal instruction",
618 "Trace/BPT trap",
619 "Abort",
620 "Bus error",
621 "Floating Point Exception",
622 "Killed",
623 "SIGUSR1",
624 "SIGSEGV",
625 "SIGUSR2",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000626 NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000627 "Alarm clock",
628 "Terminated",
629};
Eric Andersen8401eea2004-08-04 19:16:54 +0000630
Eric Andersenff9eee42001-06-29 04:57:14 +0000631#define NSIGNAL (sizeof(signame)/sizeof(signame[0]))
632
633struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000634 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000635 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000636};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000637static const struct res restab[] = {
Eric Andersen8401eea2004-08-04 19:16:54 +0000638 {"for", FOR},
639 {"case", CASE},
640 {"esac", ESAC},
641 {"while", WHILE},
642 {"do", DO},
643 {"done", DONE},
644 {"if", IF},
645 {"in", IN},
646 {"then", THEN},
647 {"else", ELSE},
648 {"elif", ELIF},
649 {"until", UNTIL},
650 {"fi", FI},
Eric Andersen8401eea2004-08-04 19:16:54 +0000651 {";;", BREAK},
652 {"||", LOGOR},
653 {"&&", LOGAND},
654 {"{", '{'},
655 {"}", '}'},
Eric Andersen12de6cf2004-08-04 19:19:10 +0000656 {".", DOT},
Eric Andersen8401eea2004-08-04 19:16:54 +0000657 {0, 0},
Eric Andersenff9eee42001-06-29 04:57:14 +0000658};
659
660
Eric Andersen1c039232001-07-07 00:05:55 +0000661struct builtincmd {
662 const char *name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000663 int (*builtinfunc) (struct op * t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000664};
Eric Andersen8401eea2004-08-04 19:16:54 +0000665static const struct builtincmd builtincmds[] = {
666 {".", dodot},
667 {":", dolabel},
668 {"break", dobreak},
669 {"cd", dochdir},
670 {"continue", docontinue},
671 {"eval", doeval},
672 {"exec", doexec},
673 {"exit", doexit},
674 {"export", doexport},
675 {"help", dohelp},
676 {"login", dologin},
677 {"newgrp", dologin},
678 {"read", doread},
679 {"readonly", doreadonly},
680 {"set", doset},
681 {"shift", doshift},
682 {"times", dotimes},
683 {"trap", dotrap},
684 {"umask", doumask},
685 {"wait", dowait},
686 {0, 0}
Eric Andersenff9eee42001-06-29 04:57:14 +0000687};
688
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000689static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000690static struct op *dowholefile(int, int);
691
Eric Andersen12de6cf2004-08-04 19:19:10 +0000692
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000693/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000694static char **dolv;
695static int dolc;
696static int exstat;
697static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000698static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000699static int execflg;
700static int multiline; /* \n changed to ; */
701static struct op *outtree; /* result from parser */
702static xint *failpt;
703static xint *errpt;
704static struct brkcon *brklist;
705static int isbreak;
706static struct wdblock *wdlist;
707static struct wdblock *iolist;
708static char *trap[_NSIG + 1];
709static char ourtrap[_NSIG + 1];
710static int trapset; /* trap pending */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000711
712#ifdef MSHDEBUG
713static struct var *mshdbg_var;
714#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000715static struct var *vlist; /* dictionary */
716static struct var *homedir; /* home directory */
717static struct var *prompt; /* main prompt */
718static struct var *cprompt; /* continuation prompt */
719static struct var *path; /* search path for commands */
720static struct var *shell; /* shell to interpret command files */
721static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000722
Eric Andersen8401eea2004-08-04 19:16:54 +0000723static int areanum; /* current allocation area */
724static int intr;
725static int inparse;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000726static char *null = (char*)"";
Eric Andersen8401eea2004-08-04 19:16:54 +0000727static int heedint = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +0000728static void (*qflag) (int) = SIG_IGN;
729static int startl;
730static int peeksym;
731static int nlseen;
732static int iounit = IODEFAULT;
733static YYSTYPE yylval;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000734static char *elinep = line + sizeof(line) - 5;
735
Eric Andersen12de6cf2004-08-04 19:19:10 +0000736
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000737static struct here *inhere; /* list of hear docs while parsing */
738static struct here *acthere; /* list of active here documents */
739static struct region *areabot; /* bottom of area */
740static struct region *areatop; /* top of area */
741static struct region *areanxt; /* starting point of scan */
Eric Andersen8401eea2004-08-04 19:16:54 +0000742static void *brktop;
743static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000744
Eric Andersen12de6cf2004-08-04 19:19:10 +0000745static struct env e = {
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000746 line, /* linep: char ptr */
747 iostack, /* iobase: struct io ptr */
748 iostack - 1, /* iop: struct io ptr */
749 (xint *) NULL, /* errpt: void ptr for errors? */
750 FDBASE, /* iofd: file desc */
751 (struct env *) NULL /* oenv: struct env ptr */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000752};
753
754#ifdef MSHDEBUG
755void print_t(struct op *t)
756{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000757 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
758 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000759
760 if (t->words) {
761 DBGPRINTF(("T: W1: %s", t->words[0]));
762 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000763}
764
765void print_tree(struct op *head)
766{
767 if (head == NULL) {
768 DBGPRINTF(("PRINT_TREE: no tree\n"));
769 return;
770 }
771
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000772 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000773 head->right));
774
775 if (head->left)
776 print_tree(head->left);
777
778 if (head->right)
779 print_tree(head->right);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000780}
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000781#endif /* MSHDEBUG */
782
783
784/*
785 * IO functions
786 */
787static void prs(const char *s)
788{
789 if (*s)
790 write(2, s, strlen(s));
791}
792
793static void prn(unsigned u)
794{
795 prs(itoa(u));
796}
797
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000798static void echo(char **wp)
799{
800 int i;
801
802 prs("+");
803 for (i = 0; wp[i]; i++) {
804 if (i)
805 prs(" ");
806 prs(wp[i]);
807 }
808 prs("\n");
809}
810
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000811static void closef(int i)
812{
813 if (i > 2)
814 close(i);
815}
816
817static void closeall(void)
818{
819 int u;
820
821 for (u = NUFILE; u < NOFILE;)
822 close(u++);
823}
Eric Andersen12de6cf2004-08-04 19:19:10 +0000824
Eric Andersenff9eee42001-06-29 04:57:14 +0000825
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000826/* fail but return to process next command */
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000827static void fail(void) ATTRIBUTE_NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000828static void fail(void)
829{
830 longjmp(failpt, 1);
831 /* NOTREACHED */
832}
Eric Andersenff9eee42001-06-29 04:57:14 +0000833
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000834/* abort shell (or fail in subshell) */
835static void leave(void) ATTRIBUTE_NORETURN;
836static void leave(void)
837{
838 DBGPRINTF(("LEAVE: leave called!\n"));
839
840 if (execflg)
841 fail();
842 scraphere();
843 freehere(1);
844 runtrap(0);
845 _exit(exstat);
846 /* NOTREACHED */
847}
848
849static void warn(const char *s)
850{
851 if (*s) {
852 prs(s);
853 exstat = -1;
854 }
855 prs("\n");
856 if (flag['e'])
857 leave();
858}
859
860static void err(const char *s)
861{
862 warn(s);
863 if (flag['n'])
864 return;
865 if (!interactive)
866 leave();
867 if (e.errpt)
868 longjmp(e.errpt, 1);
869 closeall();
870 e.iop = e.iobase = iostack;
871}
872
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000873
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000874/* -------- area.c -------- */
875
Eric Andersenff9eee42001-06-29 04:57:14 +0000876/*
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000877 * All memory between (char *)areabot and (char *)(areatop+1) is
878 * exclusively administered by the area management routines.
879 * It is assumed that sbrk() and brk() manipulate the high end.
Eric Andersenff9eee42001-06-29 04:57:14 +0000880 */
881
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000882#define sbrk(X) ({ \
883 void * __q = (void *)-1; \
884 if (brkaddr + (int)(X) < brktop) { \
885 __q = brkaddr; \
886 brkaddr += (int)(X); \
887 } \
888 __q; \
889})
Eric Andersenff9eee42001-06-29 04:57:14 +0000890
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000891static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000892{
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000893 brkaddr = xmalloc(AREASIZE);
894 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +0000895
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000896 while ((long) sbrk(0) & ALIGN)
897 sbrk(1);
898 areabot = (struct region *) sbrk(REGSIZE);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000899
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000900 areabot->next = areabot;
901 areabot->area = BUSY;
902 areatop = areabot;
903 areanxt = areabot;
Eric Andersenff9eee42001-06-29 04:57:14 +0000904}
905
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000906static char *getcell(unsigned nbytes)
907{
908 int nregio;
909 struct region *p, *q;
910 int i;
911
912 if (nbytes == 0) {
913 puts("getcell(0)");
914 abort();
915 }
916 /* silly and defeats the algorithm */
917 /*
918 * round upwards and add administration area
919 */
920 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
921 p = areanxt;
922 for (;;) {
923 if (p->area > areanum) {
924 /*
925 * merge free cells
926 */
927 while ((q = p->next)->area > areanum && q != areanxt)
928 p->next = q->next;
929 /*
930 * exit loop if cell big enough
931 */
932 if (q >= p + nregio)
933 goto found;
934 }
935 p = p->next;
936 if (p == areanxt)
937 break;
938 }
939 i = nregio >= GROWBY ? nregio : GROWBY;
940 p = (struct region *) sbrk(i * REGSIZE);
941 if (p == (struct region *) -1)
942 return NULL;
943 p--;
944 if (p != areatop) {
945 puts("not contig");
946 abort(); /* allocated areas are contiguous */
947 }
948 q = p + i;
949 p->next = q;
950 p->area = FREE;
951 q->next = areabot;
952 q->area = BUSY;
953 areatop = q;
954 found:
955 /*
956 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
957 */
958 areanxt = p + nregio;
959 if (areanxt < q) {
960 /*
961 * split into requested area and rest
962 */
963 if (areanxt + 1 > q) {
964 puts("OOM");
965 abort(); /* insufficient space left for admin */
966 }
967 areanxt->next = q;
968 areanxt->area = FREE;
969 p->next = areanxt;
970 }
971 p->area = areanum;
972 return (char *) (p + 1);
973}
974
975static void freecell(char *cp)
976{
977 struct region *p;
978
979 p = (struct region *) cp;
980 if (p != NULL) {
981 p--;
982 if (p < areanxt)
983 areanxt = p;
984 p->area = FREE;
985 }
986}
987#define DELETE(obj) freecell((char *)obj)
988
989static void freearea(int a)
990{
991 struct region *p, *top;
992
993 top = areatop;
994 for (p = areabot; p != top; p = p->next)
995 if (p->area >= a)
996 p->area = FREE;
997}
998
999static void setarea(char *cp, int a)
1000{
1001 struct region *p;
1002
1003 p = (struct region *) cp;
1004 if (p != NULL)
1005 (p - 1)->area = a;
1006}
1007
1008static int getarea(char *cp)
1009{
1010 return ((struct region *) cp - 1)->area;
1011}
1012
1013static void garbage(void)
1014{
1015 struct region *p, *q, *top;
1016
1017 top = areatop;
1018 for (p = areabot; p != top; p = p->next) {
1019 if (p->area > areanum) {
1020 while ((q = p->next)->area > areanum)
1021 p->next = q->next;
1022 areanxt = p;
1023 }
1024 }
1025#ifdef SHRINKBY
1026 if (areatop >= q + SHRINKBY && q->area > areanum) {
1027 brk((char *) (q + 1));
1028 q->next = areabot;
1029 q->area = BUSY;
1030 areatop = q;
1031 }
1032#endif
1033}
1034
1035static char *space(int n)
1036{
1037 char *cp;
1038
1039 cp = getcell(n);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001040 if (cp == NULL)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001041 err("out of string space");
1042 return cp;
1043}
1044
1045static char *strsave(const char *s, int a)
1046{
1047 char *cp;
1048
1049 cp = space(strlen(s) + 1);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001050 if (cp == NULL) {
1051// FIXME: I highly doubt this is good.
1052 return (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001053 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001054 setarea(cp, a);
1055 strcpy(cp, s);
1056 return cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001057}
1058
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001059
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001060/* -------- var.c -------- */
1061
1062static int eqname(const char *n1, const char *n2)
1063{
1064 for (; *n1 != '=' && *n1 != '\0'; n1++)
1065 if (*n2++ != *n1)
1066 return 0;
1067 return *n2 == '\0' || *n2 == '=';
1068}
1069
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001070static const char *findeq(const char *cp)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001071{
1072 while (*cp != '\0' && *cp != '=')
1073 cp++;
1074 return cp;
1075}
1076
1077/*
1078 * Find the given name in the dictionary
1079 * and return its value. If the name was
1080 * not previously there, enter it now and
1081 * return a null value.
1082 */
1083static struct var *lookup(const char *n)
1084{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001085// FIXME: dirty hack
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001086 static struct var dummy;
1087
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001088 struct var *vp;
1089 const char *cp;
1090 char *xp;
1091 int c;
1092
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001093 if (isdigit(*n)) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001094 dummy.name = (char*)n;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001095 for (c = 0; isdigit(*n) && c < 1000; n++)
1096 c = c * 10 + *n - '0';
1097 dummy.status = RONLY;
1098 dummy.value = (c <= dolc ? dolv[c] : null);
1099 return &dummy;
1100 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001101
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001102 for (vp = vlist; vp; vp = vp->next)
1103 if (eqname(vp->name, n))
1104 return vp;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001105
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001106 cp = findeq(n);
1107 vp = (struct var *) space(sizeof(*vp));
1108 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001109 dummy.name = dummy.value = (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001110 return &dummy;
1111 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001112
1113 xp = vp->name;
1114 while ((*xp = *n++) != '\0' && *xp != '=')
1115 xp++;
1116 *xp++ = '=';
1117 *xp = '\0';
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001118 setarea((char *) vp, 0);
1119 setarea((char *) vp->name, 0);
1120 vp->value = null;
1121 vp->next = vlist;
1122 vp->status = GETCELL;
1123 vlist = vp;
1124 return vp;
1125}
1126
1127/*
1128 * if name is not NULL, it must be
1129 * a prefix of the space `val',
1130 * and end with `='.
1131 * this is all so that exporting
1132 * values is reasonably painless.
1133 */
1134static void nameval(struct var *vp, const char *val, const char *name)
1135{
1136 const char *cp;
1137 char *xp;
1138 int fl;
1139
1140 if (vp->status & RONLY) {
1141 xp = vp->name;
1142 while (*xp && *xp != '=')
1143 putc(*xp++, stderr);
1144 err(" is read-only");
1145 return;
1146 }
1147 fl = 0;
1148 if (name == NULL) {
1149 xp = space(strlen(vp->name) + strlen(val) + 2);
1150 if (xp == NULL)
1151 return;
1152 /* make string: name=value */
1153 setarea(xp, 0);
1154 name = xp;
1155 cp = vp->name;
1156 while ((*xp = *cp++) != '\0' && *xp != '=')
1157 xp++;
1158 *xp++ = '=';
1159 strcpy(xp, val);
1160 val = xp;
1161 fl = GETCELL;
1162 }
1163 if (vp->status & GETCELL)
1164 freecell(vp->name); /* form new string `name=value' */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001165 vp->name = (char*)name;
1166 vp->value = (char*)val;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001167 vp->status |= fl;
1168}
1169
1170/*
1171 * give variable at `vp' the value `val'.
1172 */
1173static void setval(struct var *vp, const char *val)
1174{
1175 nameval(vp, val, NULL);
1176}
1177
1178static void export(struct var *vp)
1179{
1180 vp->status |= EXPORT;
1181}
1182
1183static void ronly(struct var *vp)
1184{
1185 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1186 vp->status |= RONLY;
1187}
1188
1189static int isassign(const char *s)
1190{
1191 unsigned char c;
1192 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1193
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001194 c = *s;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001195 /* no isalpha() - we shouldn't use locale */
1196 /* c | 0x20 - lowercase (Latin) letters */
1197 if (c != '_' && (unsigned)((c|0x20) - 'a') > 25)
1198 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001199 return 0;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001200
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001201 while (1) {
1202 c = *++s;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001203 if (c == '=')
1204 return 1;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001205 if (c == '\0')
1206 return 0;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001207 if (c != '_'
1208 && (unsigned)(c - '0') > 9 /* not number */
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001209 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001210 ) {
1211 return 0;
1212 }
1213 }
1214}
1215
1216static int assign(const char *s, int cf)
1217{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001218 const char *cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001219 struct var *vp;
1220
1221 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1222
1223 if (!isalpha(*s) && *s != '_')
1224 return 0;
1225 for (cp = s; *cp != '='; cp++)
1226 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
1227 return 0;
1228 vp = lookup(s);
1229 nameval(vp, ++cp, cf == COPYV ? NULL : s);
1230 if (cf != COPYV)
1231 vp->status &= ~GETCELL;
1232 return 1;
1233}
1234
1235static int checkname(char *cp)
1236{
1237 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1238
1239 if (!isalpha(*cp++) && *(cp - 1) != '_')
1240 return 0;
1241 while (*cp)
1242 if (!isalnum(*cp++) && *(cp - 1) != '_')
1243 return 0;
1244 return 1;
1245}
1246
1247static void putvlist(int f, int out)
1248{
1249 struct var *vp;
1250
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001251 for (vp = vlist; vp; vp = vp->next) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001252 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1253 if (vp->status & EXPORT)
1254 write(out, "export ", 7);
1255 if (vp->status & RONLY)
1256 write(out, "readonly ", 9);
1257 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
1258 write(out, "\n", 1);
1259 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001260 }
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001261}
1262
1263
1264/*
1265 * trap handling
1266 */
1267static void sig(int i)
1268{
1269 trapset = i;
1270 signal(i, sig);
1271}
1272
1273static void runtrap(int i)
1274{
1275 char *trapstr;
1276
1277 trapstr = trap[i];
1278 if (trapstr == NULL)
1279 return;
1280
1281 if (i == 0)
1282 trap[i] = NULL;
1283
1284 RUN(aword, trapstr, nlchar);
1285}
1286
1287
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001288static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001289{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001290 char *cp;
1291 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001292 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001293
1294 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001295 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001296 if (flag[c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001297 *cp++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001298 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001299 setval(lookup("-"), m);
1300}
1301
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001302static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001303{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001304 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001305
1306 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001307
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001308 f = 0;
Denis Vlasenko9f739442006-12-16 23:49:13 +00001309 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001310 DBGPRINTF(("NEWFILE: s is %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001311 f = open(s, 0);
1312 if (f < 0) {
1313 prs(s);
1314 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001315 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001316 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001317 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001318
Eric Andersenff9eee42001-06-29 04:57:14 +00001319 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001320 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001321}
1322
Eric Andersen12de6cf2004-08-04 19:19:10 +00001323
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001324struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001325{
1326 struct op *dotnode;
1327
1328 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001329 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001330
1331 if (head->left != NULL) {
1332 dotnode = scantree(head->left);
1333 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001334 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001335 }
1336
1337 if (head->right != NULL) {
1338 dotnode = scantree(head->right);
1339 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001340 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001341 }
1342
1343 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001344 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001345
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001346 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001347
Denis Vlasenkocf787cf2007-02-04 17:11:25 +00001348 if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001349 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001350 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001351 }
1352
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001353 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001354}
1355
1356
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001357static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001358{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001359 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001360 jmp_buf m1;
1361
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001362 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001363
Eric Andersenff9eee42001-06-29 04:57:14 +00001364 while (e.oenv)
1365 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001366
Eric Andersenff9eee42001-06-29 04:57:14 +00001367 areanum = 1;
1368 freehere(areanum);
1369 freearea(areanum);
1370 garbage();
1371 wdlist = 0;
1372 iolist = 0;
1373 e.errpt = 0;
1374 e.linep = line;
1375 yynerrs = 0;
1376 multiline = 0;
1377 inparse = 1;
1378 intr = 0;
1379 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001380
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001381 failpt = m1;
1382 setjmp(failpt); /* Bruce Evans' fix */
1383 failpt = m1;
1384 if (setjmp(failpt) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001385 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1386
Eric Andersenff9eee42001-06-29 04:57:14 +00001387 while (e.oenv)
1388 quitenv();
1389 scraphere();
1390 if (!interactive && intr)
1391 leave();
1392 inparse = 0;
1393 intr = 0;
1394 return;
1395 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001396
Eric Andersenff9eee42001-06-29 04:57:14 +00001397 inparse = 0;
1398 brklist = 0;
1399 intr = 0;
1400 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001401
1402 if (!flag['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001403 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001404 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001405 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001406 }
1407
Eric Andersenff9eee42001-06-29 04:57:14 +00001408 if (!interactive && intr) {
1409 execflg = 0;
1410 leave();
1411 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001412
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001413 i = trapset;
1414 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001415 trapset = 0;
1416 runtrap(i);
1417 }
1418}
1419
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001420static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001421{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001422 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001423
1424 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001425
1426 if (f) {
1427 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001428 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001429 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001430
Eric Andersenff9eee42001-06-29 04:57:14 +00001431 ep = (struct env *) space(sizeof(*ep));
1432 if (ep == NULL) {
1433 while (e.oenv)
1434 quitenv();
1435 fail();
1436 }
1437 *ep = e;
1438 e.oenv = ep;
1439 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001440
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001441 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001442}
1443
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001444static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001445{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001446 struct env *ep;
1447 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001448
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001449 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001450
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001451 ep = e.oenv;
1452 if (ep != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001453 fd = e.iofd;
1454 e = *ep;
1455 /* should close `'d files */
1456 DELETE(ep);
1457 while (--fd >= e.iofd)
1458 close(fd);
1459 }
1460}
1461
1462/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001463 * Is character c in s?
Eric Andersenff9eee42001-06-29 04:57:14 +00001464 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001465static int any(int c, const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001466{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001467 while (*s)
1468 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001469 return 1;
1470 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001471}
1472
1473/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001474 * Is any character from s1 in s2?
Eric Andersenff9eee42001-06-29 04:57:14 +00001475 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001476static int anys(const char *s1, const char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001477{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001478 while (*s1)
1479 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001480 return 1;
1481 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001482}
1483
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001484static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001485{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001486 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001487}
1488
Eric Andersen8401eea2004-08-04 19:16:54 +00001489static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001490{
1491 PUSHIO(afile, f, filechar);
1492}
1493
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001494static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001495{
1496 signal(SIGINT, onintr);
1497 intr = 1;
1498 if (interactive) {
1499 if (inparse) {
1500 prs("\n");
1501 fail();
1502 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001503 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001504 execflg = 0;
1505 leave();
1506 }
1507}
1508
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001509
Eric Andersenff9eee42001-06-29 04:57:14 +00001510/* -------- gmatch.c -------- */
1511/*
1512 * int gmatch(string, pattern)
1513 * char *string, *pattern;
1514 *
1515 * Match a pattern as in sh(1).
1516 */
1517
1518#define CMASK 0377
1519#define QUOTE 0200
1520#define QMASK (CMASK&~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001521#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001522
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001523static const char *cclass(const char *p, int sub)
1524{
1525 int c, d, not, found;
1526
1527 not = (*p == NOT);
1528 if (not != 0)
1529 p++;
1530 found = not;
1531 do {
1532 if (*p == '\0')
1533 return NULL;
1534 c = *p & CMASK;
1535 if (p[1] == '-' && p[2] != ']') {
1536 d = p[2] & CMASK;
1537 p++;
1538 } else
1539 d = c;
1540 if (c == sub || (c <= sub && sub <= d))
1541 found = !not;
1542 } while (*++p != ']');
1543 return found ? p + 1 : NULL;
1544}
1545
1546static int gmatch(const char *s, const char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001547{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001548 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001549
1550 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001551 return 0;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001552
Eric Andersenff9eee42001-06-29 04:57:14 +00001553 while ((pc = *p++ & CMASK) != '\0') {
1554 sc = *s++ & QMASK;
1555 switch (pc) {
1556 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001557 p = cclass(p, sc);
1558 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001559 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001560 break;
1561
1562 case '?':
1563 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001564 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001565 break;
1566
1567 case '*':
1568 s--;
1569 do {
1570 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001571 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001572 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001573 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001574
1575 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001576 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001577 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001578 }
1579 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001580 return *s == '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001581}
1582
Eric Andersenff9eee42001-06-29 04:57:14 +00001583
Eric Andersenff9eee42001-06-29 04:57:14 +00001584/* -------- csyn.c -------- */
1585/*
1586 * shell: syntax (C version)
1587 */
1588
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001589static void yyerror(const char *s) ATTRIBUTE_NORETURN;
1590static void yyerror(const char *s)
1591{
1592 yynerrs++;
1593 if (interactive && e.iop <= iostack) {
1594 multiline = 0;
1595 while (eofc() == 0 && yylex(0) != '\n');
1596 }
1597 err(s);
1598 fail();
1599}
1600
1601static void zzerr(void) ATTRIBUTE_NORETURN;
1602static void zzerr(void)
1603{
1604 yyerror("syntax error");
1605}
1606
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001607int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001608{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001609 DBGPRINTF7(("YYPARSE: enter...\n"));
1610
Eric Andersen8401eea2004-08-04 19:16:54 +00001611 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001612 peeksym = 0;
1613 yynerrs = 0;
1614 outtree = c_list();
1615 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001616 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001617}
1618
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001619static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001620{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001621 struct op *t, *p;
1622 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001623
1624 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001625
1626 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001627
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001628 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001629
Eric Andersenff9eee42001-06-29 04:57:14 +00001630 if (t != NULL) {
1631 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001632 p = command(CONTIN);
1633 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001634 DBGPRINTF8(("PIPELINE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001635 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001636 }
1637
Eric Andersenff9eee42001-06-29 04:57:14 +00001638 if (t->type != TPAREN && t->type != TCOM) {
1639 /* shell statement */
1640 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1641 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001642
Eric Andersenff9eee42001-06-29 04:57:14 +00001643 t = block(TPIPE, t, p, NOWORDS);
1644 }
1645 peeksym = c;
1646 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001647
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001648 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001649 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001650}
1651
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001652static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001653{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001654 struct op *t, *p;
1655 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001656
1657 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001658
1659 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001660
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001661 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001662
Eric Andersenff9eee42001-06-29 04:57:14 +00001663 if (t != NULL) {
1664 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001665 p = pipeline(CONTIN);
1666 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001667 DBGPRINTF8(("ANDOR: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001668 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001669 }
1670
Eric Andersen8401eea2004-08-04 19:16:54 +00001671 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001672 } /* WHILE */
1673
Eric Andersenff9eee42001-06-29 04:57:14 +00001674 peeksym = c;
1675 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001676
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001677 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001678 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001679}
1680
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001681static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001682{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001683 struct op *t, *p;
1684 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001685
1686 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001687
1688 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001689
Eric Andersenff9eee42001-06-29 04:57:14 +00001690 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001691 peeksym = yylex(0);
1692 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001693 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001694
Eric Andersen8401eea2004-08-04 19:16:54 +00001695 while ((c = yylex(0)) == ';' || c == '&'
1696 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001697
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001698 p = andor();
1699 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001700 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001701
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001702 peeksym = yylex(0);
1703 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001704 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001705
Eric Andersenff9eee42001-06-29 04:57:14 +00001706 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001707 } /* WHILE */
1708
Eric Andersenff9eee42001-06-29 04:57:14 +00001709 peeksym = c;
1710 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001711 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001712 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001713 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001714}
1715
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001716static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001717{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001718 struct ioword *iop;
1719 int i;
1720 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001721
1722 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001723
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001724 c = yylex(cf);
1725 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001726 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001727 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001728 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001729
Eric Andersenff9eee42001-06-29 04:57:14 +00001730 i = yylval.i;
1731 musthave(WORD, 0);
1732 iop = io(iounit, i, yylval.cp);
1733 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001734
Eric Andersenff9eee42001-06-29 04:57:14 +00001735 if (i & IOHERE)
1736 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001737
1738 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001739 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001740}
1741
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001742static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001743{
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001744 peeksym = yylex(cf);
1745 if (peeksym != c) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001746 DBGPRINTF7(("MUSTHAVE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001747 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001748 }
1749
Eric Andersenff9eee42001-06-29 04:57:14 +00001750 peeksym = 0;
1751}
1752
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001753static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001754{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001755 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001756
1757 t = NULL;
1758 for (;;) {
1759 switch (peeksym = yylex(0)) {
1760 case '<':
1761 case '>':
1762 (void) synio(0);
1763 break;
1764
1765 case WORD:
1766 if (t == NULL) {
1767 t = newtp();
1768 t->type = TCOM;
1769 }
1770 peeksym = 0;
1771 word(yylval.cp);
1772 break;
1773
1774 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001775 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001776 }
1777 }
1778}
1779
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001780static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001781{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001782 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001783
1784 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001785
1786 multiline++;
1787 t = c_list();
1788 musthave(mark, 0);
1789 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001790 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001791}
1792
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001793static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001794{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001795 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001796 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001797 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001798
1799 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001800
1801 iosave = iolist;
1802 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001803
Eric Andersenff9eee42001-06-29 04:57:14 +00001804 if (multiline)
1805 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001806
Eric Andersenff9eee42001-06-29 04:57:14 +00001807 while (synio(cf))
1808 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001809
1810 c = yylex(cf);
1811
1812 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001813 default:
1814 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001815 t = simple();
1816 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001817 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001818 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001819 t = newtp();
1820 t->type = TCOM;
1821 }
1822 break;
1823
1824 case '(':
1825 t = nested(TPAREN, ')');
1826 break;
1827
1828 case '{':
1829 t = nested(TBRACE, '}');
1830 break;
1831
1832 case FOR:
1833 t = newtp();
1834 t->type = TFOR;
1835 musthave(WORD, 0);
1836 startl = 1;
1837 t->str = yylval.cp;
1838 multiline++;
1839 t->words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001840 c = yylex(0);
1841 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001842 peeksym = c;
1843 t->left = dogroup(0);
1844 multiline--;
1845 break;
1846
1847 case WHILE:
1848 case UNTIL:
1849 multiline++;
1850 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001851 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001852 t->left = c_list();
1853 t->right = dogroup(1);
1854 t->words = NULL;
1855 multiline--;
1856 break;
1857
1858 case CASE:
1859 t = newtp();
1860 t->type = TCASE;
1861 musthave(WORD, 0);
1862 t->str = yylval.cp;
1863 startl++;
1864 multiline++;
1865 musthave(IN, CONTIN);
1866 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001867
Eric Andersenff9eee42001-06-29 04:57:14 +00001868 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001869
Eric Andersenff9eee42001-06-29 04:57:14 +00001870 musthave(ESAC, 0);
1871 multiline--;
1872 break;
1873
1874 case IF:
1875 multiline++;
1876 t = newtp();
1877 t->type = TIF;
1878 t->left = c_list();
1879 t->right = thenpart();
1880 musthave(FI, 0);
1881 multiline--;
1882 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001883
1884 case DOT:
1885 t = newtp();
1886 t->type = TDOT;
1887
1888 musthave(WORD, 0); /* gets name of file */
1889 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1890
1891 word(yylval.cp); /* add word to wdlist */
1892 word(NOWORD); /* terminate wdlist */
1893 t->words = copyw(); /* dup wdlist */
1894 break;
1895
Eric Andersenff9eee42001-06-29 04:57:14 +00001896 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001897
Eric Andersen8401eea2004-08-04 19:16:54 +00001898 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001899
Eric Andersenff9eee42001-06-29 04:57:14 +00001900 t = namelist(t);
1901 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001902
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001903 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001904
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001905 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001906}
1907
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001908static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001909{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001910 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001911
1912 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
1913
1914 multiline++;
1915 t = c_list();
1916 multiline--;
1917 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001918 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001919 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001920}
1921
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001922static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00001923{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001924 int c;
1925 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001926
1927 c = yylex(CONTIN);
1928 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001929 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001930 if (c != DO)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001931 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001932 mylist = c_list();
1933 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001934 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001935}
1936
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001937static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001938{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001939 int c;
1940 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001941
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001942 c = yylex(0);
1943 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001944 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001945 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001946 }
1947 t = newtp();
1948 t->type = 0;
1949 t->left = c_list();
1950 if (t->left == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001951 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001952 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001953 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001954}
1955
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001956static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001957{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001958 int c;
1959 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001960
1961 switch (c = yylex(0)) {
1962 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001963 t = c_list();
1964 if (t == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001965 zzerr();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001966 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001967
1968 case ELIF:
1969 t = newtp();
1970 t->type = TELIF;
1971 t->left = c_list();
1972 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001973 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001974
1975 default:
1976 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001977 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001978 }
1979}
1980
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001981static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001982{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001983 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001984
1985 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001986 while ((peeksym = yylex(CONTIN)) != ESAC) {
1987 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00001988 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00001989 }
1990
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001991 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001992 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001993}
1994
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001995static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001996{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001997 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001998
1999 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002000
2001 t = newtp();
2002 t->type = TPAT;
2003 t->words = pattern();
2004 musthave(')', 0);
2005 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002006 peeksym = yylex(CONTIN);
2007 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00002008 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002009
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002010 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002011
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002012 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002013}
2014
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002015static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002016{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002017 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00002018
2019 cf = CONTIN;
2020 do {
2021 musthave(WORD, cf);
2022 word(yylval.cp);
2023 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002024 c = yylex(0);
2025 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00002026 peeksym = c;
2027 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002028
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002029 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002030}
2031
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002032static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002033{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002034 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002035
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002036 c = yylex(0);
2037 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002038 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002039 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002040 }
2041 startl = 0;
2042 while ((c = yylex(0)) == WORD)
2043 word(yylval.cp);
2044 word(NOWORD);
2045 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002046 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002047}
2048
2049/*
2050 * supporting functions
2051 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002052static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00002053{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002054 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002055
Eric Andersenff9eee42001-06-29 04:57:14 +00002056 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002057 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002058 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002059 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002060
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002061 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00002062}
2063
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002064static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002065{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002066 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002067
2068 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002069
2070 t = newtp();
2071 t->type = type;
2072 t->left = t1;
2073 t->right = t2;
2074 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002075
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002076 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002077 t2));
2078
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002079 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002080}
2081
Eric Andersen12de6cf2004-08-04 19:19:10 +00002082/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002083static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002084{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002085 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002086
2087 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002088
2089 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002090 if (strcmp(rp->r_name, n) == 0) {
2091 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002092 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002093 }
2094
2095 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002096 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002097}
2098
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002099static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002100{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002101 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002102
Eric Andersen8401eea2004-08-04 19:16:54 +00002103 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002104 t->type = 0;
2105 t->words = NULL;
2106 t->ioact = NULL;
2107 t->left = NULL;
2108 t->right = NULL;
2109 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002110
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002111 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002112
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002113 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002114}
2115
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002116static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002117{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002118
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002119 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002120 T_CMD_NAMES[t->type], iolist));
2121
Eric Andersenff9eee42001-06-29 04:57:14 +00002122 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002123 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002124 t->ioact = copyio();
2125 } else
2126 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002127
Eric Andersenff9eee42001-06-29 04:57:14 +00002128 if (t->type != TCOM) {
2129 if (t->type != TPAREN && t->ioact != NULL) {
2130 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2131 t->ioact = t->left->ioact;
2132 t->left->ioact = NULL;
2133 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002134 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002135 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002136
Eric Andersenff9eee42001-06-29 04:57:14 +00002137 word(NOWORD);
2138 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002139
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002140 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002141}
2142
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002143static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002144{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002145 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002146
2147 wd = getwords(wdlist);
2148 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002149 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002150}
2151
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002152static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002153{
2154 wdlist = addword(cp, wdlist);
2155}
2156
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002157static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002158{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002159 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002160
2161 iop = (struct ioword **) getwords(iolist);
2162 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002163 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002164}
2165
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002166static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002167{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002168 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002169
2170 iop = (struct ioword *) tree(sizeof(*iop));
2171 iop->io_unit = u;
2172 iop->io_flag = f;
2173 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002174 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002175 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002176}
2177
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002178static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002179{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002180 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002181 int atstart;
2182
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002183 c = peeksym;
2184 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002185 peeksym = 0;
2186 if (c == '\n')
2187 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002188 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002189 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002190
Eric Andersenff9eee42001-06-29 04:57:14 +00002191 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002192 atstart = startl;
2193 startl = 0;
2194 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002195 e.linep = line;
2196
2197/* MALAMO */
2198 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002199
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002200 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002201 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2202 ;
2203
Eric Andersenff9eee42001-06-29 04:57:14 +00002204 switch (c) {
2205 default:
2206 if (any(c, "0123456789")) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002207 c1 = my_getc(0);
2208 unget(c1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002209 if (c1 == '<' || c1 == '>') {
2210 iounit = c - '0';
2211 goto loop;
2212 }
2213 *e.linep++ = c;
2214 c = c1;
2215 }
2216 break;
2217
Eric Andersen12de6cf2004-08-04 19:19:10 +00002218 case '#': /* Comment, skip to next newline or End-of-string */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002219 while ((c = my_getc(0)) != '\0' && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002220 unget(c);
2221 goto loop;
2222
2223 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002224 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002225 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002226
2227 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002228 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002229 *e.linep++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002230 c = my_getc(0);
2231 if (c == '{') {
2232 c = collect(c, '}');
2233 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002234 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002235 goto pack;
2236 }
2237 break;
2238
2239 case '`':
2240 case '\'':
2241 case '"':
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002242 c = collect(c, c);
2243 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002244 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002245 goto pack;
2246
2247 case '|':
2248 case '&':
2249 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002250 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002251 /* If more chars process them, else return NULL char */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002252 c1 = dual(c);
2253 if (c1 != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002254 return c1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002255 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002256
Eric Andersenff9eee42001-06-29 04:57:14 +00002257 case '^':
2258 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002259 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002260 case '>':
2261 case '<':
2262 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002263 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002264
2265 case '\n':
2266 nlseen++;
2267 gethere();
2268 startl = 1;
2269 if (multiline || cf & CONTIN) {
2270 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002271#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002272 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002273#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002274 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002275#endif
2276 }
2277 if (cf & CONTIN)
2278 goto loop;
2279 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002280 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002281
2282 case '(':
2283 case ')':
2284 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002285 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002286 }
2287
2288 unget(c);
2289
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002290 pack:
2291 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002292 if (e.linep >= elinep)
2293 err("word too long");
2294 else
2295 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002296 };
2297
Eric Andersenff9eee42001-06-29 04:57:14 +00002298 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002299
Eric Andersen8401eea2004-08-04 19:16:54 +00002300 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002301 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002302
Eric Andersenff9eee42001-06-29 04:57:14 +00002303 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002304
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002305 if (atstart) {
2306 c = rlookup(line);
2307 if (c != 0) {
2308 startl = 1;
2309 return c;
2310 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002311 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002312
Eric Andersenff9eee42001-06-29 04:57:14 +00002313 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002314 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002315}
2316
Eric Andersen12de6cf2004-08-04 19:19:10 +00002317
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002318static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002319{
2320 char s[2];
2321
Eric Andersen12de6cf2004-08-04 19:19:10 +00002322 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2323
Eric Andersenff9eee42001-06-29 04:57:14 +00002324 *e.linep++ = c;
2325 while ((c = my_getc(c1)) != c1) {
2326 if (c == 0) {
2327 unget(c);
2328 s[0] = c1;
2329 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002330 prs("no closing ");
2331 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002332 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002333 }
2334 if (interactive && c == '\n' && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002335#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002336 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002337#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002338 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002339#endif
2340 }
2341 *e.linep++ = c;
2342 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002343
Eric Andersenff9eee42001-06-29 04:57:14 +00002344 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002345
2346 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2347
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002348 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002349}
2350
Eric Andersen12de6cf2004-08-04 19:19:10 +00002351/* "multiline commands" helper func */
2352/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002353static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002354{
2355 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002356 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002357
Eric Andersen12de6cf2004-08-04 19:19:10 +00002358 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2359
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002360 *cp++ = c; /* c is the given "peek" char */
2361 *cp++ = my_getc(0); /* get next char of input */
2362 *cp = '\0'; /* add EOS marker */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002363
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002364 c = rlookup(s); /* see if 2 chars form a shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002365 if (c == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002366 unget(*--cp); /* String is not a shell multiline, put peek char back */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002367
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002368 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002369}
2370
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002371static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002372{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002373 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002374
2375 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002376
2377 c = my_getc(0);
2378 if (c == '>' || c == '<') {
2379 if (c != ec)
2380 zzerr();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002381 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002382 c = my_getc(0);
2383 } else
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002384 yylval.i = (ec == '>' ? IOWRITE : IOREAD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002385 if (c != '&' || yylval.i == IOHERE)
2386 unget(c);
2387 else
2388 yylval.i |= IODUP;
2389}
2390
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002391static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002392{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002393 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002394
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002395 t = getcell(size);
2396 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002397 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002398 prs("command line too complicated\n");
2399 fail();
2400 /* NOTREACHED */
2401 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002402 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002403}
2404
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002405
Eric Andersenff9eee42001-06-29 04:57:14 +00002406/* VARARGS1 */
2407/* ARGSUSED */
2408
2409/* -------- exec.c -------- */
2410
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002411static struct op **find1case(struct op *t, const char *w)
2412{
2413 struct op *t1;
2414 struct op **tp;
2415 char **wp;
2416 char *cp;
2417
2418 if (t == NULL) {
2419 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
2420 return NULL;
2421 }
2422
2423 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
2424 T_CMD_NAMES[t->type]));
2425
2426 if (t->type == TLIST) {
2427 tp = find1case(t->left, w);
2428 if (tp != NULL) {
2429 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
2430 return tp;
2431 }
2432 t1 = t->right; /* TPAT */
2433 } else
2434 t1 = t;
2435
2436 for (wp = t1->words; *wp;) {
2437 cp = evalstr(*wp++, DOSUB);
2438 if (cp && gmatch(w, cp)) {
2439 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
2440 &t1->left));
2441 return &t1->left;
2442 }
2443 }
2444
2445 DBGPRINTF(("FIND1CASE: returning NULL\n"));
2446 return NULL;
2447}
2448
2449static struct op *findcase(struct op *t, const char *w)
2450{
2451 struct op **tp;
2452
2453 tp = find1case(t, w);
2454 return tp != NULL ? *tp : NULL;
2455}
2456
Eric Andersenff9eee42001-06-29 04:57:14 +00002457/*
2458 * execute tree
2459 */
2460
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002461static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002462{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002463 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002464 volatile int i, rv, a;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002465 const char *cp;
2466 char **wp, **wp2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002467 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002468 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002469 struct brkcon bc;
2470
2471#if __GNUC__
2472 /* Avoid longjmp clobbering */
2473 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002474#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002475
Eric Andersen12de6cf2004-08-04 19:19:10 +00002476 if (t == NULL) {
2477 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002478 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002479 }
2480
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002481 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002482 t->type, T_CMD_NAMES[t->type],
2483 ((t->words == NULL) ? "NULL" : t->words[0])));
2484
Eric Andersenff9eee42001-06-29 04:57:14 +00002485 rv = 0;
2486 a = areanum++;
2487 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002488 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2489 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002490
Eric Andersen8401eea2004-08-04 19:16:54 +00002491 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002492 case TDOT:
2493 DBGPRINTF3(("EXECUTE: TDOT\n"));
2494
2495 outtree_save = outtree;
2496
2497 newfile(evalstr(t->words[0], DOALL));
2498
2499 t->left = dowholefile(TLIST, 0);
2500 t->right = NULL;
2501
2502 outtree = outtree_save;
2503
2504 if (t->left)
2505 rv = execute(t->left, pin, pout, 0);
2506 if (t->right)
2507 rv = execute(t->right, pin, pout, 0);
2508 break;
2509
Eric Andersenff9eee42001-06-29 04:57:14 +00002510 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002511 rv = execute(t->left, pin, pout, 0);
2512 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002513
Eric Andersenff9eee42001-06-29 04:57:14 +00002514 case TCOM:
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002515 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002516 break;
2517
2518 case TPIPE:
2519 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002520 int pv[2];
2521
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002522 rv = openpipe(pv);
2523 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002524 break;
2525 pv[0] = remap(pv[0]);
2526 pv[1] = remap(pv[1]);
2527 (void) execute(t->left, pin, pv, 0);
2528 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002529 }
2530 break;
2531
2532 case TLIST:
2533 (void) execute(t->left, pin, pout, 0);
2534 rv = execute(t->right, pin, pout, 0);
2535 break;
2536
2537 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002538 {
2539 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002540
Eric Andersen12de6cf2004-08-04 19:19:10 +00002541 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2542
Eric Andersen8401eea2004-08-04 19:16:54 +00002543 i = vfork();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002544 if (i == 0) { /* child */
Eric Andersen8401eea2004-08-04 19:16:54 +00002545 signal(SIGINT, SIG_IGN);
2546 signal(SIGQUIT, SIG_IGN);
2547 if (interactive)
2548 signal(SIGTERM, SIG_DFL);
2549 interactive = 0;
2550 if (pin == NULL) {
2551 close(0);
"Vladimir N. Oleynik"6c35c7c2005-10-12 15:34:25 +00002552 open(bb_dev_null, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002553 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002554 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002555 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002556 interactive = hinteractive;
2557 if (i != -1) {
2558 setval(lookup("!"), putn(i));
2559 if (pin != NULL)
2560 closepipe(pin);
2561 if (interactive) {
2562 prs(putn(i));
2563 prs("\n");
2564 }
2565 } else
2566 rv = -1;
2567 setstatus(rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002568 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002569 break;
2570
2571 case TOR:
2572 case TAND:
2573 rv = execute(t->left, pin, pout, 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002574 t1 = t->right;
2575 if (t1 != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002576 rv = execute(t1, pin, pout, 0);
2577 break;
2578
2579 case TFOR:
2580 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002581 wp = dolv + 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002582 i = dolc;
2583 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002584 i = 0;
2585 } else {
2586 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002587 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002588 }
2589 vp = lookup(t->str);
2590 while (setjmp(bc.brkpt))
2591 if (isbreak)
2592 goto broken;
2593 brkset(&bc);
2594 for (t1 = t->left; i-- && *wp != NULL;) {
2595 setval(vp, *wp++);
2596 rv = execute(t1, pin, pout, 0);
2597 }
2598 brklist = brklist->nextlev;
2599 break;
2600
2601 case TWHILE:
2602 case TUNTIL:
2603 while (setjmp(bc.brkpt))
2604 if (isbreak)
2605 goto broken;
2606 brkset(&bc);
2607 t1 = t->left;
2608 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2609 rv = execute(t->right, pin, pout, 0);
2610 brklist = brklist->nextlev;
2611 break;
2612
2613 case TIF:
2614 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002615 if (t->right != NULL) {
2616 rv = !execute(t->left, pin, pout, 0) ?
2617 execute(t->right->left, pin, pout, 0) :
2618 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002619 }
2620 break;
2621
2622 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002623 cp = evalstr(t->str, DOSUB | DOTRIM);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002624 if (cp == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002625 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002626
2627 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2628 ((t->str == NULL) ? "NULL" : t->str),
2629 ((cp == NULL) ? "NULL" : cp)));
2630
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002631 t1 = findcase(t->left, cp);
2632 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002633 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002634 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002635 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002636 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002637 break;
2638
2639 case TBRACE:
2640/*
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002641 iopp = t->ioact;
2642 if (i)
Eric Andersenff9eee42001-06-29 04:57:14 +00002643 while (*iopp)
2644 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2645 rv = -1;
2646 break;
2647 }
2648*/
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002649 if (rv >= 0) {
2650 t1 = t->left;
2651 if (t1) {
2652 rv = execute(t1, pin, pout, 0);
2653 }
2654 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002655 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002656
2657 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002658
Eric Andersen8401eea2004-08-04 19:16:54 +00002659 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002660 t->words = wp2;
2661 isbreak = 0;
2662 freehere(areanum);
2663 freearea(areanum);
2664 areanum = a;
2665 if (interactive && intr) {
2666 closeall();
2667 fail();
2668 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002669
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002670 i = trapset;
2671 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002672 trapset = 0;
2673 runtrap(i);
2674 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002675
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002676 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002677 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002678}
2679
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002680typedef int (*builtin_func_ptr)(struct op *);
2681
2682static builtin_func_ptr inbuilt(const char *s) {
2683 const struct builtincmd *bp;
2684
2685 for (bp = builtincmds; bp->name != NULL; bp++)
2686 if (strcmp(bp->name, s) == 0)
2687 return bp->builtinfunc;
2688
2689 return NULL;
2690}
2691
2692static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002693{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002694 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002695 int i, rv;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002696 builtin_func_ptr shcom = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002697 int f;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002698 const char *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002699 struct ioword **iopp;
2700 int resetsig;
2701 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002702 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002703
2704 int *hpin = pin;
2705 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002706 char *hwp;
2707 int hinteractive;
2708 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002709 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002710 int hexecflg;
2711
2712#if __GNUC__
2713 /* Avoid longjmp clobbering */
2714 (void) &pin;
2715 (void) &pout;
2716 (void) &wp;
2717 (void) &shcom;
2718 (void) &cp;
2719 (void) &resetsig;
2720 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002721#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002722
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002723 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002724 pout, act));
2725 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2726 ((t->words == NULL) ? "NULL" : t->words[0])));
2727
Eric Andersenff9eee42001-06-29 04:57:14 +00002728 owp = wp;
2729 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002730 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002731 if (t->type == TCOM) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002732 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002733 cp = *wp;
2734
2735 /* strip all initial assignments */
2736 /* not correct wrt PATH=yyy command etc */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002737 if (flag['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002738 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002739 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002740 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002741 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002742
Eric Andersenff9eee42001-06-29 04:57:14 +00002743 if (cp == NULL && t->ioact == NULL) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002744 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2745 /**/;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002746 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002747 return setstatus(0);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002748 }
2749 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002750 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002751 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002752 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002753
Eric Andersenff9eee42001-06-29 04:57:14 +00002754 t->words = wp;
2755 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002756
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002757 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002758 f & FEXEC, owp));
2759
2760 if (shcom == NULL && (f & FEXEC) == 0) {
2761 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002762 hpin = pin;
2763 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002764 hwp = *wp;
2765 hinteractive = interactive;
2766 hintr = intr;
2767 hbrklist = brklist;
2768 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002769
Eric Andersen12de6cf2004-08-04 19:19:10 +00002770 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2771
2772 newpid = vfork();
2773
2774 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002775 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002776 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002777 }
2778
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002779 if (newpid > 0) { /* Parent */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002780 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002781 pin = hpin;
2782 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002783 *wp = hwp;
2784 interactive = hinteractive;
2785 intr = hintr;
2786 brklist = hbrklist;
2787 execflg = hexecflg;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002788/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002789 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002790 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002791*/
Eric Andersenff9eee42001-06-29 04:57:14 +00002792 if (pin != NULL)
2793 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002794
2795 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002796 }
2797
Eric Andersen12de6cf2004-08-04 19:19:10 +00002798 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002799 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002800
Eric Andersenff9eee42001-06-29 04:57:14 +00002801 if (interactive) {
2802 signal(SIGINT, SIG_IGN);
2803 signal(SIGQUIT, SIG_IGN);
2804 resetsig = 1;
2805 }
2806 interactive = 0;
2807 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002808 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002809 brklist = 0;
2810 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002811 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002812
Eric Andersenff9eee42001-06-29 04:57:14 +00002813 if (owp != NULL)
2814 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2815 if (shcom == NULL)
2816 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002817
Eric Andersenff9eee42001-06-29 04:57:14 +00002818#ifdef COMPIPE
2819 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2820 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002821 if (forked)
2822 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002823 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002824 }
2825#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002826
Eric Andersenff9eee42001-06-29 04:57:14 +00002827 if (pin != NULL) {
2828 dup2(pin[0], 0);
2829 closepipe(pin);
2830 }
2831 if (pout != NULL) {
2832 dup2(pout[1], 1);
2833 closepipe(pout);
2834 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002835
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002836 iopp = t->ioact;
2837 if (iopp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002838 if (shcom != NULL && shcom != doexec) {
2839 prs(cp);
2840 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002841 if (forked)
2842 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002843 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002844 }
2845 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002846 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2847 if (forked)
2848 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002849 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002850 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002851 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002852
2853 if (shcom) {
2854 i = setstatus((*shcom) (t));
2855 if (forked)
2856 _exit(i);
2857 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002858 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002859 }
2860
Eric Andersenff9eee42001-06-29 04:57:14 +00002861 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002862 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002863 close(i);
2864 if (resetsig) {
2865 signal(SIGINT, SIG_DFL);
2866 signal(SIGQUIT, SIG_DFL);
2867 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002868
Eric Andersen12de6cf2004-08-04 19:19:10 +00002869 if (t->type == TPAREN)
2870 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2871 if (wp[0] == NULL)
2872 _exit(0);
2873
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002874 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002875 prs(wp[0]);
2876 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002877 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002878 if (!execflg)
2879 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002880
2881 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2882
Eric Andersenff9eee42001-06-29 04:57:14 +00002883 leave();
2884 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002885 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002886}
2887
2888/*
2889 * 0< 1> are ignored as required
2890 * within pipelines.
2891 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002892static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002893{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002894 int u = -1;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002895 char *cp = NULL;
2896 const char *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002897
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002898 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002899 pipein, pipeout));
2900
Eric Andersenff9eee42001-06-29 04:57:14 +00002901 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002902 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002903
Eric Andersenff9eee42001-06-29 04:57:14 +00002904 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002905 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002906
Eric Andersenff9eee42001-06-29 04:57:14 +00002907 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002908 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002909
Eric Andersen8401eea2004-08-04 19:16:54 +00002910 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002911 if ((iop->io_flag & IOHERE) == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002912 cp = iop->io_name; /* huh?? */
2913 cp = evalstr(cp, DOSUB | DOTRIM);
2914 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002915 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002916 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002917
Eric Andersenff9eee42001-06-29 04:57:14 +00002918 if (iop->io_flag & IODUP) {
2919 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2920 prs(cp);
2921 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002922 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002923 }
2924 if (*cp == '-')
2925 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002926 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002927 }
2928 switch (iop->io_flag) {
2929 case IOREAD:
2930 u = open(cp, 0);
2931 break;
2932
2933 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002934 case IOHERE | IOXHERE:
2935 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002936 cp = (char*)"here file";
Eric Andersenff9eee42001-06-29 04:57:14 +00002937 break;
2938
Eric Andersen8401eea2004-08-04 19:16:54 +00002939 case IOWRITE | IOCAT:
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002940 u = open(cp, 1);
2941 if (u >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002942 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002943 break;
2944 }
2945 case IOWRITE:
2946 u = creat(cp, 0666);
2947 break;
2948
2949 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002950 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002951 break;
2952
2953 case IOCLOSE:
2954 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002955 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002956 }
2957 if (u < 0) {
2958 prs(cp);
2959 prs(": cannot ");
2960 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002961 return 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002962 }
2963 if (u != iop->io_unit) {
2964 dup2(u, iop->io_unit);
2965 close(u);
Eric Andersenff9eee42001-06-29 04:57:14 +00002966 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002967 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002968}
2969
Eric Andersenff9eee42001-06-29 04:57:14 +00002970/*
2971 * Enter a new loop level (marked for break/continue).
2972 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002973static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00002974{
2975 bc->nextlev = brklist;
2976 brklist = bc;
2977}
2978
2979/*
2980 * Wait for the last process created.
2981 * Print a message for each process found
2982 * that was killed by a signal.
2983 * Ignore interrupt signals while waiting
2984 * unless `canintr' is true.
2985 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002986static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00002987{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002988 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002989 int s;
2990 int oheedint = heedint;
2991
2992 heedint = 0;
2993 rv = 0;
2994 do {
2995 pid = wait(&s);
2996 if (pid == -1) {
2997 if (errno != EINTR || canintr)
2998 break;
2999 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003000 rv = WAITSIG(s);
3001 if (rv != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003002 if (rv < NSIGNAL) {
3003 if (signame[rv] != NULL) {
3004 if (pid != lastpid) {
3005 prn(pid);
3006 prs(": ");
3007 }
3008 prs(signame[rv]);
3009 }
3010 } else {
3011 if (pid != lastpid) {
3012 prn(pid);
3013 prs(": ");
3014 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003015 prs("Signal ");
3016 prn(rv);
3017 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003018 }
3019 if (WAITCORE(s))
3020 prs(" - core dumped");
3021 if (rv >= NSIGNAL || signame[rv])
3022 prs("\n");
3023 rv = -1;
3024 } else
3025 rv = WAITVAL(s);
3026 }
3027 } while (pid != lastpid);
3028 heedint = oheedint;
3029 if (intr) {
3030 if (interactive) {
3031 if (canintr)
3032 intr = 0;
3033 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003034 if (exstat == 0)
3035 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003036 onintr(0);
3037 }
3038 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003039 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003040}
3041
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003042static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003043{
3044 exstat = s;
3045 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003046 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003047}
3048
3049/*
3050 * PATH-searching interface to execve.
3051 * If getenv("PATH") were kept up-to-date,
3052 * execvp might be used.
3053 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003054static const char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003055{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003056 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003057 const char *sp;
3058 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003059 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003060 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003061
Rob Landleya299efb2006-08-10 21:46:43 +00003062 if (ENABLE_FEATURE_SH_STANDALONE_SHELL) {
3063 optind = 1;
3064 if (find_applet_by_name(name)) {
3065 /* We have to exec here since we vforked. Running
3066 * run_applet_by_name() won't work and bad things
3067 * will happen. */
3068 execve(CONFIG_BUSYBOX_EXEC_PATH, v, envp);
3069 }
Eric Andersen1c039232001-07-07 00:05:55 +00003070 }
Eric Andersen1c039232001-07-07 00:05:55 +00003071
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003072 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003073
Eric Andersen8401eea2004-08-04 19:16:54 +00003074 sp = any('/', c) ? "" : path->value;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003075 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003076 while (asis || *sp != '\0') {
3077 asis = 0;
3078 tp = e.linep;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003079 for (; *sp != '\0'; tp++) {
3080 *tp = *sp++;
3081 if (*tp == ':') {
3082 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003083 break;
3084 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003085 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003086 if (tp != e.linep)
3087 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003088 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003089
Eric Andersen12de6cf2004-08-04 19:19:10 +00003090 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3091
Eric Andersenff9eee42001-06-29 04:57:14 +00003092 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003093
Eric Andersenff9eee42001-06-29 04:57:14 +00003094 switch (errno) {
3095 case ENOEXEC:
3096 *v = e.linep;
3097 tp = *--v;
3098 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003099 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003100 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003101 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003102
3103 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003104 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003105
3106 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003107 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003108
3109 case EACCES:
3110 eacces++;
3111 break;
3112 }
3113 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003114 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003115}
3116
3117/*
3118 * Run the command produced by generator `f'
3119 * applied to stream `arg'.
3120 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003121static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003122{
3123 struct op *otree;
3124 struct wdblock *swdlist;
3125 struct wdblock *siolist;
3126 jmp_buf ev, rt;
3127 xint *ofail;
3128 int rv;
3129
3130#if __GNUC__
3131 /* Avoid longjmp clobbering */
3132 (void) &rv;
3133#endif
3134
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003135 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003136 areanum, outtree, failpt));
3137
Eric Andersenff9eee42001-06-29 04:57:14 +00003138 areanum++;
3139 swdlist = wdlist;
3140 siolist = iolist;
3141 otree = outtree;
3142 ofail = failpt;
3143 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003144
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003145 errpt = ev;
3146 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003147 wdlist = 0;
3148 iolist = 0;
3149 pushio(argp, f);
3150 e.iobase = e.iop;
3151 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003152 failpt = rt;
3153 if (setjmp(failpt) == 0 && yyparse() == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003154 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3155 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003156 } else {
3157 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003158 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003159
Eric Andersenff9eee42001-06-29 04:57:14 +00003160 wdlist = swdlist;
3161 iolist = siolist;
3162 failpt = ofail;
3163 outtree = otree;
3164 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003165
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003166 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003167}
3168
3169/* -------- do.c -------- */
3170
3171/*
3172 * built-in commands: doX
3173 */
3174
Eric Andersen8401eea2004-08-04 19:16:54 +00003175static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003176{
3177 int col;
3178 const struct builtincmd *x;
3179
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003180 puts("\nBuilt-in commands:\n"
3181 "-------------------");
Eric Andersen1c039232001-07-07 00:05:55 +00003182
Eric Andersen8401eea2004-08-04 19:16:54 +00003183 for (col = 0, x = builtincmds; x->builtinfunc != NULL; x++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003184 if (!x->name)
3185 continue;
3186 col += printf("%s%s", ((col == 0) ? "\t" : " "), x->name);
3187 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003188 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003189 col = 0;
3190 }
3191 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00003192#if ENABLE_FEATURE_SH_STANDALONE_SHELL
Eric Andersen1c039232001-07-07 00:05:55 +00003193 {
3194 int i;
3195 const struct BB_applet *applet;
Eric Andersen1c039232001-07-07 00:05:55 +00003196
Eric Andersen8401eea2004-08-04 19:16:54 +00003197 for (i = 0, applet = applets; i < NUM_APPLETS; applet++, i++) {
Eric Andersen1c039232001-07-07 00:05:55 +00003198 if (!applet->name)
3199 continue;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00003200
Eric Andersen8401eea2004-08-04 19:16:54 +00003201 col += printf("%s%s", ((col == 0) ? "\t" : " "), applet->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003202 if (col > 60) {
Denis Vlasenkoc6f188d2006-10-26 00:37:00 +00003203 puts("");
Eric Andersen1c039232001-07-07 00:05:55 +00003204 col = 0;
3205 }
3206 }
3207 }
3208#endif
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003209 puts("\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003210 return EXIT_SUCCESS;
3211}
3212
3213
3214
Eric Andersen8401eea2004-08-04 19:16:54 +00003215static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003216{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003217 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003218}
3219
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003220static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003221{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003222 const char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003223
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003224 cp = t->words[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003225 if (cp == NULL) {
3226 cp = homedir->value;
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003227 if (cp != NULL)
3228 goto do_cd;
3229 er = ": no home directory";
3230 } else {
3231 do_cd:
3232 if (chdir(cp) >= 0)
3233 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003234 er = ": bad directory";
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003235 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003236 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003237 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003238 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003239}
3240
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003241static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003242{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003243 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003244
Eric Andersen8401eea2004-08-04 19:16:54 +00003245 n = t->words[1] ? getn(t->words[1]) : 1;
3246 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003247 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003248 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003249 }
3250 dolv[n] = dolv[0];
3251 dolv += n;
3252 dolc -= n;
3253 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003254 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003255}
3256
3257/*
3258 * execute login and newgrp directly
3259 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003260static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003261{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003262 const char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003263
3264 if (interactive) {
3265 signal(SIGINT, SIG_DFL);
3266 signal(SIGQUIT, SIG_DFL);
3267 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003268 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003269 prs(t->words[0]);
3270 prs(": ");
3271 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003272 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003273}
3274
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003275static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003276{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003277 int i, n;
3278 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003279
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003280 cp = t->words[1];
3281 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003282 i = umask(0);
3283 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003284 for (n = 3 * 4; (n -= 3) >= 0;)
3285 putc('0' + ((i >> n) & 07), stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003286 putc('\n', stderr);
3287 } else {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003288/* huh??? '8','9' are not allowed! */
Eric Andersen8401eea2004-08-04 19:16:54 +00003289 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3290 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003291 umask(n);
3292 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003293 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003294}
3295
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003296static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003297{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003298 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003299 jmp_buf ex;
3300 xint *ofail;
3301
3302 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003303 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003304 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003305 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003306 execflg = 1;
3307 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003308 failpt = ex;
3309 if (setjmp(failpt) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003310 execute(t, NOPIPE, NOPIPE, FEXEC);
3311 failpt = ofail;
3312 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003313 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003314}
3315
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003316static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003317{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003318 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003319 const char *sp;
3320 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003321 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003322 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003323
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003324 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 +00003325
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003326 cp = t->words[1];
3327 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003328 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003329 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003330 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003331 DBGPRINTF(("DODOT: cp is %s\n", cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003332
Eric Andersen8401eea2004-08-04 19:16:54 +00003333 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003334
3335 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3336 ((sp == NULL) ? "NULL" : sp),
3337 ((e.linep == NULL) ? "NULL" : e.linep)));
3338
Eric Andersenff9eee42001-06-29 04:57:14 +00003339 while (*sp) {
3340 tp = e.linep;
3341 while (*sp && (*tp = *sp++) != ':')
3342 tp++;
3343 if (tp != e.linep)
3344 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003345
Eric Andersen8401eea2004-08-04 19:16:54 +00003346 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003347
3348 /* Original code */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003349 i = open(e.linep, 0);
3350 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003351 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003352 maltmp = remap(i);
3353 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3354
3355 next(maltmp); /* Basically a PUSHIO */
3356
3357 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3358
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003359 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003360 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003361 } /* while */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003362
Eric Andersenff9eee42001-06-29 04:57:14 +00003363 prs(cp);
3364 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003365
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003366 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003367}
3368
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003369static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003370{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003371 int i;
3372 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003373
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003374 cp = t->words[1];
3375 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003376 i = getn(cp);
3377 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003378 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003379 } else
3380 i = -1;
3381 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003382 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003383}
3384
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003385static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003386{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003387 char *cp, **wp;
3388 int nb = 0;
3389 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003390
3391 if (t->words[1] == NULL) {
3392 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003393 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003394 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003395 for (wp = t->words + 1; *wp; wp++) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003396 for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
3397 nb = read(0, cp, sizeof(*cp));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003398 if (nb != sizeof(*cp))
Eric Andersenff9eee42001-06-29 04:57:14 +00003399 break;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003400 nl = (*cp == '\n');
3401 if (nl || (wp[1] && any(*cp, ifs->value)))
3402 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003403 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003404 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003405 if (nb <= 0)
3406 break;
3407 setval(lookup(*wp), e.linep);
3408 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003409 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003410}
3411
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003412static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003413{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003414 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003415}
3416
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003417static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003418{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003419 int n, i;
3420 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003421
3422 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003423 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003424 if (trap[i]) {
3425 prn(i);
3426 prs(": ");
3427 prs(trap[i]);
3428 prs("\n");
3429 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003430 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003431 }
3432 resetsig = isdigit(*t->words[1]);
3433 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3434 n = getsig(t->words[i]);
3435 freecell(trap[n]);
3436 trap[n] = 0;
3437 if (!resetsig) {
3438 if (*t->words[1] != '\0') {
3439 trap[n] = strsave(t->words[1], 0);
3440 setsig(n, sig);
3441 } else
3442 setsig(n, SIG_IGN);
3443 } else {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003444 if (interactive) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003445 if (n == SIGINT)
3446 setsig(n, onintr);
3447 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003448 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003449 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00003450 setsig(n, SIG_DFL);
3451 }
3452 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003453 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003454}
3455
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003456static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003457{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003458 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003459
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003460 n = getn(s);
3461 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003462 err("trap: bad signal number");
3463 n = 0;
3464 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003465 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003466}
3467
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003468static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003469{
3470 if (n == 0)
3471 return;
3472 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3473 ourtrap[n] = 1;
3474 signal(n, f);
3475 }
3476}
3477
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003478static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003479{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003480 char *s;
3481 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003482
3483 s = as;
3484 m = 1;
3485 if (*s == '-') {
3486 m = -1;
3487 s++;
3488 }
3489 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003490 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003491 if (*s) {
3492 prs(as);
3493 err(": bad number");
3494 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003495 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003496}
3497
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003498static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003499{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003500 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003501}
3502
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003503static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003504{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003505 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003506}
3507
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003508static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003509{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003510 struct brkcon *bc;
3511 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003512
Eric Andersen8401eea2004-08-04 19:16:54 +00003513 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003514 if (nl <= 0)
3515 nl = 999;
3516 do {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003517 bc = brklist;
3518 if (bc == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003519 break;
3520 brklist = bc->nextlev;
3521 } while (--nl);
3522 if (nl) {
3523 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003524 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003525 }
3526 isbreak = val;
3527 longjmp(bc->brkpt, 1);
3528 /* NOTREACHED */
3529}
3530
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003531static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003532{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003533 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003534
3535 execflg = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003536 cp = t->words[1];
3537 if (cp != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003538 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003539
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003540 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003541
Eric Andersenff9eee42001-06-29 04:57:14 +00003542 leave();
3543 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003544 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003545}
3546
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003547static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003548{
Eric Andersen8401eea2004-08-04 19:16:54 +00003549 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003550 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003551}
3552
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003553static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003554{
Eric Andersen8401eea2004-08-04 19:16:54 +00003555 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003556 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003557}
3558
Eric Andersen8401eea2004-08-04 19:16:54 +00003559static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003560{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003561 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003562 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3563
Eric Andersenff9eee42001-06-29 04:57:14 +00003564 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003565 for (; *wp != NULL; wp++) {
3566 if (isassign(*wp)) {
3567 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003568
Matt Kraaif69bfc72001-07-12 19:39:59 +00003569 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003570 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003571 *cp = '\0';
3572 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003573 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003574 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003575 else
3576 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003577 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003578 } else
3579 putvlist(key, 1);
3580}
3581
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003582static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003583{
3584 prs(s);
3585 err(": bad identifier");
3586}
3587
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003588static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003589{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003590 struct var *vp;
3591 char *cp;
3592 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003593
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003594 cp = t->words[1];
3595 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003596 for (vp = vlist; vp; vp = vp->next)
3597 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003598 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003599 }
3600 if (*cp == '-') {
3601 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003602 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003603 if (*++cp == 0)
3604 flag['x'] = flag['v'] = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003605 else {
3606 for (; *cp; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003607 switch (*cp) {
3608 case 'e':
3609 if (!interactive)
3610 flag['e']++;
3611 break;
3612
3613 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003614 if (*cp >= 'a' && *cp <= 'z')
3615 flag[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003616 break;
3617 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003618 }
3619 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003620 setdash();
3621 }
3622 if (t->words[1]) {
3623 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003624 for (n = 1; t->words[n]; n++)
3625 setarea((char *) t->words[n], 0);
3626 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003627 dolv = t->words;
3628 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003629 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003630 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003631 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003632}
3633
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003634static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003635{
Matt Kraai69edfec2001-08-06 14:14:18 +00003636 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003637 write(out, s, strlen(s));
3638 write(out, "\n", 1);
3639 }
3640}
3641
3642
3643/*
3644 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3645 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003646 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003647static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003648{
3649 struct tms buf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003650 long clk_tck = sysconf(_SC_CLK_TCK);
Eric Andersenff9eee42001-06-29 04:57:14 +00003651
3652 times(&buf);
3653 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003654 (int) (buf.tms_utime / clk_tck / 60),
3655 ((double) buf.tms_utime) / clk_tck,
3656 (int) (buf.tms_stime / clk_tck / 60),
3657 ((double) buf.tms_stime) / clk_tck,
3658 (int) (buf.tms_cutime / clk_tck / 60),
3659 ((double) buf.tms_cutime) / clk_tck,
3660 (int) (buf.tms_cstime / clk_tck / 60),
3661 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003662 return 0;
3663}
3664
3665
Eric Andersenff9eee42001-06-29 04:57:14 +00003666/* -------- eval.c -------- */
3667
3668/*
3669 * ${}
3670 * `command`
3671 * blank interpretation
3672 * quoting
3673 * glob
3674 */
3675
Eric Andersen8401eea2004-08-04 19:16:54 +00003676static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003677{
3678 struct wdblock *wb;
3679 char **wp;
3680 char **wf;
3681 jmp_buf ev;
3682
3683#if __GNUC__
3684 /* Avoid longjmp clobbering */
3685 (void) &wp;
3686 (void) &ap;
3687#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003688
3689 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3690
Eric Andersenff9eee42001-06-29 04:57:14 +00003691 wp = NULL;
3692 wb = NULL;
3693 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003694 errpt = ev;
3695 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003696 while (*ap && isassign(*ap))
3697 expand(*ap++, &wb, f & ~DOGLOB);
3698 if (flag['k']) {
3699 for (wf = ap; *wf; wf++) {
3700 if (isassign(*wf))
3701 expand(*wf, &wb, f & ~DOGLOB);
3702 }
3703 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003704 for (wb = addword((char *) 0, wb); *ap; ap++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003705 if (!flag['k'] || !isassign(*ap))
3706 expand(*ap, &wb, f & ~DOKEY);
3707 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003708 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003709 wp = getwords(wb);
3710 quitenv();
3711 } else
3712 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003713
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003714 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003715}
3716
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003717
Eric Andersenff9eee42001-06-29 04:57:14 +00003718/*
3719 * Make the exported environment from the exported
3720 * names in the dictionary. Keyword assignments
3721 * will already have been done.
3722 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003723static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003724{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003725 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003726
3727 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003728
Eric Andersenff9eee42001-06-29 04:57:14 +00003729 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003730 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003731 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003732 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003733 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003734}
3735
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003736static int expand(const char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003737{
3738 jmp_buf ev;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003739 char *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003740
3741#if __GNUC__
3742 /* Avoid longjmp clobbering */
3743 (void) &cp;
3744#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003745
3746 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3747
Eric Andersenff9eee42001-06-29 04:57:14 +00003748 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003749
Eric Andersenff9eee42001-06-29 04:57:14 +00003750 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003751 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003752
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003753 if (!anys("$`'\"", cp) && !anys(ifs->value, cp)
3754 && ((f & DOGLOB) == 0 || !anys("[*?", cp))
3755 ) {
3756 xp = strsave(cp, areanum);
Eric Andersenff9eee42001-06-29 04:57:14 +00003757 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003758 unquote(xp);
3759 *wbp = addword(xp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003760 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003761 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003762 errpt = ev;
3763 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003764 PUSHIO(aword, cp, strchar);
3765 e.iobase = e.iop;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003766 while ((xp = blank(f)) && gflg == 0) {
3767 e.linep = xp;
3768 xp = strsave(xp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003769 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003770 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003771 unquote(xp);
3772 *wbp = addword(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003773 } else
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003774 *wbp = glob(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003775 }
3776 quitenv();
3777 } else
3778 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003779 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003780}
3781
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003782static char *evalstr(char *cp, int f)
3783{
3784 struct wdblock *wb;
3785
3786 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
3787
3788 wb = NULL;
3789 if (expand(cp, &wb, f)) {
3790 if (wb == NULL || wb->w_nword == 0
3791 || (cp = wb->w_words[0]) == NULL
3792 ) {
Denis Vlasenko8e858e22007-03-07 09:35:43 +00003793// TODO: I suspect that
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003794// char *evalstr(char *cp, int f) is actually
3795// const char *evalstr(const char *cp, int f)!
3796 cp = (char*)"";
3797 }
3798 DELETE(wb);
3799 } else
3800 cp = NULL;
3801 return cp;
3802}
3803
3804
Eric Andersenff9eee42001-06-29 04:57:14 +00003805/*
3806 * Blank interpretation and quoting
3807 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003808static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003809{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003810 int c, c1;
3811 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003812 int scanequals, foundequals;
3813
Eric Andersen12de6cf2004-08-04 19:19:10 +00003814 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3815
Eric Andersenff9eee42001-06-29 04:57:14 +00003816 sp = e.linep;
3817 scanequals = f & DOKEY;
3818 foundequals = 0;
3819
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003820 loop:
3821 c = subgetc('"', foundequals);
3822 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003823 case 0:
3824 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003825 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003826 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003827 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003828
3829 default:
3830 if (f & DOBLANK && any(c, ifs->value))
3831 goto loop;
3832 break;
3833
3834 case '"':
3835 case '\'':
3836 scanequals = 0;
3837 if (INSUB())
3838 break;
3839 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3840 if (c == 0)
3841 break;
3842 if (c == '\'' || !any(c, "$`\""))
3843 c |= QUOTE;
3844 *e.linep++ = c;
3845 }
3846 c = 0;
3847 }
3848 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003849 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003850 scanequals = 0;
3851 for (;;) {
3852 c = subgetc('"', foundequals);
3853 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003854 f & (DOBLANK && any(c, ifs->value)) ||
3855 (!INSUB() && any(c, "\"'"))) {
3856 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003857 unget(c);
3858 if (any(c, "\"'"))
3859 goto loop;
3860 break;
3861 }
3862 if (scanequals) {
3863 if (c == '=') {
3864 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003865 scanequals = 0;
3866 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003867 scanequals = 0;
3868 }
3869 *e.linep++ = c;
3870 }
3871 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003872 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003873}
3874
3875/*
3876 * Get characters, substituting for ` and $
3877 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003878static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003879{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003880 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003881
3882 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003883
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003884 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003885 c = my_getc(ec);
3886 if (!INSUB() && ec != '\'') {
3887 if (c == '`') {
3888 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003889 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003890 e.iop->task = XGRAVE;
3891 goto again;
3892 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003893 if (c == '$') {
3894 c = dollar(quoted);
3895 if (c == 0) {
3896 e.iop->task = XDOLL;
3897 goto again;
3898 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003899 }
3900 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003901 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003902}
3903
3904/*
3905 * Prepare to generate the string returned by ${} substitution.
3906 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003907static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003908{
3909 int otask;
3910 struct io *oiop;
3911 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003912 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003913 struct var *vp;
3914
Eric Andersen12de6cf2004-08-04 19:19:10 +00003915 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3916
Eric Andersenff9eee42001-06-29 04:57:14 +00003917 c = readc();
3918 s = e.linep;
3919 if (c != '{') {
3920 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003921 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003922 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003923 if (e.linep < elinep)
3924 *e.linep++ = c;
3925 unget(c);
3926 }
3927 c = 0;
3928 } else {
3929 oiop = e.iop;
3930 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003931
Eric Andersenff9eee42001-06-29 04:57:14 +00003932 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003933 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003934 if (e.linep < elinep)
3935 *e.linep++ = c;
3936 if (oiop == e.iop)
3937 e.iop->task = otask;
3938 if (c != '}') {
3939 err("unclosed ${");
3940 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003941 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003942 }
3943 }
3944 if (e.linep >= elinep) {
3945 err("string in ${} too long");
3946 gflg++;
3947 e.linep -= 10;
3948 }
3949 *e.linep = 0;
3950 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003951 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003952 if (any(*cp, "=-+?")) {
3953 c = *cp;
3954 *cp++ = 0;
3955 break;
3956 }
3957 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3958 if (dolc > 1) {
3959 /* currently this does not distinguish $* and $@ */
3960 /* should check dollar */
3961 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00003962 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003963 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003964 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00003965 s[0] = '1';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003966 s[1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003967 }
3968 }
3969 vp = lookup(s);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003970 dolp = vp->value;
3971 if (dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003972 switch (c) {
3973 case '=':
3974 if (isdigit(*s)) {
3975 err("cannot use ${...=...} with $n");
3976 gflg++;
3977 break;
3978 }
3979 setval(vp, cp);
3980 dolp = vp->value;
3981 break;
3982
3983 case '-':
3984 dolp = strsave(cp, areanum);
3985 break;
3986
3987 case '?':
3988 if (*cp == 0) {
3989 prs("missing value for ");
3990 err(s);
3991 } else
3992 err(cp);
3993 gflg++;
3994 break;
3995 }
3996 } else if (c == '+')
3997 dolp = strsave(cp, areanum);
3998 if (flag['u'] && dolp == null) {
3999 prs("unset variable: ");
4000 err(s);
4001 gflg++;
4002 }
4003 e.linep = s;
4004 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004005 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004006}
4007
4008/*
4009 * Run the command in `...` and read its output.
4010 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004011
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004012static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004013{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004014 const char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004015 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004016 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004017 int pf[2];
Eric Andersen737f5fb2003-03-14 16:05:59 +00004018 static char child_cmd[LINELIM];
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004019 const char *src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004020 char *dest;
4021 int count;
4022 int ignore;
4023 int ignore_once;
4024 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004025 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004026
4027#if __GNUC__
4028 /* Avoid longjmp clobbering */
4029 (void) &cp;
4030#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004031
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004032 for (cp = e.iop->argp->aword; *cp != '`'; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004033 if (*cp == 0) {
4034 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004035 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004036 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004037 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004038
4039 /* string copy with dollar expansion */
4040 src = e.iop->argp->aword;
4041 dest = child_cmd;
4042 count = 0;
4043 ignore = 0;
4044 ignore_once = 0;
4045 while ((*src != '`') && (count < LINELIM)) {
4046 if (*src == '\'')
4047 ignore = !ignore;
4048 if (*src == '\\')
4049 ignore_once = 1;
4050 if (*src == '$' && !ignore && !ignore_once) {
4051 struct var *vp;
4052 char var_name[LINELIM];
4053 char alt_value[LINELIM];
4054 int var_index = 0;
4055 int alt_index = 0;
4056 char operator = 0;
4057 int braces = 0;
4058 char *value;
4059
4060 src++;
4061 if (*src == '{') {
4062 braces = 1;
4063 src++;
4064 }
4065
4066 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004067 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004068 var_name[var_index++] = *src++;
4069 var_name[var_index] = 0;
4070
4071 if (braces) {
4072 switch (*src) {
4073 case '}':
4074 break;
4075 case '-':
4076 case '=':
4077 case '+':
4078 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004079 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004080 break;
4081 default:
4082 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004083 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004084 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004085 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004086 src++;
4087 while (*src && (*src != '}')) {
4088 alt_value[alt_index++] = *src++;
4089 }
4090 alt_value[alt_index] = 0;
4091 if (*src != '}') {
4092 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004093 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004094 }
4095 }
4096 src++;
4097 }
4098
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004099 if (isalpha(*var_name)) {
4100 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004101
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004102 char *namep = var_name;
4103
4104 *dest++ = '$';
4105 if (braces)
4106 *dest++ = '{';
4107 while (*namep)
4108 *dest++ = *namep++;
4109 if (operator) {
4110 char *altp = alt_value;
4111 *dest++ = operator;
4112 while (*altp)
4113 *dest++ = *altp++;
4114 }
4115 if (braces)
4116 *dest++ = '}';
4117
4118 wb = addword(lookup(var_name)->name, wb);
4119 } else {
4120 /* expand */
4121
4122 vp = lookup(var_name);
4123 if (vp->value != null)
4124 value = (operator == '+') ?
4125 alt_value : vp->value;
4126 else if (operator == '?') {
4127 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004128 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004129 } else if (alt_index && (operator != '+')) {
4130 value = alt_value;
4131 if (operator == '=')
4132 setval(vp, value);
4133 } else
4134 continue;
4135
4136 while (*value && (count < LINELIM)) {
4137 *dest++ = *value++;
4138 count++;
4139 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004140 }
4141 } else {
4142 *dest++ = *src++;
4143 count++;
4144 ignore_once = 0;
4145 }
4146 }
4147 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004148
Eric Andersenff9eee42001-06-29 04:57:14 +00004149 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004150 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004151
Eric Andersen8401eea2004-08-04 19:16:54 +00004152 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004153
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004154 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004155
Eric Andersen737f5fb2003-03-14 16:05:59 +00004156 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004157 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004158 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004159 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004160 }
4161 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004162 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004163 e.iop->argp->aword = ++cp;
4164 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004165 PUSHIO(afile, remap(pf[0]),
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004166 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004167 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004168 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004169 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004170 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004171 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004172 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4173 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004174
Eric Andersenff9eee42001-06-29 04:57:14 +00004175 dup2(pf[1], 1);
4176 closepipe(pf);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004177
Eric Andersen8401eea2004-08-04 19:16:54 +00004178 argument_list[0] = (char *) DEFAULT_SHELL;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004179 argument_list[1] = (char *) "-c";
Eric Andersen737f5fb2003-03-14 16:05:59 +00004180 argument_list[2] = child_cmd;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004181 argument_list[3] = NULL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004182
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004183 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004184 prs(argument_list[0]);
4185 prs(": ");
4186 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004187 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004188}
4189
Eric Andersen737f5fb2003-03-14 16:05:59 +00004190
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004191static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004192{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004193 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004194
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004195 s = as;
4196 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004197 while (*s)
4198 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004199 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004200}
4201
4202/* -------- glob.c -------- */
4203
4204/*
4205 * glob
4206 */
4207
4208#define scopy(x) strsave((x), areanum)
4209#define BLKSIZ 512
4210#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4211
Eric Andersen8401eea2004-08-04 19:16:54 +00004212static struct wdblock *cl, *nl;
4213static char spcl[] = "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004214
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004215static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004216{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004217 int i;
4218 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004219
4220 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004221 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004222 i = 0;
4223 for (pp = cp; *pp; pp++)
4224 if (any(*pp, spcl))
4225 i++;
4226 else if (!any(*pp & ~QUOTE, spcl))
4227 *pp &= ~QUOTE;
4228 if (i != 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004229 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004230 nl = newword(cl->w_nword * 2);
4231 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004232 for (pp = cl->w_words[i]; *pp; pp++)
4233 if (any(*pp, spcl)) {
4234 globname(cl->w_words[i], pp);
4235 break;
4236 }
4237 if (*pp == '\0')
4238 nl = addword(scopy(cl->w_words[i]), nl);
4239 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004240 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004241 DELETE(cl->w_words[i]);
4242 DELETE(cl);
4243 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004244 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004245 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004246 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004247 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004248 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004249 wb = addword(cl->w_words[i], wb);
4250 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004251 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004252 }
4253 }
4254 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004255 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004256}
4257
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004258static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004259{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004260 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004261 char *name, *gp, *dp;
4262 int k;
4263 DIR *dirp;
4264 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004265 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004266 struct stat dbuf;
4267
4268 for (np = we; np != pp; pp--)
4269 if (pp[-1] == '/')
4270 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004271 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004272 *cp++ = *np++;
4273 *cp++ = '.';
4274 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004275 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004276 *cp++ = *np++;
4277 *cp = '\0';
4278 dirp = opendir(dp);
4279 if (dirp == 0) {
4280 DELETE(dp);
4281 DELETE(gp);
4282 return;
4283 }
4284 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004285 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004286 /* XXX Hmmm... What this could be? (abial) */
4287 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004288 if (ent[j].d_ino == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004289 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004290 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004291 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004292 if (dname[0] == '.')
4293 if (*gp != '.')
4294 continue;
4295 for (k = 0; k < NAME_MAX; k++)
4296 if (any(dname[k], spcl))
4297 dname[k] |= QUOTE;
4298 if (gmatch(dname, gp)) {
4299 name = generate(we, pp, dname, np);
4300 if (*np && !anys(np, spcl)) {
4301 if (stat(name, &dbuf)) {
4302 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004303 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004304 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004305 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004306 nl = addword(name, nl);
4307 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004308 }
4309 closedir(dirp);
4310 DELETE(dp);
4311 DELETE(gp);
4312}
4313
4314/*
4315 * generate a pathname as below.
4316 * start..end1 / middle end
4317 * the slashes come for free
4318 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004319static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004320{
4321 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004322 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004323
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004324 p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004325 for (xp = start1; xp != end1;)
4326 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004327 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004328 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004329 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004330 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004331}
4332
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004333static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004334{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004335 int i;
4336 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004337
4338 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004339 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004340 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004341 return 1;
4342 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004343}
4344
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004345static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004346{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004347 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004348}
4349
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004350
Eric Andersenff9eee42001-06-29 04:57:14 +00004351/* -------- word.c -------- */
4352
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004353static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004354{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004355 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004356
Eric Andersen8401eea2004-08-04 19:16:54 +00004357 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004358 wb->w_bsize = nw;
4359 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004360 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004361}
4362
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004363static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004364{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004365 struct wdblock *wb2;
4366 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004367
4368 if (wb == NULL)
4369 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004370 nw = wb->w_nword;
4371 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004372 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004373 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4374 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004375 wb2->w_nword = nw;
4376 DELETE(wb);
4377 wb = wb2;
4378 }
4379 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004380 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004381}
Eric Andersen8401eea2004-08-04 19:16:54 +00004382
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004383static
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004384char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004385{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004386 char **wd;
4387 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004388
4389 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004390 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004391 if (wb->w_nword == 0) {
4392 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004393 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004394 }
4395 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004396 memcpy((char *) wd, (char *) wb->w_words, nb);
4397 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004398 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004399}
4400
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004401static int (*func) (char *, char *);
4402static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004403
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004404static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004405{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004406 char *index1, *index2, *index3;
4407 int c;
4408 int m;
4409
4410 m = globv;
4411 index1 = i;
4412 index2 = j;
4413 index3 = k;
4414 do {
4415 c = *index1;
4416 *index1++ = *index3;
4417 *index3++ = *index2;
4418 *index2++ = c;
4419 } while (--m);
4420}
4421
4422static void glob2(char *i, char *j)
4423{
4424 char *index1, *index2, c;
4425 int m;
4426
4427 m = globv;
4428 index1 = i;
4429 index2 = j;
4430 do {
4431 c = *index1;
4432 *index1++ = *index2;
4433 *index2++ = c;
4434 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004435}
4436
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004437static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004438{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004439 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004440 int v2;
4441 char *lptr, *hptr;
4442 int c;
4443 unsigned n;
4444
Eric Andersenff9eee42001-06-29 04:57:14 +00004445 v2 = globv;
4446
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004447 top:
4448 n = (int) (lim - base);
4449 if (n <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004450 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004451 n = v2 * (n / (2 * v2));
4452 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004453 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004454 j = lim - v2;
4455 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004456 if (i < lptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004457 c = (*func) (i, lptr);
4458 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004459 lptr -= v2;
4460 glob2(i, lptr);
Eric Andersenff9eee42001-06-29 04:57:14 +00004461 continue;
4462 }
4463 if (c < 0) {
4464 i += v2;
4465 continue;
4466 }
4467 }
4468
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004469 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004470 if (j > hptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004471 c = (*func) (hptr, j);
4472 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004473 hptr += v2;
4474 glob2(hptr, j);
Eric Andersenff9eee42001-06-29 04:57:14 +00004475 goto begin;
4476 }
4477 if (c > 0) {
4478 if (i == lptr) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004479 hptr += v2;
4480 glob3(i, hptr, j);
4481 i = (lptr += v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004482 goto begin;
4483 }
4484 glob2(i, j);
4485 j -= v2;
4486 i += v2;
4487 continue;
4488 }
4489 j -= v2;
4490 goto begin;
4491 }
4492
4493
4494 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004495 if (lptr - base >= lim - hptr) {
4496 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004497 lim = lptr;
4498 } else {
4499 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004500 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004501 }
4502 goto top;
4503 }
4504
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004505 lptr -= v2;
4506 glob3(j, lptr, i);
4507 j = (hptr -= v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004508 }
4509}
4510
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004511static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004512{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004513 func = a3;
4514 globv = a2;
4515 glob1(a0, a0 + a1 * a2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004516}
4517
Eric Andersenff9eee42001-06-29 04:57:14 +00004518
4519/* -------- io.c -------- */
4520
4521/*
4522 * shell IO
4523 */
4524
Eric Andersen8401eea2004-08-04 19:16:54 +00004525static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004526{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004527 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004528
Eric Andersen8401eea2004-08-04 19:16:54 +00004529 if (e.linep > elinep) {
4530 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004531 err("input line too long");
4532 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004533 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004534 }
4535 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004536 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004537 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004538 c = readc();
4539 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004540 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004541 c |= QUOTE;
4542 }
4543 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004544 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004545}
4546
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004547static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004548{
4549 if (e.iop >= e.iobase)
4550 e.iop->peekc = c;
4551}
4552
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004553static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004554{
Eric Andersen8401eea2004-08-04 19:16:54 +00004555 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004556}
4557
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004558static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004559{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004560 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004561
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004562 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004563
4564 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004565 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004566 c = e.iop->peekc;
4567 if (c != '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004568 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004569 return c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004570 }
4571 if (e.iop->prev != 0) {
4572 c = (*e.iop->iofn)(e.iop->argp, e.iop);
4573 if (c != '\0') {
4574 if (c == -1) {
4575 e.iop++;
4576 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004577 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004578 if (e.iop == iostack)
4579 ioecho(c);
4580 e.iop->prev = c;
4581 return e.iop->prev;
Eric Andersenff9eee42001-06-29 04:57:14 +00004582 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004583 if (e.iop->task == XIO && e.iop->prev != '\n') {
4584 e.iop->prev = 0;
4585 if (e.iop == iostack)
4586 ioecho('\n');
4587 return '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004588 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004589 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004590 if (e.iop->task == XIO) {
4591 if (multiline) {
4592 e.iop->prev = 0;
4593 return e.iop->prev;
4594 }
4595 if (interactive && e.iop == iostack + 1) {
4596#if ENABLE_FEATURE_EDITING
4597 current_prompt = prompt->value;
4598#else
4599 prs(prompt->value);
4600#endif
4601 }
4602 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004603 } /* FOR */
4604
4605 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004606 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004607 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004608 }
4609
4610 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004611 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004612
Eric Andersenff9eee42001-06-29 04:57:14 +00004613 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004614 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004615}
4616
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004617static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004618{
4619 if (flag['v'])
4620 write(2, &c, sizeof c);
4621}
4622
Eric Andersen12de6cf2004-08-04 19:19:10 +00004623
Eric Andersen8401eea2004-08-04 19:16:54 +00004624static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004625{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004626 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004627 argp->afid, e.iop));
4628
4629 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004630 if (++e.iop >= &iostack[NPUSH]) {
4631 e.iop--;
4632 err("Shell input nested too deeply");
4633 gflg++;
4634 return;
4635 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004636
4637 /* We did not overflow the NPUSH array spots so setup data structs */
4638
4639 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004640
4641 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004642 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004643 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004644
4645 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4646 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4647
4648 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4649
4650 if (e.iop == &iostack[0])
4651 e.iop->argp->afbuf = &mainbuf;
4652 else
4653 e.iop->argp->afbuf = &sharedbuf;
4654
4655 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4656 /* This line appears to be active when running scripts from command line */
4657 if ((isatty(e.iop->argp->afile) == 0)
4658 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004659 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004660 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4661 bufid = AFID_ID; /* AFID_ID = 0 */
4662
4663 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004664 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004665
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004666 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004667 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004668 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004669 &mainbuf, &sharedbuf, bufid, e.iop));
4670
Eric Andersenff9eee42001-06-29 04:57:14 +00004671 }
4672
Eric Andersen8401eea2004-08-04 19:16:54 +00004673 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004674 e.iop->peekc = 0;
4675 e.iop->xchar = 0;
4676 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004677
Eric Andersenff9eee42001-06-29 04:57:14 +00004678 if (fn == filechar || fn == linechar)
4679 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004680 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004681 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004682 e.iop->task = XGRAVE;
4683 else
4684 e.iop->task = XOTHER;
4685}
4686
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004687static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004688{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004689 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004690
4691 xp = e.iobase;
4692 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004693 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004694}
4695
4696/*
4697 * Input generating functions
4698 */
4699
4700/*
4701 * Produce the characters of a string, then a newline, then EOF.
4702 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004703static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004704{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004705 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004706
4707 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004708 return 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004709 c = *ap->aword++;
4710 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004711 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004712 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004713 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004714 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004715}
4716
4717/*
4718 * Given a list of words, produce the characters
4719 * in them, with a space after each word.
4720 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004721static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004722{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004723 char c;
4724 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004725
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004726 wl = ap->awordlist;
4727 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004728 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004729 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004730 c = *(*wl)++;
4731 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004732 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004733 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004734 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004735 }
4736 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004737 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004738}
4739
4740/*
4741 * Return the characters of a list of words,
4742 * producing a space between them.
4743 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004744static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004745{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004746 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004747
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004748 wp = *ap->awordlist++;
4749 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004750 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004751 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004752 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004753 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004754}
4755
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004756static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004757{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004758 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004759
4760 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004761 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004762 c = *ap->aword++;
4763 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004764 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004765 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004766 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004767 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004768}
4769
4770/*
4771 * Produce the characters from a single word (string).
4772 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004773static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004774{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004775 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004776 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004777 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004778}
4779
4780/*
4781 * Produce quoted characters from a single word (string).
4782 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004783static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004784{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004785 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004786
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004787 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004788 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004789 c = *ap->aword++;
4790 if (c)
4791 c |= QUOTE;
4792 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004793}
4794
4795/*
4796 * Return the characters from a file.
4797 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004798static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004799{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004800 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004801 char c;
4802 struct iobuf *bp = ap->afbuf;
4803
4804 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004805 i = (ap->afid != bp->id);
4806 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004807 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004808 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004809
Eric Andersen8401eea2004-08-04 19:16:54 +00004810 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4811 if (i <= 0) {
4812 closef(ap->afile);
4813 return 0;
4814 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004815
Eric Andersen8401eea2004-08-04 19:16:54 +00004816 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004817 bp->bufp = bp->buf;
4818 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004819 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004820
Eric Andersen8401eea2004-08-04 19:16:54 +00004821 ap->afpos++;
4822 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004823 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00004824#if ENABLE_FEATURE_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004825 if (interactive && isatty(ap->afile)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004826 static char mycommand[BUFSIZ];
4827 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004828
Eric Andersen8401eea2004-08-04 19:16:54 +00004829 while (size == 0 || position >= size) {
Denis Vlasenko8e1c7152007-01-22 07:21:38 +00004830 read_line_input(current_prompt, mycommand, BUFSIZ, line_input_state);
Eric Andersen8401eea2004-08-04 19:16:54 +00004831 size = strlen(mycommand);
4832 position = 0;
4833 }
4834 c = mycommand[position];
4835 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004836 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004837 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004838#endif
4839 i = safe_read(ap->afile, &c, sizeof(c));
4840 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004841}
4842
4843/*
4844 * Return the characters from a here temp file.
4845 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004846static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004847{
4848 char c;
4849
Eric Andersenff9eee42001-06-29 04:57:14 +00004850 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4851 close(ap->afile);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004852 c = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00004853 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004854 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004855}
4856
4857/*
4858 * Return the characters produced by a process (`...`).
4859 * Quote them if required, and remove any trailing newline characters.
4860 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004861static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004862{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004863 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004864
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004865 c = qgravechar(ap, iop) & ~QUOTE;
4866 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004867 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004868 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004869}
4870
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004871static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004872{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004873 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004874
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004875 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004876
4877 if (iop->xchar) {
4878 if (iop->nlcount) {
4879 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004880 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004881 }
4882 c = iop->xchar;
4883 iop->xchar = 0;
4884 } else if ((c = filechar(ap)) == '\n') {
4885 iop->nlcount = 1;
4886 while ((c = filechar(ap)) == '\n')
4887 iop->nlcount++;
4888 iop->xchar = c;
4889 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004890 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004891 iop->nlcount--;
4892 c = '\n';
4893 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004894 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004895}
4896
4897/*
4898 * Return a single command (usually the first line) from a file.
4899 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004900static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004901{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004902 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004903
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004904 c = filechar(ap);
4905 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004906 if (!multiline) {
4907 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004908 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004909 }
4910 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004911 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004912}
4913
Eric Andersenff9eee42001-06-29 04:57:14 +00004914/*
4915 * remap fd into Shell's fd space
4916 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004917static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004918{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004919 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004920 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004921 int newfd;
4922
Eric Andersen12de6cf2004-08-04 19:19:10 +00004923 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004924
4925 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004926 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004927 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004928
Eric Andersenff9eee42001-06-29 04:57:14 +00004929 do {
4930 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004931 newfd = dup(fd);
4932 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004933 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004934
Eric Andersen8401eea2004-08-04 19:16:54 +00004935 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004936 if (map[i])
4937 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004938
Eric Andersenff9eee42001-06-29 04:57:14 +00004939 if (fd < 0)
4940 err("too many files open in shell");
4941 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004942
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004943 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004944}
4945
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004946static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004947{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004948 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004949
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004950 i = pipe(pv);
4951 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004952 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004953 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004954}
4955
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004956static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004957{
4958 if (pv != NULL) {
4959 close(*pv++);
4960 close(*pv);
4961 }
4962}
4963
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004964
Eric Andersenff9eee42001-06-29 04:57:14 +00004965/* -------- here.c -------- */
4966
4967/*
4968 * here documents
4969 */
4970
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004971static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004972{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004973 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004974
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004975 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00004976
4977 h = (struct here *) space(sizeof(struct here));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004978 if (h == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004979 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004980
Eric Andersenff9eee42001-06-29 04:57:14 +00004981 h->h_tag = evalstr(s, DOSUB);
4982 if (h->h_tag == 0)
4983 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004984
Eric Andersenff9eee42001-06-29 04:57:14 +00004985 h->h_iop = iop;
4986 iop->io_name = 0;
4987 h->h_next = NULL;
4988 if (inhere == 0)
4989 inhere = h;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004990 else {
4991 for (lh = inhere; lh != NULL; lh = lh->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004992 if (lh->h_next == 0) {
4993 lh->h_next = h;
4994 break;
4995 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004996 }
4997 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004998 iop->io_flag |= IOHERE | IOXHERE;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004999 for (s = h->h_tag; *s; s++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005000 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005001 iop->io_flag &= ~IOXHERE;
5002 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005003 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005004 }
Eric Andersenff9eee42001-06-29 04:57:14 +00005005 h->h_dosub = iop->io_flag & IOXHERE;
5006}
5007
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005008static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005009{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005010 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005011
5012 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005013
5014 /* Scan here files first leaving inhere list in place */
5015 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005016 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005017
5018 /* Make inhere list active - keep list intact for scraphere */
5019 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005020 hp->h_next = acthere;
5021 acthere = inhere;
5022 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005023 }
5024}
5025
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005026static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005027{
5028 int tf;
5029 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005030 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005031 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005032 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005033 char *thenext;
5034
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005035 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005036
Eric Andersenff9eee42001-06-29 04:57:14 +00005037 tf = mkstemp(tname);
5038 if (tf < 0)
5039 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005040
Eric Andersenff9eee42001-06-29 04:57:14 +00005041 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00005042 errpt = ev;
5043 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00005044 unlink(tname);
5045 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005046 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005047 e.iobase = e.iop;
5048 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005049 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00005050#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005051 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005052#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005053 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005054#endif
5055 }
5056 thenext = myline;
5057 while ((c = my_getc(ec)) != '\n' && c) {
5058 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005059 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005060 if (thenext >= &myline[LINELIM]) {
5061 c = 0;
5062 break;
5063 }
5064 *thenext++ = c;
5065 }
5066 *thenext = 0;
5067 if (strcmp(s, myline) == 0 || c == 0)
5068 break;
5069 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005070 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005071 }
5072 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005073 prs("here document `");
5074 prs(s);
5075 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005076 }
5077 quitenv();
5078 }
5079 close(tf);
5080}
5081
5082/*
5083 * open here temp file.
5084 * if unquoted here, expand here temp file into second temp file.
5085 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005086static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005087{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005088 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005089 int tf;
5090
5091#if __GNUC__
5092 /* Avoid longjmp clobbering */
5093 (void) &tf;
5094#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005095 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005096 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005097
5098 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5099
Eric Andersenff9eee42001-06-29 04:57:14 +00005100 hf = open(hname, 0);
5101 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005102 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005103
Eric Andersenff9eee42001-06-29 04:57:14 +00005104 if (xdoll) {
5105 char c;
5106 char tname[30] = ".msh_XXXXXX";
5107 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005108
Eric Andersenff9eee42001-06-29 04:57:14 +00005109 tf = mkstemp(tname);
5110 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005111 return -1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005112 errpt = ev;
5113 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005114 PUSHIO(afile, hf, herechar);
5115 setbase(e.iop);
5116 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005117 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005118 write(tf, &c, sizeof c);
5119 }
5120 quitenv();
5121 } else
5122 unlink(tname);
5123 close(tf);
5124 tf = open(tname, 0);
5125 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005126 return tf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005127 }
5128 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005129}
5130
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005131static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005132{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005133 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005134
5135 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005136
5137 for (h = inhere; h != NULL; h = h->h_next) {
5138 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005139 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005140 }
5141 inhere = NULL;
5142}
5143
5144/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005145static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005146{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005147 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005148
5149 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005150
5151 hl = NULL;
5152 for (h = acthere; h != NULL; h = h->h_next)
5153 if (getarea((char *) h) >= area) {
5154 if (h->h_iop->io_name != NULL)
5155 unlink(h->h_iop->io_name);
5156 if (hl == NULL)
5157 acthere = h->h_next;
5158 else
5159 hl->h_next = h->h_next;
5160 } else
5161 hl = h;
5162}
5163
5164
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005165/* -------- sh.c -------- */
5166/*
5167 * shell
5168 */
5169
Denis Vlasenko06af2162007-02-03 17:28:39 +00005170int msh_main(int argc, char **argv);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005171int msh_main(int argc, char **argv)
5172{
5173 int f;
5174 char *s;
5175 int cflag;
5176 char *name, **ap;
5177 int (*iof) (struct ioarg *);
5178
5179#if ENABLE_FEATURE_EDITING
5180 line_input_state = new_line_input_t(FOR_SHELL);
5181#endif
5182
5183 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
5184
5185 initarea();
5186 ap = environ;
5187 if (ap != NULL) {
5188 while (*ap)
5189 assign(*ap++, !COPYV);
5190 for (ap = environ; *ap;)
5191 export(lookup(*ap++));
5192 }
5193 closeall();
5194 areanum = 1;
5195
5196 shell = lookup("SHELL");
5197 if (shell->value == null)
5198 setval(shell, (char *)DEFAULT_SHELL);
5199 export(shell);
5200
5201 homedir = lookup("HOME");
5202 if (homedir->value == null)
5203 setval(homedir, "/");
5204 export(homedir);
5205
5206 setval(lookup("$"), putn(getpid()));
5207
5208 path = lookup("PATH");
5209 if (path->value == null) {
5210 if (geteuid() == 0)
5211 setval(path, "/sbin:/bin:/usr/sbin:/usr/bin");
5212 else
5213 setval(path, "/bin:/usr/bin");
5214 }
5215 export(path);
5216
5217 ifs = lookup("IFS");
5218 if (ifs->value == null)
5219 setval(ifs, " \t\n");
5220
5221#ifdef MSHDEBUG
5222 mshdbg_var = lookup("MSHDEBUG");
5223 if (mshdbg_var->value == null)
5224 setval(mshdbg_var, "0");
5225#endif
5226
5227 prompt = lookup("PS1");
5228#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5229 if (prompt->value == null)
5230#endif
5231 setval(prompt, DEFAULT_USER_PROMPT);
5232 if (geteuid() == 0) {
5233 setval(prompt, DEFAULT_ROOT_PROMPT);
5234 prompt->status &= ~EXPORT;
5235 }
5236 cprompt = lookup("PS2");
5237#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5238 if (cprompt->value == null)
5239#endif
5240 setval(cprompt, "> ");
5241
5242 iof = filechar;
5243 cflag = 0;
5244 name = *argv++;
5245 if (--argc >= 1) {
5246 if (argv[0][0] == '-' && argv[0][1] != '\0') {
5247 for (s = argv[0] + 1; *s; s++)
5248 switch (*s) {
5249 case 'c':
5250 prompt->status &= ~EXPORT;
5251 cprompt->status &= ~EXPORT;
5252 setval(prompt, "");
5253 setval(cprompt, "");
5254 cflag = 1;
5255 if (--argc > 0)
5256 PUSHIO(aword, *++argv, iof = nlchar);
5257 break;
5258
5259 case 'q':
5260 qflag = SIG_DFL;
5261 break;
5262
5263 case 's':
5264 /* standard input */
5265 break;
5266
5267 case 't':
5268 prompt->status &= ~EXPORT;
5269 setval(prompt, "");
5270 iof = linechar;
5271 break;
5272
5273 case 'i':
5274 interactive++;
5275 default:
5276 if (*s >= 'a' && *s <= 'z')
5277 flag[(int) *s]++;
5278 }
5279 } else {
5280 argv--;
5281 argc++;
5282 }
5283
5284 if (iof == filechar && --argc > 0) {
5285 setval(prompt, "");
5286 setval(cprompt, "");
5287 prompt->status &= ~EXPORT;
5288 cprompt->status &= ~EXPORT;
5289
5290/* Shell is non-interactive, activate printf-based debug */
5291#ifdef MSHDEBUG
5292 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
5293 if (mshdbg < 0)
5294 mshdbg = 0;
5295#endif
5296 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
5297
5298 name = *++argv;
5299 if (newfile(name))
5300 exit(1); /* Exit on error */
5301 }
5302 }
5303
5304 setdash();
5305
5306 /* This won't be true if PUSHIO has been called, say from newfile() above */
5307 if (e.iop < iostack) {
5308 PUSHIO(afile, 0, iof);
5309 if (isatty(0) && isatty(1) && !cflag) {
5310 interactive++;
5311#if !ENABLE_FEATURE_SH_EXTRA_QUIET
5312#ifdef MSHDEBUG
5313 printf("\n\n%s Built-in shell (msh with debug)\n", BB_BANNER);
5314#else
5315 printf("\n\n%s Built-in shell (msh)\n", BB_BANNER);
5316#endif
5317 printf("Enter 'help' for a list of built-in commands.\n\n");
5318#endif
5319 }
5320 }
5321
5322 signal(SIGQUIT, qflag);
5323 if (name && name[0] == '-') {
5324 interactive++;
5325 f = open(".profile", 0);
5326 if (f >= 0)
5327 next(remap(f));
5328 f = open("/etc/profile", 0);
5329 if (f >= 0)
5330 next(remap(f));
5331 }
5332 if (interactive)
5333 signal(SIGTERM, sig);
5334
5335 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
5336 signal(SIGINT, onintr);
5337 dolv = argv;
5338 dolc = argc;
5339 dolv[0] = name;
5340 if (dolc > 1) {
5341 for (ap = ++argv; --argc > 0;) {
5342 *ap = *argv++;
5343 if (assign(*ap, !COPYV)) {
5344 dolc--; /* keyword */
5345 } else {
5346 ap++;
5347 }
5348 }
5349 }
5350 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
5351
5352 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
5353
5354 for (;;) {
5355 if (interactive && e.iop <= iostack) {
5356#if ENABLE_FEATURE_EDITING
5357 current_prompt = prompt->value;
5358#else
5359 prs(prompt->value);
5360#endif
5361 }
5362 onecommand();
5363 /* Ensure that getenv("PATH") stays current */
5364 setenv("PATH", path->value, 1);
5365 }
5366
5367 DBGPRINTF(("MSH_MAIN: returning.\n"));
5368}
5369
5370
Eric Andersenff9eee42001-06-29 04:57:14 +00005371/*
5372 * Copyright (c) 1987,1997, Prentice Hall
5373 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005374 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005375 * Redistribution and use of the MINIX operating system in source and
5376 * binary forms, with or without modification, are permitted provided
5377 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005378 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005379 * Redistributions of source code must retain the above copyright
5380 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005381 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005382 * Redistributions in binary form must reproduce the above
5383 * copyright notice, this list of conditions and the following
5384 * disclaimer in the documentation and/or other materials provided
5385 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005386 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005387 * Neither the name of Prentice Hall nor the names of the software
5388 * authors or contributors may be used to endorse or promote
5389 * products derived from this software without specific prior
5390 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005391 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005392 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5393 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5394 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5395 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5396 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5397 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5398 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5399 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5400 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5401 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5402 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5403 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5404 *
5405 */