blob: 9f95fe28aff462930e0d8a83c48a420fb2d60517 [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
Denis Vlasenko95cb3262007-04-09 03:06:34 +000016#include <sys/times.h>
17#include <setjmp.h>
Denis Vlasenko55f30b02007-03-24 22:42:29 +000018
Mike Frysinger67a32ad2007-03-09 08:25:24 +000019#ifdef STANDALONE
20# ifndef _GNU_SOURCE
21# define _GNU_SOURCE
22# endif
Mike Frysinger67a32ad2007-03-09 08:25:24 +000023# include <sys/types.h>
24# include <sys/stat.h>
25# include <sys/wait.h>
26# include <signal.h>
27# include <stdio.h>
28# include <stdlib.h>
29# include <unistd.h>
30# include <string.h>
31# include <errno.h>
32# include <dirent.h>
33# include <fcntl.h>
34# include <ctype.h>
35# include <assert.h>
36# define bb_dev_null "/dev/null"
37# define DEFAULT_SHELL "/proc/self/exe"
38# define CONFIG_BUSYBOX_EXEC_PATH "/proc/self/exe"
Denis Vlasenkoca525b42007-06-13 12:27:17 +000039# define bb_banner "busybox standalone"
Denis Vlasenko80d14be2007-04-10 23:03:30 +000040# define ENABLE_FEATURE_SH_STANDALONE 0
Mike Frysinger67a32ad2007-03-09 08:25:24 +000041# define bb_msg_memory_exhausted "memory exhausted"
42# define xmalloc(size) malloc(size)
43# define msh_main(argc,argv) main(argc,argv)
44# define safe_read(fd,buf,count) read(fd,buf,count)
45# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
46# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
47# define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000048static int find_applet_by_name(const char *applet)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000049{
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000050 return -1;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000051}
Denis Vlasenko10457b92007-03-27 22:01:31 +000052static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000053{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000054 unsigned i, out, res;
55 assert(sizeof(unsigned) == 4);
56 if (buflen) {
57 out = 0;
58 for (i = 1000000000; i; i /= 10) {
59 res = n / i;
60 if (res || out || i == 1) {
Denis Vlasenko4b924f32007-05-30 00:29:55 +000061 if (!--buflen) break;
62 out++;
63 n -= res*i;
64 *buf++ = '0' + res;
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000065 }
66 }
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000067 }
Denis Vlasenko10457b92007-03-27 22:01:31 +000068 return buf;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000069}
Denis Vlasenko10457b92007-03-27 22:01:31 +000070static char *itoa_to_buf(int n, char *buf, unsigned buflen)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000071{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000072 if (buflen && n < 0) {
73 n = -n;
74 *buf++ = '-';
75 buflen--;
76 }
Denis Vlasenko10457b92007-03-27 22:01:31 +000077 return utoa_to_buf((unsigned)n, buf, buflen);
Mike Frysinger67a32ad2007-03-09 08:25:24 +000078}
79static char local_buf[12];
80static char *itoa(int n)
81{
Denis Vlasenko10457b92007-03-27 22:01:31 +000082 *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000083 return local_buf;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000084}
85#else
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000086# include "busybox.h" /* for applet_names */
Denis Vlasenko489f93e2007-02-01 01:43:16 +000087extern char **environ;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000088#endif
Eric Andersenff9eee42001-06-29 04:57:14 +000089
Mike Frysinger17811882006-05-05 20:33:07 +000090/*#define MSHDEBUG 1*/
Eric Andersen12de6cf2004-08-04 19:19:10 +000091
92#ifdef MSHDEBUG
Mike Frysinger14ff19b2006-06-20 20:37:01 +000093int mshdbg = MSHDEBUG;
Eric Andersen12de6cf2004-08-04 19:19:10 +000094
Denis Vlasenko51742f42007-04-12 00:32:05 +000095#define DBGPRINTF(x) if (mshdbg>0) printf x
96#define DBGPRINTF0(x) if (mshdbg>0) printf x
97#define DBGPRINTF1(x) if (mshdbg>1) printf x
98#define DBGPRINTF2(x) if (mshdbg>2) printf x
99#define DBGPRINTF3(x) if (mshdbg>3) printf x
100#define DBGPRINTF4(x) if (mshdbg>4) printf x
101#define DBGPRINTF5(x) if (mshdbg>5) printf x
102#define DBGPRINTF6(x) if (mshdbg>6) printf x
103#define DBGPRINTF7(x) if (mshdbg>7) printf x
104#define DBGPRINTF8(x) if (mshdbg>8) printf x
105#define DBGPRINTF9(x) if (mshdbg>9) printf x
Eric Andersen12de6cf2004-08-04 19:19:10 +0000106
107int mshdbg_rc = 0;
108
Denis Vlasenko51742f42007-04-12 00:32:05 +0000109#define RCPRINTF(x) if (mshdbg_rc) printf x
Eric Andersen12de6cf2004-08-04 19:19:10 +0000110
111#else
112
113#define DBGPRINTF(x)
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000114#define DBGPRINTF0(x) ((void)0)
115#define DBGPRINTF1(x) ((void)0)
116#define DBGPRINTF2(x) ((void)0)
117#define DBGPRINTF3(x) ((void)0)
118#define DBGPRINTF4(x) ((void)0)
119#define DBGPRINTF5(x) ((void)0)
120#define DBGPRINTF6(x) ((void)0)
121#define DBGPRINTF7(x) ((void)0)
122#define DBGPRINTF8(x) ((void)0)
123#define DBGPRINTF9(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000124
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000125#define RCPRINTF(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000126
127#endif /* MSHDEBUG */
128
129
Denis Vlasenko38f63192007-01-22 09:03:07 +0000130#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger2a131752006-06-06 06:26:12 +0000131# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
132# define DEFAULT_USER_PROMPT "\\u:\\w$ "
133#else
134# define DEFAULT_ROOT_PROMPT "# "
135# define DEFAULT_USER_PROMPT "$ "
136#endif
137
138
Eric Andersenff9eee42001-06-29 04:57:14 +0000139/* -------- sh.h -------- */
140/*
141 * shell
142 */
143
Eric Andersen12de6cf2004-08-04 19:19:10 +0000144#define LINELIM 2100
145#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +0000146
Eric Andersen392947c2002-12-11 07:42:46 +0000147#undef NOFILE
Eric Andersen12de6cf2004-08-04 19:19:10 +0000148#define NOFILE 20 /* Number of open files */
149#define NUFILE 10 /* Number of user-accessible files */
150#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000151
152/*
153 * values returned by wait
154 */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000155#define WAITSIG(s) ((s) & 0177)
156#define WAITVAL(s) (((s) >> 8) & 0377)
157#define WAITCORE(s) (((s) & 0200) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +0000158
159/*
Eric Andersenaff114c2004-04-14 17:51:38 +0000160 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +0000161 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000162typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +0000163
164/*
165 * shell components
166 */
Eric Andersenff9eee42001-06-29 04:57:14 +0000167#define NOBLOCK ((struct op *)NULL)
168#define NOWORD ((char *)NULL)
169#define NOWORDS ((char **)NULL)
170#define NOPIPE ((int *)NULL)
171
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000172/*
173 * redirection
174 */
175struct ioword {
176 short io_unit; /* unit affected */
177 short io_flag; /* action (below) */
178 char *io_name; /* file name */
179};
180
181#define IOREAD 1 /* < */
182#define IOHERE 2 /* << (here file) */
183#define IOWRITE 4 /* > */
184#define IOCAT 8 /* >> */
185#define IOXHERE 16 /* ${}, ` in << */
186#define IODUP 32 /* >&digit */
187#define IOCLOSE 64 /* >&- */
188
189#define IODEFAULT (-1) /* token for default IO unit */
190
191
Eric Andersenff9eee42001-06-29 04:57:14 +0000192/*
193 * Description of a command or an operation on commands.
194 * Might eventually use a union.
195 */
196struct op {
Eric Andersen8401eea2004-08-04 19:16:54 +0000197 int type; /* operation type, see below */
198 char **words; /* arguments to a command */
199 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000200 struct op *left;
201 struct op *right;
Eric Andersen8401eea2004-08-04 19:16:54 +0000202 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000203};
204
Eric Andersen8401eea2004-08-04 19:16:54 +0000205#define TCOM 1 /* command */
206#define TPAREN 2 /* (c-list) */
207#define TPIPE 3 /* a | b */
208#define TLIST 4 /* a [&;] b */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000209#define TOR 5 /* || */
Eric Andersen8401eea2004-08-04 19:16:54 +0000210#define TAND 6 /* && */
Eric Andersenff9eee42001-06-29 04:57:14 +0000211#define TFOR 7
Eric Andersen12de6cf2004-08-04 19:19:10 +0000212#define TDO 8
Eric Andersenff9eee42001-06-29 04:57:14 +0000213#define TCASE 9
Eric Andersen12de6cf2004-08-04 19:19:10 +0000214#define TIF 10
Eric Andersenff9eee42001-06-29 04:57:14 +0000215#define TWHILE 11
216#define TUNTIL 12
217#define TELIF 13
Eric Andersen8401eea2004-08-04 19:16:54 +0000218#define TPAT 14 /* pattern in case */
219#define TBRACE 15 /* {c-list} */
220#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000221/* Added to support "." file expansion */
222#define TDOT 17
223
224/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000225#ifdef MSHDEBUG
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000226static const char *const T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000227 "PLACEHOLDER",
228 "TCOM",
229 "TPAREN",
230 "TPIPE",
231 "TLIST",
232 "TOR",
233 "TAND",
234 "TFOR",
235 "TDO",
236 "TCASE",
237 "TIF",
238 "TWHILE",
239 "TUNTIL",
240 "TELIF",
241 "TPAT",
242 "TBRACE",
243 "TASYNC",
244 "TDOT",
245};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000246#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000247
248/*
249 * actions determining the environment of a process
250 */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000251#define FEXEC 1 /* execute without forking */
Eric Andersenff9eee42001-06-29 04:57:14 +0000252
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000253#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000254
Eric Andersenff9eee42001-06-29 04:57:14 +0000255/*
256 * flags to control evaluation of words
257 */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000258#define DOSUB 1 /* interpret $, `, and quotes */
259#define DOBLANK 2 /* perform blank interpretation */
260#define DOGLOB 4 /* interpret [?* */
261#define DOKEY 8 /* move words with `=' to 2nd arg. list */
262#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000263
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000264#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
Eric Andersenff9eee42001-06-29 04:57:14 +0000265
Eric Andersenff9eee42001-06-29 04:57:14 +0000266
Eric Andersen8401eea2004-08-04 19:16:54 +0000267struct brkcon {
268 jmp_buf brkpt;
269 struct brkcon *nextlev;
270};
Eric Andersenff9eee42001-06-29 04:57:14 +0000271
Eric Andersen12de6cf2004-08-04 19:19:10 +0000272
Eric Andersenff9eee42001-06-29 04:57:14 +0000273/*
Eric Andersenff9eee42001-06-29 04:57:14 +0000274 * flags:
275 * -e: quit on error
276 * -k: look for name=value everywhere on command line
277 * -n: no execution
278 * -t: exit after reading and executing one command
279 * -v: echo as read
280 * -x: trace
281 * -u: unset variables net diagnostic
282 */
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000283static char flags['z' - 'a' + 1] ALIGN1;
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000284/* this looks weird, but is OK ... we index FLAG with 'a'...'z' */
285#define FLAG (flags - 'a')
Eric Andersenff9eee42001-06-29 04:57:14 +0000286
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000287/* moved to G: static char *trap[_NSIG + 1]; */
288/* moved to G: static char ourtrap[_NSIG + 1]; */
Eric Andersen8401eea2004-08-04 19:16:54 +0000289static int trapset; /* trap pending */
Eric Andersenff9eee42001-06-29 04:57:14 +0000290
Eric Andersen8401eea2004-08-04 19:16:54 +0000291static int yynerrs; /* yacc */
Eric Andersenff9eee42001-06-29 04:57:14 +0000292
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000293/* moved to G: static char line[LINELIM]; */
Eric Andersenff9eee42001-06-29 04:57:14 +0000294
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000295#if ENABLE_FEATURE_EDITING
296static char *current_prompt;
297static line_input_t *line_input_state;
298#endif
299
Eric Andersen12de6cf2004-08-04 19:19:10 +0000300
Eric Andersenff9eee42001-06-29 04:57:14 +0000301/*
302 * other functions
303 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000304static const char *rexecve(char *c, char **v, char **envp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000305static char *evalstr(char *cp, int f);
306static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000307static char *unquote(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000308static int rlookup(char *n);
309static struct wdblock *glob(char *cp, struct wdblock *wb);
310static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000311static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000312static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000313static char **eval(char **ap, int f);
314static int setstatus(int s);
315static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000316
Eric Andersen8401eea2004-08-04 19:16:54 +0000317static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000318
Eric Andersen8401eea2004-08-04 19:16:54 +0000319static int newenv(int f);
320static void quitenv(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000321static void next(int f);
322static void setdash(void);
323static void onecommand(void);
324static void runtrap(int i);
Eric Andersenff9eee42001-06-29 04:57:14 +0000325
Eric Andersen12de6cf2004-08-04 19:19:10 +0000326
Eric Andersenff9eee42001-06-29 04:57:14 +0000327/* -------- area stuff -------- */
328
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000329#define REGSIZE sizeof(struct region)
330#define GROWBY (256)
331/* #define SHRINKBY (64) */
332#undef SHRINKBY
333#define FREE (32767)
334#define BUSY (0)
335#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000336
337
338struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000339 struct region *next;
340 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000341};
342
343
Eric Andersenff9eee42001-06-29 04:57:14 +0000344/* -------- grammar stuff -------- */
345typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000346 char *cp;
347 char **wp;
348 int i;
349 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000350} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000351
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000352#define WORD 256
353#define LOGAND 257
354#define LOGOR 258
355#define BREAK 259
356#define IF 260
357#define THEN 261
358#define ELSE 262
359#define ELIF 263
360#define FI 264
361#define CASE 265
362#define ESAC 266
363#define FOR 267
364#define WHILE 268
365#define UNTIL 269
366#define DO 270
367#define DONE 271
368#define IN 272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000369/* Added for "." file expansion */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000370#define DOT 273
Eric Andersen12de6cf2004-08-04 19:19:10 +0000371
Eric Andersenff9eee42001-06-29 04:57:14 +0000372#define YYERRCODE 300
373
374/* flags to yylex */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000375#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000376
Eric Andersen8401eea2004-08-04 19:16:54 +0000377static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000378static struct op *andor(void);
379static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000380static int synio(int cf);
381static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000382static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000383static struct op *nested(int type, int mark);
384static struct op *command(int cf);
385static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000386static struct op *thenpart(void);
387static struct op *elsepart(void);
388static struct op *caselist(void);
389static struct op *casepart(void);
390static char **pattern(void);
391static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000392static struct op *list(struct op *t1, struct op *t2);
393static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000394static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000395static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000396static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000397static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000398static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000399static struct ioword *io(int u, int f, char *cp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000400static int yylex(int cf);
401static int collect(int c, int c1);
402static int dual(int c);
403static void diag(int ec);
404static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000405
406/* -------- var.h -------- */
407
Eric Andersen8401eea2004-08-04 19:16:54 +0000408struct var {
409 char *value;
410 char *name;
411 struct var *next;
412 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000413};
Eric Andersenff9eee42001-06-29 04:57:14 +0000414
Eric Andersen8401eea2004-08-04 19:16:54 +0000415#define COPYV 1 /* flag to setval, suggesting copy */
416#define RONLY 01 /* variable is read-only */
417#define EXPORT 02 /* variable is to be exported */
418#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000419
Eric Andersen8401eea2004-08-04 19:16:54 +0000420static int yyparse(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000421
422static int execute(struct op *t, int *pin, int *pout, int act);
Eric Andersenff9eee42001-06-29 04:57:14 +0000423
Eric Andersen12de6cf2004-08-04 19:19:10 +0000424
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000425#define AFID_NOBUF (~0)
426#define AFID_ID 0
427
428
Eric Andersenff9eee42001-06-29 04:57:14 +0000429/* -------- io.h -------- */
430/* io buffer */
431struct iobuf {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000432 unsigned id; /* buffer id */
433 char buf[512]; /* buffer */
434 char *bufp; /* pointer into buffer */
435 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000436};
437
438/* possible arguments to an IO function */
439struct ioarg {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000440 const char *aword;
Eric Andersen8401eea2004-08-04 19:16:54 +0000441 char **awordlist;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000442 int afile; /* file descriptor */
443 unsigned afid; /* buffer id */
444 long afpos; /* file position */
445 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000446};
Eric Andersen8401eea2004-08-04 19:16:54 +0000447
Eric Andersenff9eee42001-06-29 04:57:14 +0000448/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000449struct io {
450 int (*iofn) (struct ioarg *, struct io *);
451 struct ioarg *argp;
452 int peekc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000453 char prev; /* previous character read by readc() */
454 char nlcount; /* for `'s */
455 char xchar; /* for `'s */
456 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000457};
Eric Andersen8401eea2004-08-04 19:16:54 +0000458
Eric Andersen8401eea2004-08-04 19:16:54 +0000459#define XOTHER 0 /* none of the below */
460#define XDOLL 1 /* expanding ${} */
461#define XGRAVE 2 /* expanding `'s */
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000462#define XIO 3 /* file IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000463
464/* in substitution */
465#define INSUB() (e.iop->task == XGRAVE || e.iop->task == XDOLL)
466
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000467static struct ioarg temparg = { 0, 0, 0, AFID_NOBUF, 0 }; /* temporary for PUSHIO */
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000468/* moved to G: static struct ioarg ioargstack[NPUSH]; */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000469static struct io iostack[NPUSH];
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000470/* moved to G: static struct iobuf sharedbuf = { AFID_NOBUF }; */
471/* moved to G: static struct iobuf mainbuf = { AFID_NOBUF }; */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000472static unsigned bufid = AFID_ID; /* buffer id counter */
473
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000474#define RUN(what,arg,gen) ((temparg.what = (arg)), run(&temparg,(gen)))
475
476
477/*
Eric Andersenff9eee42001-06-29 04:57:14 +0000478 * input generators for IO structure
479 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000480static int nlchar(struct ioarg *ap);
481static int strchar(struct ioarg *ap);
482static int qstrchar(struct ioarg *ap);
483static int filechar(struct ioarg *ap);
484static int herechar(struct ioarg *ap);
485static int linechar(struct ioarg *ap);
486static int gravechar(struct ioarg *ap, struct io *iop);
487static int qgravechar(struct ioarg *ap, struct io *iop);
488static int dolchar(struct ioarg *ap);
489static int wdchar(struct ioarg *ap);
490static void scraphere(void);
491static void freehere(int area);
492static void gethere(void);
493static void markhere(char *s, struct ioword *iop);
494static int herein(char *hname, int xdoll);
495static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000496
Eric Andersen12de6cf2004-08-04 19:19:10 +0000497
Eric Andersen8401eea2004-08-04 19:16:54 +0000498static int eofc(void);
499static int readc(void);
500static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000501static void ioecho(char c);
Eric Andersenff9eee42001-06-29 04:57:14 +0000502
Eric Andersen12de6cf2004-08-04 19:19:10 +0000503
Eric Andersenff9eee42001-06-29 04:57:14 +0000504/*
505 * IO control
506 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000507static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000508#define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen)))
Eric Andersen8401eea2004-08-04 19:16:54 +0000509static int remap(int fd);
510static int openpipe(int *pv);
511static void closepipe(int *pv);
512static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000513
Eric Andersenff9eee42001-06-29 04:57:14 +0000514/* -------- word.h -------- */
515
Eric Andersen8401eea2004-08-04 19:16:54 +0000516#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000517
Eric Andersen8401eea2004-08-04 19:16:54 +0000518struct wdblock {
519 short w_bsize;
520 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000521 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000522 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000523};
524
Eric Andersen8401eea2004-08-04 19:16:54 +0000525static struct wdblock *addword(char *wd, struct wdblock *wb);
526static struct wdblock *newword(int nw);
527static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000528
Eric Andersenff9eee42001-06-29 04:57:14 +0000529/* -------- misc stuff -------- */
530
Eric Andersen12de6cf2004-08-04 19:19:10 +0000531static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000532static int iosetup(struct ioword *iop, int pipein, int pipeout);
Eric Andersen8401eea2004-08-04 19:16:54 +0000533static void brkset(struct brkcon *bc);
534static int dolabel(struct op *t);
535static int dohelp(struct op *t);
536static int dochdir(struct op *t);
537static int doshift(struct op *t);
538static int dologin(struct op *t);
539static int doumask(struct op *t);
540static int doexec(struct op *t);
541static int dodot(struct op *t);
542static int dowait(struct op *t);
543static int doread(struct op *t);
544static int doeval(struct op *t);
545static int dotrap(struct op *t);
546static int getsig(char *s);
547static void setsig(int n, sighandler_t f);
548static int getn(char *as);
549static int dobreak(struct op *t);
550static int docontinue(struct op *t);
551static int brkcontin(char *cp, int val);
552static int doexit(struct op *t);
553static int doexport(struct op *t);
554static int doreadonly(struct op *t);
555static void rdexp(char **wp, void (*f) (struct var *), int key);
556static void badid(char *s);
557static int doset(struct op *t);
558static void varput(char *s, int out);
559static int dotimes(struct op *t);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000560static int expand(const char *cp, struct wdblock **wbp, int f);
Eric Andersen8401eea2004-08-04 19:16:54 +0000561static char *blank(int f);
562static int dollar(int quoted);
563static int grave(int quoted);
564static void globname(char *we, char *pp);
565static char *generate(char *start1, char *end1, char *middle, char *end);
566static int anyspcl(struct wdblock *wb);
567static int xstrcmp(char *p1, char *p2);
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000568static void glob0(char *a0, unsigned a1, int a2,
Eric Andersen8401eea2004-08-04 19:16:54 +0000569 int (*a3) (char *, char *));
Eric Andersen8401eea2004-08-04 19:16:54 +0000570static void readhere(char **name, char *s, int ec);
Eric Andersen8401eea2004-08-04 19:16:54 +0000571static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000572
Eric Andersen8401eea2004-08-04 19:16:54 +0000573struct here {
574 char *h_tag;
575 int h_dosub;
576 struct ioword *h_iop;
577 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000578};
579
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000580static const char *const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000581 "Signal 0",
582 "Hangup",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000583 NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000584 "Quit",
585 "Illegal instruction",
586 "Trace/BPT trap",
587 "Abort",
588 "Bus error",
589 "Floating Point Exception",
590 "Killed",
591 "SIGUSR1",
592 "SIGSEGV",
593 "SIGUSR2",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000594 NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000595 "Alarm clock",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000596 "Terminated"
Eric Andersenff9eee42001-06-29 04:57:14 +0000597};
Eric Andersen8401eea2004-08-04 19:16:54 +0000598
Denis Vlasenko80b8b392007-06-25 10:55:35 +0000599
Eric Andersenff9eee42001-06-29 04:57:14 +0000600struct res {
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000601 const char *r_name;
Eric Andersen8401eea2004-08-04 19:16:54 +0000602 int r_val;
Eric Andersenff9eee42001-06-29 04:57:14 +0000603};
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000604static const struct res restab[] = {
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000605 { "for" , FOR },
606 { "case" , CASE },
607 { "esac" , ESAC },
608 { "while", WHILE },
609 { "do" , DO },
610 { "done" , DONE },
611 { "if" , IF },
612 { "in" , IN },
613 { "then" , THEN },
614 { "else" , ELSE },
615 { "elif" , ELIF },
616 { "until", UNTIL },
617 { "fi" , FI },
618 { ";;" , BREAK },
619 { "||" , LOGOR },
620 { "&&" , LOGAND },
621 { "{" , '{' },
622 { "}" , '}' },
623 { "." , DOT },
624 { NULL , 0 },
Eric Andersenff9eee42001-06-29 04:57:14 +0000625};
626
Eric Andersen1c039232001-07-07 00:05:55 +0000627struct builtincmd {
628 const char *name;
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000629 int (*builtinfunc)(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000630};
Eric Andersen8401eea2004-08-04 19:16:54 +0000631static const struct builtincmd builtincmds[] = {
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000632 { "." , dodot },
633 { ":" , dolabel },
634 { "break" , dobreak },
635 { "cd" , dochdir },
636 { "continue", docontinue },
637 { "eval" , doeval },
638 { "exec" , doexec },
639 { "exit" , doexit },
640 { "export" , doexport },
641 { "help" , dohelp },
642 { "login" , dologin },
643 { "newgrp" , dologin },
644 { "read" , doread },
645 { "readonly", doreadonly },
646 { "set" , doset },
647 { "shift" , doshift },
648 { "times" , dotimes },
649 { "trap" , dotrap },
650 { "umask" , doumask },
651 { "wait" , dowait },
652 { NULL , NULL },
Eric Andersenff9eee42001-06-29 04:57:14 +0000653};
654
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000655static struct op *scantree(struct op *);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000656static struct op *dowholefile(int, int);
657
Eric Andersen12de6cf2004-08-04 19:19:10 +0000658
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000659/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000660static char **dolv;
661static int dolc;
662static int exstat;
663static char gflg;
"Vladimir N. Oleynik"485d7cb2005-10-17 09:48:57 +0000664static int interactive; /* Is this an interactive shell */
Eric Andersen8401eea2004-08-04 19:16:54 +0000665static int execflg;
666static int multiline; /* \n changed to ; */
667static struct op *outtree; /* result from parser */
668static xint *failpt;
669static xint *errpt;
670static struct brkcon *brklist;
671static int isbreak;
672static struct wdblock *wdlist;
673static struct wdblock *iolist;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000674
675#ifdef MSHDEBUG
676static struct var *mshdbg_var;
677#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000678static struct var *vlist; /* dictionary */
679static struct var *homedir; /* home directory */
680static struct var *prompt; /* main prompt */
681static struct var *cprompt; /* continuation prompt */
682static struct var *path; /* search path for commands */
683static struct var *shell; /* shell to interpret command files */
684static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000685
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000686static int areanum; /* current allocation area */
687static int intr; /* interrupt pending */
Eric Andersen8401eea2004-08-04 19:16:54 +0000688static int inparse;
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000689static char *null = (char*)""; /* null value for variable */
690static int heedint = 1; /* heed interrupt signals */
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000691static void (*qflag)(int) = SIG_IGN;
Eric Andersen8401eea2004-08-04 19:16:54 +0000692static int startl;
693static int peeksym;
694static int nlseen;
695static int iounit = IODEFAULT;
696static YYSTYPE yylval;
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000697static char *elinep; /* done in main(): = line + sizeof(line) - 5 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000698
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000699static struct here *inhere; /* list of hear docs while parsing */
700static struct here *acthere; /* list of active here documents */
701static struct region *areabot; /* bottom of area */
702static struct region *areatop; /* top of area */
703static struct region *areanxt; /* starting point of scan */
Eric Andersen8401eea2004-08-04 19:16:54 +0000704static void *brktop;
705static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000706
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000707/*
708 * parsing & execution environment
709 */
710struct env {
711 char *linep;
712 struct io *iobase;
713 struct io *iop;
714 xint *errpt; /* void * */
715 int iofd;
716 struct env *oenv;
717};
718
Eric Andersen12de6cf2004-08-04 19:19:10 +0000719static struct env e = {
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000720 NULL /* set to line in main() */, /* linep: char ptr */
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000721 iostack, /* iobase: struct io ptr */
722 iostack - 1, /* iop: struct io ptr */
723 (xint *) NULL, /* errpt: void ptr for errors? */
724 FDBASE, /* iofd: file desc */
725 (struct env *) NULL /* oenv: struct env ptr */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000726};
727
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000728
729struct globals {
730 char ourtrap[_NSIG + 1];
731 char *trap[_NSIG + 1];
732 struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */
733 struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */
734 struct ioarg ioargstack[NPUSH];
735 char filechar_cmdbuf[BUFSIZ];
736 char line[LINELIM];
737 char child_cmd[LINELIM];
Denis Vlasenkoab801872007-12-02 08:35:37 +0000738
739 char grave__var_name[LINELIM];
740 char grave__alt_value[LINELIM];
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000741};
742
743#define G (*ptr_to_globals)
744#define ourtrap (G.ourtrap )
745#define trap (G.trap )
746#define sharedbuf (G.sharedbuf )
747#define mainbuf (G.mainbuf )
748#define ioargstack (G.ioargstack )
749#define filechar_cmdbuf (G.filechar_cmdbuf)
750#define line (G.line )
751#define child_cmd (G.child_cmd )
Denis Vlasenkoab801872007-12-02 08:35:37 +0000752#define INIT_G() do { \
753 PTR_TO_GLOBALS = xzalloc(sizeof(G)); \
754} while (0)
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000755
756
Eric Andersen12de6cf2004-08-04 19:19:10 +0000757#ifdef MSHDEBUG
758void print_t(struct op *t)
759{
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000760 DBGPRINTF(("T: t=%p, type %s, words=%p, IOword=%p\n", t,
761 T_CMD_NAMES[t->type], t->words, t->ioact));
Eric Andersen12de6cf2004-08-04 19:19:10 +0000762
763 if (t->words) {
764 DBGPRINTF(("T: W1: %s", t->words[0]));
765 }
Eric Andersen12de6cf2004-08-04 19:19:10 +0000766}
767
768void print_tree(struct op *head)
769{
770 if (head == NULL) {
771 DBGPRINTF(("PRINT_TREE: no tree\n"));
772 return;
773 }
774
Mike Frysinger02d8fa42006-05-05 20:32:31 +0000775 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000776 head->right));
777
778 if (head->left)
779 print_tree(head->left);
780
781 if (head->right)
782 print_tree(head->right);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000783}
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000784#endif /* MSHDEBUG */
785
786
787/*
788 * IO functions
789 */
790static void prs(const char *s)
791{
792 if (*s)
793 write(2, s, strlen(s));
794}
795
796static void prn(unsigned u)
797{
798 prs(itoa(u));
799}
800
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000801static void echo(char **wp)
802{
803 int i;
804
805 prs("+");
806 for (i = 0; wp[i]; i++) {
807 if (i)
808 prs(" ");
809 prs(wp[i]);
810 }
811 prs("\n");
812}
813
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000814static void closef(int i)
815{
816 if (i > 2)
817 close(i);
818}
819
820static void closeall(void)
821{
822 int u;
823
824 for (u = NUFILE; u < NOFILE;)
825 close(u++);
826}
Eric Andersen12de6cf2004-08-04 19:19:10 +0000827
Eric Andersenff9eee42001-06-29 04:57:14 +0000828
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000829/* fail but return to process next command */
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000830static void fail(void) ATTRIBUTE_NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000831static void fail(void)
832{
833 longjmp(failpt, 1);
834 /* NOTREACHED */
835}
Eric Andersenff9eee42001-06-29 04:57:14 +0000836
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000837/* abort shell (or fail in subshell) */
838static void leave(void) ATTRIBUTE_NORETURN;
839static void leave(void)
840{
841 DBGPRINTF(("LEAVE: leave called!\n"));
842
843 if (execflg)
844 fail();
845 scraphere();
846 freehere(1);
847 runtrap(0);
848 _exit(exstat);
849 /* NOTREACHED */
850}
851
852static void warn(const char *s)
853{
854 if (*s) {
855 prs(s);
856 exstat = -1;
857 }
858 prs("\n");
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000859 if (FLAG['e'])
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000860 leave();
861}
862
863static void err(const char *s)
864{
865 warn(s);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000866 if (FLAG['n'])
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000867 return;
868 if (!interactive)
869 leave();
870 if (e.errpt)
871 longjmp(e.errpt, 1);
872 closeall();
873 e.iop = e.iobase = iostack;
874}
875
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000876
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000877/* -------- area.c -------- */
878
Eric Andersenff9eee42001-06-29 04:57:14 +0000879/*
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000880 * All memory between (char *)areabot and (char *)(areatop+1) is
881 * exclusively administered by the area management routines.
882 * It is assumed that sbrk() and brk() manipulate the high end.
Eric Andersenff9eee42001-06-29 04:57:14 +0000883 */
884
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000885#define sbrk(X) ({ \
886 void * __q = (void *)-1; \
887 if (brkaddr + (int)(X) < brktop) { \
888 __q = brkaddr; \
889 brkaddr += (int)(X); \
890 } \
891 __q; \
892})
Eric Andersenff9eee42001-06-29 04:57:14 +0000893
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000894static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000895{
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000896 brkaddr = xmalloc(AREASIZE);
897 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +0000898
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000899 while ((long) sbrk(0) & ALIGN)
900 sbrk(1);
901 areabot = (struct region *) sbrk(REGSIZE);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000902
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000903 areabot->next = areabot;
904 areabot->area = BUSY;
905 areatop = areabot;
906 areanxt = areabot;
Eric Andersenff9eee42001-06-29 04:57:14 +0000907}
908
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000909static char *getcell(unsigned nbytes)
910{
911 int nregio;
912 struct region *p, *q;
913 int i;
914
915 if (nbytes == 0) {
916 puts("getcell(0)");
917 abort();
918 }
919 /* silly and defeats the algorithm */
920 /*
921 * round upwards and add administration area
922 */
923 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
924 p = areanxt;
925 for (;;) {
926 if (p->area > areanum) {
927 /*
928 * merge free cells
929 */
930 while ((q = p->next)->area > areanum && q != areanxt)
931 p->next = q->next;
932 /*
933 * exit loop if cell big enough
934 */
935 if (q >= p + nregio)
936 goto found;
937 }
938 p = p->next;
939 if (p == areanxt)
940 break;
941 }
942 i = nregio >= GROWBY ? nregio : GROWBY;
943 p = (struct region *) sbrk(i * REGSIZE);
944 if (p == (struct region *) -1)
945 return NULL;
946 p--;
947 if (p != areatop) {
948 puts("not contig");
949 abort(); /* allocated areas are contiguous */
950 }
951 q = p + i;
952 p->next = q;
953 p->area = FREE;
954 q->next = areabot;
955 q->area = BUSY;
956 areatop = q;
957 found:
958 /*
959 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
960 */
961 areanxt = p + nregio;
962 if (areanxt < q) {
963 /*
964 * split into requested area and rest
965 */
966 if (areanxt + 1 > q) {
967 puts("OOM");
968 abort(); /* insufficient space left for admin */
969 }
970 areanxt->next = q;
971 areanxt->area = FREE;
972 p->next = areanxt;
973 }
974 p->area = areanum;
975 return (char *) (p + 1);
976}
977
978static void freecell(char *cp)
979{
980 struct region *p;
981
982 p = (struct region *) cp;
983 if (p != NULL) {
984 p--;
985 if (p < areanxt)
986 areanxt = p;
987 p->area = FREE;
988 }
989}
990#define DELETE(obj) freecell((char *)obj)
991
992static void freearea(int a)
993{
994 struct region *p, *top;
995
996 top = areatop;
997 for (p = areabot; p != top; p = p->next)
998 if (p->area >= a)
999 p->area = FREE;
1000}
1001
1002static void setarea(char *cp, int a)
1003{
1004 struct region *p;
1005
1006 p = (struct region *) cp;
1007 if (p != NULL)
1008 (p - 1)->area = a;
1009}
1010
1011static int getarea(char *cp)
1012{
1013 return ((struct region *) cp - 1)->area;
1014}
1015
1016static void garbage(void)
1017{
1018 struct region *p, *q, *top;
1019
1020 top = areatop;
1021 for (p = areabot; p != top; p = p->next) {
1022 if (p->area > areanum) {
1023 while ((q = p->next)->area > areanum)
1024 p->next = q->next;
1025 areanxt = p;
1026 }
1027 }
1028#ifdef SHRINKBY
1029 if (areatop >= q + SHRINKBY && q->area > areanum) {
1030 brk((char *) (q + 1));
1031 q->next = areabot;
1032 q->area = BUSY;
1033 areatop = q;
1034 }
1035#endif
1036}
1037
1038static char *space(int n)
1039{
1040 char *cp;
1041
1042 cp = getcell(n);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001043 if (cp == NULL)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001044 err("out of string space");
1045 return cp;
1046}
1047
1048static char *strsave(const char *s, int a)
1049{
1050 char *cp;
1051
1052 cp = space(strlen(s) + 1);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001053 if (cp == NULL) {
1054// FIXME: I highly doubt this is good.
1055 return (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001056 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001057 setarea(cp, a);
1058 strcpy(cp, s);
1059 return cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001060}
1061
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001062
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001063/* -------- var.c -------- */
1064
1065static int eqname(const char *n1, const char *n2)
1066{
1067 for (; *n1 != '=' && *n1 != '\0'; n1++)
1068 if (*n2++ != *n1)
1069 return 0;
1070 return *n2 == '\0' || *n2 == '=';
1071}
1072
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001073static const char *findeq(const char *cp)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001074{
1075 while (*cp != '\0' && *cp != '=')
1076 cp++;
1077 return cp;
1078}
1079
1080/*
1081 * Find the given name in the dictionary
1082 * and return its value. If the name was
1083 * not previously there, enter it now and
1084 * return a null value.
1085 */
1086static struct var *lookup(const char *n)
1087{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001088// FIXME: dirty hack
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001089 static struct var dummy;
1090
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001091 struct var *vp;
1092 const char *cp;
1093 char *xp;
1094 int c;
1095
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001096 if (isdigit(*n)) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001097 dummy.name = (char*)n;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001098 for (c = 0; isdigit(*n) && c < 1000; n++)
1099 c = c * 10 + *n - '0';
1100 dummy.status = RONLY;
1101 dummy.value = (c <= dolc ? dolv[c] : null);
1102 return &dummy;
1103 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001104
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001105 for (vp = vlist; vp; vp = vp->next)
1106 if (eqname(vp->name, n))
1107 return vp;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001108
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001109 cp = findeq(n);
1110 vp = (struct var *) space(sizeof(*vp));
1111 if (vp == 0 || (vp->name = space((int) (cp - n) + 2)) == 0) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001112 dummy.name = dummy.value = (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001113 return &dummy;
1114 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001115
1116 xp = vp->name;
1117 while ((*xp = *n++) != '\0' && *xp != '=')
1118 xp++;
1119 *xp++ = '=';
1120 *xp = '\0';
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001121 setarea((char *) vp, 0);
1122 setarea((char *) vp->name, 0);
1123 vp->value = null;
1124 vp->next = vlist;
1125 vp->status = GETCELL;
1126 vlist = vp;
1127 return vp;
1128}
1129
1130/*
1131 * if name is not NULL, it must be
1132 * a prefix of the space `val',
1133 * and end with `='.
1134 * this is all so that exporting
1135 * values is reasonably painless.
1136 */
1137static void nameval(struct var *vp, const char *val, const char *name)
1138{
1139 const char *cp;
1140 char *xp;
1141 int fl;
1142
1143 if (vp->status & RONLY) {
1144 xp = vp->name;
1145 while (*xp && *xp != '=')
Denis Vlasenko4daad902007-09-27 10:20:47 +00001146 fputc(*xp++, stderr);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001147 err(" is read-only");
1148 return;
1149 }
1150 fl = 0;
1151 if (name == NULL) {
1152 xp = space(strlen(vp->name) + strlen(val) + 2);
1153 if (xp == NULL)
1154 return;
1155 /* make string: name=value */
1156 setarea(xp, 0);
1157 name = xp;
1158 cp = vp->name;
1159 while ((*xp = *cp++) != '\0' && *xp != '=')
1160 xp++;
1161 *xp++ = '=';
1162 strcpy(xp, val);
1163 val = xp;
1164 fl = GETCELL;
1165 }
1166 if (vp->status & GETCELL)
1167 freecell(vp->name); /* form new string `name=value' */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001168 vp->name = (char*)name;
1169 vp->value = (char*)val;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001170 vp->status |= fl;
1171}
1172
1173/*
1174 * give variable at `vp' the value `val'.
1175 */
1176static void setval(struct var *vp, const char *val)
1177{
1178 nameval(vp, val, NULL);
1179}
1180
1181static void export(struct var *vp)
1182{
1183 vp->status |= EXPORT;
1184}
1185
1186static void ronly(struct var *vp)
1187{
1188 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1189 vp->status |= RONLY;
1190}
1191
1192static int isassign(const char *s)
1193{
1194 unsigned char c;
1195 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1196
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001197 c = *s;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001198 /* no isalpha() - we shouldn't use locale */
1199 /* c | 0x20 - lowercase (Latin) letters */
1200 if (c != '_' && (unsigned)((c|0x20) - 'a') > 25)
1201 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001202 return 0;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001203
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001204 while (1) {
1205 c = *++s;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001206 if (c == '=')
1207 return 1;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001208 if (c == '\0')
1209 return 0;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001210 if (c != '_'
1211 && (unsigned)(c - '0') > 9 /* not number */
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001212 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001213 ) {
1214 return 0;
1215 }
1216 }
1217}
1218
1219static int assign(const char *s, int cf)
1220{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001221 const char *cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001222 struct var *vp;
1223
1224 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1225
1226 if (!isalpha(*s) && *s != '_')
1227 return 0;
1228 for (cp = s; *cp != '='; cp++)
1229 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
1230 return 0;
1231 vp = lookup(s);
1232 nameval(vp, ++cp, cf == COPYV ? NULL : s);
1233 if (cf != COPYV)
1234 vp->status &= ~GETCELL;
1235 return 1;
1236}
1237
1238static int checkname(char *cp)
1239{
1240 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1241
1242 if (!isalpha(*cp++) && *(cp - 1) != '_')
1243 return 0;
1244 while (*cp)
1245 if (!isalnum(*cp++) && *(cp - 1) != '_')
1246 return 0;
1247 return 1;
1248}
1249
1250static void putvlist(int f, int out)
1251{
1252 struct var *vp;
1253
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001254 for (vp = vlist; vp; vp = vp->next) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001255 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1256 if (vp->status & EXPORT)
1257 write(out, "export ", 7);
1258 if (vp->status & RONLY)
1259 write(out, "readonly ", 9);
1260 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
1261 write(out, "\n", 1);
1262 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001263 }
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001264}
1265
1266
1267/*
1268 * trap handling
1269 */
1270static void sig(int i)
1271{
1272 trapset = i;
1273 signal(i, sig);
1274}
1275
1276static void runtrap(int i)
1277{
1278 char *trapstr;
1279
1280 trapstr = trap[i];
1281 if (trapstr == NULL)
1282 return;
1283
1284 if (i == 0)
1285 trap[i] = NULL;
1286
1287 RUN(aword, trapstr, nlchar);
1288}
1289
1290
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001291static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001292{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001293 char *cp;
1294 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001295 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001296
1297 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001298 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00001299 if (FLAG[c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001300 *cp++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001301 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001302 setval(lookup("-"), m);
1303}
1304
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001305static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001306{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001307 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001308
1309 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001310
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001311 f = 0;
Denis Vlasenko9f739442006-12-16 23:49:13 +00001312 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001313 DBGPRINTF(("NEWFILE: s is %s\n", s));
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00001314 f = open(s, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00001315 if (f < 0) {
1316 prs(s);
1317 err(": cannot open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001318 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001319 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001320 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001321
Eric Andersenff9eee42001-06-29 04:57:14 +00001322 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001323 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001324}
1325
Eric Andersen12de6cf2004-08-04 19:19:10 +00001326
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001327struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001328{
1329 struct op *dotnode;
1330
1331 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001332 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001333
1334 if (head->left != NULL) {
1335 dotnode = scantree(head->left);
1336 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001337 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001338 }
1339
1340 if (head->right != NULL) {
1341 dotnode = scantree(head->right);
1342 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001343 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001344 }
1345
1346 if (head->words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001347 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001348
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001349 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001350
Denis Vlasenkocf787cf2007-02-04 17:11:25 +00001351 if ((head->type != TDOT) && LONE_CHAR(head->words[0], '.')) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001352 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001353 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001354 }
1355
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001356 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001357}
1358
1359
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001360static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001361{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001362 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001363 jmp_buf m1;
1364
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001365 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001366
Eric Andersenff9eee42001-06-29 04:57:14 +00001367 while (e.oenv)
1368 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001369
Eric Andersenff9eee42001-06-29 04:57:14 +00001370 areanum = 1;
1371 freehere(areanum);
1372 freearea(areanum);
1373 garbage();
1374 wdlist = 0;
1375 iolist = 0;
1376 e.errpt = 0;
1377 e.linep = line;
1378 yynerrs = 0;
1379 multiline = 0;
1380 inparse = 1;
1381 intr = 0;
1382 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001383
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001384 failpt = m1;
1385 setjmp(failpt); /* Bruce Evans' fix */
1386 failpt = m1;
1387 if (setjmp(failpt) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001388 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1389
Eric Andersenff9eee42001-06-29 04:57:14 +00001390 while (e.oenv)
1391 quitenv();
1392 scraphere();
1393 if (!interactive && intr)
1394 leave();
1395 inparse = 0;
1396 intr = 0;
1397 return;
1398 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001399
Eric Andersenff9eee42001-06-29 04:57:14 +00001400 inparse = 0;
1401 brklist = 0;
1402 intr = 0;
1403 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001404
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00001405 if (!FLAG['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001406 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001407 outtree));
Eric Andersenff9eee42001-06-29 04:57:14 +00001408 execute(outtree, NOPIPE, NOPIPE, 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001409 }
1410
Eric Andersenff9eee42001-06-29 04:57:14 +00001411 if (!interactive && intr) {
1412 execflg = 0;
1413 leave();
1414 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001415
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001416 i = trapset;
1417 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001418 trapset = 0;
1419 runtrap(i);
1420 }
1421}
1422
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001423static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001424{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001425 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001426
1427 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001428
1429 if (f) {
1430 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001431 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001432 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001433
Eric Andersenff9eee42001-06-29 04:57:14 +00001434 ep = (struct env *) space(sizeof(*ep));
1435 if (ep == NULL) {
1436 while (e.oenv)
1437 quitenv();
1438 fail();
1439 }
1440 *ep = e;
1441 e.oenv = ep;
1442 e.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001443
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001444 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001445}
1446
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001447static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001448{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001449 struct env *ep;
1450 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001451
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001452 DBGPRINTF(("QUITENV: e.oenv=%p\n", e.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001453
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001454 ep = e.oenv;
1455 if (ep != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001456 fd = e.iofd;
1457 e = *ep;
1458 /* should close `'d files */
1459 DELETE(ep);
1460 while (--fd >= e.iofd)
1461 close(fd);
1462 }
1463}
1464
1465/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001466 * Is character c in s?
Eric Andersenff9eee42001-06-29 04:57:14 +00001467 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001468static int any(int c, const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001469{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001470 while (*s)
1471 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001472 return 1;
1473 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001474}
1475
1476/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001477 * Is any character from s1 in s2?
Eric Andersenff9eee42001-06-29 04:57:14 +00001478 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001479static int anys(const char *s1, const char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001480{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001481 while (*s1)
1482 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001483 return 1;
1484 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001485}
1486
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001487static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001488{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001489 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001490}
1491
Eric Andersen8401eea2004-08-04 19:16:54 +00001492static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001493{
1494 PUSHIO(afile, f, filechar);
1495}
1496
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001497static void onintr(int s) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001498{
1499 signal(SIGINT, onintr);
1500 intr = 1;
1501 if (interactive) {
1502 if (inparse) {
1503 prs("\n");
1504 fail();
1505 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001506 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001507 execflg = 0;
1508 leave();
1509 }
1510}
1511
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001512
Eric Andersenff9eee42001-06-29 04:57:14 +00001513/* -------- gmatch.c -------- */
1514/*
1515 * int gmatch(string, pattern)
1516 * char *string, *pattern;
1517 *
1518 * Match a pattern as in sh(1).
1519 */
1520
1521#define CMASK 0377
1522#define QUOTE 0200
Denis Vlasenko55f30b02007-03-24 22:42:29 +00001523#define QMASK (CMASK & ~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001524#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001525
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001526static const char *cclass(const char *p, int sub)
1527{
1528 int c, d, not, found;
1529
1530 not = (*p == NOT);
1531 if (not != 0)
1532 p++;
1533 found = not;
1534 do {
1535 if (*p == '\0')
1536 return NULL;
1537 c = *p & CMASK;
1538 if (p[1] == '-' && p[2] != ']') {
1539 d = p[2] & CMASK;
1540 p++;
1541 } else
1542 d = c;
1543 if (c == sub || (c <= sub && sub <= d))
1544 found = !not;
1545 } while (*++p != ']');
1546 return found ? p + 1 : NULL;
1547}
1548
1549static int gmatch(const char *s, const char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001550{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001551 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001552
1553 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001554 return 0;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001555
Eric Andersenff9eee42001-06-29 04:57:14 +00001556 while ((pc = *p++ & CMASK) != '\0') {
1557 sc = *s++ & QMASK;
1558 switch (pc) {
1559 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001560 p = cclass(p, sc);
1561 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001562 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001563 break;
1564
1565 case '?':
1566 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001567 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001568 break;
1569
1570 case '*':
1571 s--;
1572 do {
1573 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001574 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001575 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001576 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001577
1578 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001579 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001580 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001581 }
1582 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001583 return *s == '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001584}
1585
Eric Andersenff9eee42001-06-29 04:57:14 +00001586
Eric Andersenff9eee42001-06-29 04:57:14 +00001587/* -------- csyn.c -------- */
1588/*
1589 * shell: syntax (C version)
1590 */
1591
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001592static void yyerror(const char *s) ATTRIBUTE_NORETURN;
1593static void yyerror(const char *s)
1594{
1595 yynerrs++;
1596 if (interactive && e.iop <= iostack) {
1597 multiline = 0;
1598 while (eofc() == 0 && yylex(0) != '\n');
1599 }
1600 err(s);
1601 fail();
1602}
1603
1604static void zzerr(void) ATTRIBUTE_NORETURN;
1605static void zzerr(void)
1606{
1607 yyerror("syntax error");
1608}
1609
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001610int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001611{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001612 DBGPRINTF7(("YYPARSE: enter...\n"));
1613
Eric Andersen8401eea2004-08-04 19:16:54 +00001614 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001615 peeksym = 0;
1616 yynerrs = 0;
1617 outtree = c_list();
1618 musthave('\n', 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00001619 return (yynerrs != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00001620}
1621
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001622static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001623{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001624 struct op *t, *p;
1625 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001626
1627 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001628
1629 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001630
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001631 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001632
Eric Andersenff9eee42001-06-29 04:57:14 +00001633 if (t != NULL) {
1634 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001635 p = command(CONTIN);
1636 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001637 DBGPRINTF8(("PIPELINE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001638 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001639 }
1640
Eric Andersenff9eee42001-06-29 04:57:14 +00001641 if (t->type != TPAREN && t->type != TCOM) {
1642 /* shell statement */
1643 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1644 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001645
Eric Andersenff9eee42001-06-29 04:57:14 +00001646 t = block(TPIPE, t, p, NOWORDS);
1647 }
1648 peeksym = c;
1649 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001650
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001651 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001652 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001653}
1654
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001655static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001656{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001657 struct op *t, *p;
1658 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001659
1660 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001661
1662 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001663
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001664 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001665
Eric Andersenff9eee42001-06-29 04:57:14 +00001666 if (t != NULL) {
1667 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001668 p = pipeline(CONTIN);
1669 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001670 DBGPRINTF8(("ANDOR: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001671 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001672 }
1673
Eric Andersen8401eea2004-08-04 19:16:54 +00001674 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001675 } /* WHILE */
1676
Eric Andersenff9eee42001-06-29 04:57:14 +00001677 peeksym = c;
1678 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001679
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001680 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001681 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001682}
1683
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001684static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001685{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001686 struct op *t, *p;
1687 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001688
1689 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001690
1691 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001692
Eric Andersenff9eee42001-06-29 04:57:14 +00001693 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001694 peeksym = yylex(0);
1695 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001696 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001697
Eric Andersen8401eea2004-08-04 19:16:54 +00001698 while ((c = yylex(0)) == ';' || c == '&'
1699 || (multiline && c == '\n')) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001700
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001701 p = andor();
1702 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001703 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001704
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001705 peeksym = yylex(0);
1706 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001707 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001708
Eric Andersenff9eee42001-06-29 04:57:14 +00001709 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001710 } /* WHILE */
1711
Eric Andersenff9eee42001-06-29 04:57:14 +00001712 peeksym = c;
1713 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001714 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001715 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001716 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001717}
1718
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001719static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001720{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001721 struct ioword *iop;
1722 int i;
1723 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001724
1725 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001726
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001727 c = yylex(cf);
1728 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001729 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001730 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001731 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001732
Eric Andersenff9eee42001-06-29 04:57:14 +00001733 i = yylval.i;
1734 musthave(WORD, 0);
1735 iop = io(iounit, i, yylval.cp);
1736 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001737
Eric Andersenff9eee42001-06-29 04:57:14 +00001738 if (i & IOHERE)
1739 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001740
1741 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001742 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001743}
1744
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001745static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001746{
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001747 peeksym = yylex(cf);
1748 if (peeksym != c) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001749 DBGPRINTF7(("MUSTHAVE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001750 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001751 }
1752
Eric Andersenff9eee42001-06-29 04:57:14 +00001753 peeksym = 0;
1754}
1755
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001756static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001757{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001758 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001759
1760 t = NULL;
1761 for (;;) {
1762 switch (peeksym = yylex(0)) {
1763 case '<':
1764 case '>':
1765 (void) synio(0);
1766 break;
1767
1768 case WORD:
1769 if (t == NULL) {
1770 t = newtp();
1771 t->type = TCOM;
1772 }
1773 peeksym = 0;
1774 word(yylval.cp);
1775 break;
1776
1777 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001778 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001779 }
1780 }
1781}
1782
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001783static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001784{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001785 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001786
1787 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001788
1789 multiline++;
1790 t = c_list();
1791 musthave(mark, 0);
1792 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001793 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001794}
1795
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001796static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001797{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001798 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001799 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001800 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001801
1802 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001803
1804 iosave = iolist;
1805 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001806
Eric Andersenff9eee42001-06-29 04:57:14 +00001807 if (multiline)
1808 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001809
Eric Andersenff9eee42001-06-29 04:57:14 +00001810 while (synio(cf))
1811 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001812
1813 c = yylex(cf);
1814
1815 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001816 default:
1817 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001818 t = simple();
1819 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001820 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001821 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001822 t = newtp();
1823 t->type = TCOM;
1824 }
1825 break;
1826
1827 case '(':
1828 t = nested(TPAREN, ')');
1829 break;
1830
1831 case '{':
1832 t = nested(TBRACE, '}');
1833 break;
1834
1835 case FOR:
1836 t = newtp();
1837 t->type = TFOR;
1838 musthave(WORD, 0);
1839 startl = 1;
1840 t->str = yylval.cp;
1841 multiline++;
1842 t->words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001843 c = yylex(0);
1844 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001845 peeksym = c;
1846 t->left = dogroup(0);
1847 multiline--;
1848 break;
1849
1850 case WHILE:
1851 case UNTIL:
1852 multiline++;
1853 t = newtp();
Eric Andersen8401eea2004-08-04 19:16:54 +00001854 t->type = c == WHILE ? TWHILE : TUNTIL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001855 t->left = c_list();
1856 t->right = dogroup(1);
1857 t->words = NULL;
1858 multiline--;
1859 break;
1860
1861 case CASE:
1862 t = newtp();
1863 t->type = TCASE;
1864 musthave(WORD, 0);
1865 t->str = yylval.cp;
1866 startl++;
1867 multiline++;
1868 musthave(IN, CONTIN);
1869 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001870
Eric Andersenff9eee42001-06-29 04:57:14 +00001871 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001872
Eric Andersenff9eee42001-06-29 04:57:14 +00001873 musthave(ESAC, 0);
1874 multiline--;
1875 break;
1876
1877 case IF:
1878 multiline++;
1879 t = newtp();
1880 t->type = TIF;
1881 t->left = c_list();
1882 t->right = thenpart();
1883 musthave(FI, 0);
1884 multiline--;
1885 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001886
1887 case DOT:
1888 t = newtp();
1889 t->type = TDOT;
1890
1891 musthave(WORD, 0); /* gets name of file */
1892 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1893
1894 word(yylval.cp); /* add word to wdlist */
1895 word(NOWORD); /* terminate wdlist */
1896 t->words = copyw(); /* dup wdlist */
1897 break;
1898
Eric Andersenff9eee42001-06-29 04:57:14 +00001899 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001900
Eric Andersen8401eea2004-08-04 19:16:54 +00001901 while (synio(0));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001902
Eric Andersenff9eee42001-06-29 04:57:14 +00001903 t = namelist(t);
1904 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001905
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001906 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001907
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001908 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001909}
1910
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001911static struct op *dowholefile(int type, int mark)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001912{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001913 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001914
1915 DBGPRINTF(("DOWHOLEFILE: enter, type=%d, mark=%d\n", type, mark));
1916
1917 multiline++;
1918 t = c_list();
1919 multiline--;
1920 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001921 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001922 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001923}
1924
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001925static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00001926{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001927 int c;
1928 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001929
1930 c = yylex(CONTIN);
1931 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001932 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001933 if (c != DO)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001934 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001935 mylist = c_list();
1936 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001937 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001938}
1939
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001940static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001941{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001942 int c;
1943 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001944
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001945 c = yylex(0);
1946 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001947 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001948 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001949 }
1950 t = newtp();
1951 t->type = 0;
1952 t->left = c_list();
1953 if (t->left == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001954 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001955 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001956 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001957}
1958
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001959static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001960{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001961 int c;
1962 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001963
1964 switch (c = yylex(0)) {
1965 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001966 t = c_list();
1967 if (t == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001968 zzerr();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001969 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001970
1971 case ELIF:
1972 t = newtp();
1973 t->type = TELIF;
1974 t->left = c_list();
1975 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001976 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001977
1978 default:
1979 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001980 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001981 }
1982}
1983
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001984static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001985{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001986 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001987
1988 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001989 while ((peeksym = yylex(CONTIN)) != ESAC) {
1990 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00001991 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00001992 }
1993
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001994 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001995 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001996}
1997
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001998static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001999{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002000 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002001
2002 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002003
2004 t = newtp();
2005 t->type = TPAT;
2006 t->words = pattern();
2007 musthave(')', 0);
2008 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002009 peeksym = yylex(CONTIN);
2010 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00002011 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002012
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002013 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002014
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002015 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002016}
2017
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002018static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002019{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002020 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00002021
2022 cf = CONTIN;
2023 do {
2024 musthave(WORD, cf);
2025 word(yylval.cp);
2026 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002027 c = yylex(0);
2028 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00002029 peeksym = c;
2030 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002031
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002032 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002033}
2034
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002035static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002036{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002037 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002038
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002039 c = yylex(0);
2040 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002041 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002042 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002043 }
2044 startl = 0;
2045 while ((c = yylex(0)) == WORD)
2046 word(yylval.cp);
2047 word(NOWORD);
2048 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002049 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002050}
2051
2052/*
2053 * supporting functions
2054 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002055static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00002056{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002057 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002058
Eric Andersenff9eee42001-06-29 04:57:14 +00002059 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002060 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002061 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002062 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002063
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002064 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00002065}
2066
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002067static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002068{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002069 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002070
2071 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002072
2073 t = newtp();
2074 t->type = type;
2075 t->left = t1;
2076 t->right = t2;
2077 t->words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002078
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002079 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002080 t2));
2081
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002082 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002083}
2084
Eric Andersen12de6cf2004-08-04 19:19:10 +00002085/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002086static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002087{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002088 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002089
2090 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002091
2092 for (rp = restab; rp->r_name; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002093 if (strcmp(rp->r_name, n) == 0) {
2094 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002095 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002096 }
2097
2098 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002099 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002100}
2101
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002102static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002103{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002104 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002105
Eric Andersen8401eea2004-08-04 19:16:54 +00002106 t = (struct op *) tree(sizeof(*t));
Eric Andersenff9eee42001-06-29 04:57:14 +00002107 t->type = 0;
2108 t->words = NULL;
2109 t->ioact = NULL;
2110 t->left = NULL;
2111 t->right = NULL;
2112 t->str = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002113
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002114 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002115
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002116 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002117}
2118
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002119static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002120{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002121 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002122 T_CMD_NAMES[t->type], iolist));
2123
Eric Andersenff9eee42001-06-29 04:57:14 +00002124 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002125 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002126 t->ioact = copyio();
2127 } else
2128 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002129
Eric Andersenff9eee42001-06-29 04:57:14 +00002130 if (t->type != TCOM) {
2131 if (t->type != TPAREN && t->ioact != NULL) {
2132 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2133 t->ioact = t->left->ioact;
2134 t->left->ioact = NULL;
2135 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002136 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002137 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002138
Eric Andersenff9eee42001-06-29 04:57:14 +00002139 word(NOWORD);
2140 t->words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002141
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002142 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002143}
2144
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002145static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002146{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002147 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002148
2149 wd = getwords(wdlist);
2150 wdlist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002151 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002152}
2153
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002154static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002155{
2156 wdlist = addword(cp, wdlist);
2157}
2158
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002159static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002160{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002161 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002162
2163 iop = (struct ioword **) getwords(iolist);
2164 iolist = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002165 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002166}
2167
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002168static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002169{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002170 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002171
2172 iop = (struct ioword *) tree(sizeof(*iop));
2173 iop->io_unit = u;
2174 iop->io_flag = f;
2175 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002176 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002177 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002178}
2179
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002180static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002181{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002182 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002183 int atstart;
2184
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002185 c = peeksym;
2186 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002187 peeksym = 0;
2188 if (c == '\n')
2189 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002190 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002191 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002192
Eric Andersenff9eee42001-06-29 04:57:14 +00002193 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002194 atstart = startl;
2195 startl = 0;
2196 yylval.i = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002197 e.linep = line;
2198
2199/* MALAMO */
2200 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002201
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002202 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002203 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
2204 ;
2205
Eric Andersenff9eee42001-06-29 04:57:14 +00002206 switch (c) {
2207 default:
2208 if (any(c, "0123456789")) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002209 c1 = my_getc(0);
2210 unget(c1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002211 if (c1 == '<' || c1 == '>') {
2212 iounit = c - '0';
2213 goto loop;
2214 }
2215 *e.linep++ = c;
2216 c = c1;
2217 }
2218 break;
2219
Eric Andersen12de6cf2004-08-04 19:19:10 +00002220 case '#': /* Comment, skip to next newline or End-of-string */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002221 while ((c = my_getc(0)) != '\0' && c != '\n');
Eric Andersenff9eee42001-06-29 04:57:14 +00002222 unget(c);
2223 goto loop;
2224
2225 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002226 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002227 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002228
2229 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002230 DBGPRINTF9(("YYLEX: found $\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00002231 *e.linep++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002232 c = my_getc(0);
2233 if (c == '{') {
2234 c = collect(c, '}');
2235 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002236 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002237 goto pack;
2238 }
2239 break;
2240
2241 case '`':
2242 case '\'':
2243 case '"':
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002244 c = collect(c, c);
2245 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002246 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002247 goto pack;
2248
2249 case '|':
2250 case '&':
2251 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002252 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002253 /* If more chars process them, else return NULL char */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002254 c1 = dual(c);
2255 if (c1 != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002256 return c1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002257 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002258
Eric Andersenff9eee42001-06-29 04:57:14 +00002259 case '^':
2260 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002261 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002262 case '>':
2263 case '<':
2264 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002265 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002266
2267 case '\n':
2268 nlseen++;
2269 gethere();
2270 startl = 1;
2271 if (multiline || cf & CONTIN) {
2272 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002273#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002274 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002275#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002276 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002277#endif
2278 }
2279 if (cf & CONTIN)
2280 goto loop;
2281 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002282 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002283
2284 case '(':
2285 case ')':
2286 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002287 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002288 }
2289
2290 unget(c);
2291
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002292 pack:
2293 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002294 if (e.linep >= elinep)
2295 err("word too long");
2296 else
2297 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002298 };
2299
Eric Andersenff9eee42001-06-29 04:57:14 +00002300 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002301
Eric Andersen8401eea2004-08-04 19:16:54 +00002302 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002303 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002304
Eric Andersenff9eee42001-06-29 04:57:14 +00002305 *e.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002306
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002307 if (atstart) {
2308 c = rlookup(line);
2309 if (c != 0) {
2310 startl = 1;
2311 return c;
2312 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002313 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002314
Eric Andersenff9eee42001-06-29 04:57:14 +00002315 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002316 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002317}
2318
Eric Andersen12de6cf2004-08-04 19:19:10 +00002319
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002320static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002321{
2322 char s[2];
2323
Eric Andersen12de6cf2004-08-04 19:19:10 +00002324 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2325
Eric Andersenff9eee42001-06-29 04:57:14 +00002326 *e.linep++ = c;
2327 while ((c = my_getc(c1)) != c1) {
2328 if (c == 0) {
2329 unget(c);
2330 s[0] = c1;
2331 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002332 prs("no closing ");
2333 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002334 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002335 }
2336 if (interactive && c == '\n' && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002337#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002338 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002339#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002340 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002341#endif
2342 }
2343 *e.linep++ = c;
2344 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002345
Eric Andersenff9eee42001-06-29 04:57:14 +00002346 *e.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002347
2348 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2349
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002350 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002351}
2352
Eric Andersen12de6cf2004-08-04 19:19:10 +00002353/* "multiline commands" helper func */
2354/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002355static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002356{
2357 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002358 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002359
Eric Andersen12de6cf2004-08-04 19:19:10 +00002360 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2361
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002362 *cp++ = c; /* c is the given "peek" char */
2363 *cp++ = my_getc(0); /* get next char of input */
2364 *cp = '\0'; /* add EOS marker */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002365
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002366 c = rlookup(s); /* see if 2 chars form a shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002367 if (c == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002368 unget(*--cp); /* String is not a shell multiline, put peek char back */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002369
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002370 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002371}
2372
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002373static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002374{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002375 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002376
2377 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002378
2379 c = my_getc(0);
2380 if (c == '>' || c == '<') {
2381 if (c != ec)
2382 zzerr();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002383 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002384 c = my_getc(0);
2385 } else
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002386 yylval.i = (ec == '>' ? IOWRITE : IOREAD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002387 if (c != '&' || yylval.i == IOHERE)
2388 unget(c);
2389 else
2390 yylval.i |= IODUP;
2391}
2392
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002393static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002394{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002395 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002396
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002397 t = getcell(size);
2398 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002399 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002400 prs("command line too complicated\n");
2401 fail();
2402 /* NOTREACHED */
2403 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002404 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002405}
2406
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002407
Eric Andersenff9eee42001-06-29 04:57:14 +00002408/* VARARGS1 */
2409/* ARGSUSED */
2410
2411/* -------- exec.c -------- */
2412
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002413static struct op **find1case(struct op *t, const char *w)
2414{
2415 struct op *t1;
2416 struct op **tp;
2417 char **wp;
2418 char *cp;
2419
2420 if (t == NULL) {
2421 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
2422 return NULL;
2423 }
2424
2425 DBGPRINTF3(("FIND1CASE: enter, t->type=%d (%s)\n", t->type,
2426 T_CMD_NAMES[t->type]));
2427
2428 if (t->type == TLIST) {
2429 tp = find1case(t->left, w);
2430 if (tp != NULL) {
2431 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
2432 return tp;
2433 }
2434 t1 = t->right; /* TPAT */
2435 } else
2436 t1 = t;
2437
2438 for (wp = t1->words; *wp;) {
2439 cp = evalstr(*wp++, DOSUB);
2440 if (cp && gmatch(w, cp)) {
2441 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
2442 &t1->left));
2443 return &t1->left;
2444 }
2445 }
2446
2447 DBGPRINTF(("FIND1CASE: returning NULL\n"));
2448 return NULL;
2449}
2450
2451static struct op *findcase(struct op *t, const char *w)
2452{
2453 struct op **tp;
2454
2455 tp = find1case(t, w);
2456 return tp != NULL ? *tp : NULL;
2457}
2458
Eric Andersenff9eee42001-06-29 04:57:14 +00002459/*
2460 * execute tree
2461 */
2462
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002463static int execute(struct op *t, int *pin, int *pout, int act)
Eric Andersenff9eee42001-06-29 04:57:14 +00002464{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002465 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002466 volatile int i, rv, a;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002467 const char *cp;
2468 char **wp, **wp2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002469 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002470 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002471 struct brkcon bc;
2472
2473#if __GNUC__
2474 /* Avoid longjmp clobbering */
2475 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002476#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002477
Eric Andersen12de6cf2004-08-04 19:19:10 +00002478 if (t == NULL) {
2479 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002480 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002481 }
2482
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002483 DBGPRINTF(("EXECUTE: t=%p, t->type=%d (%s), t->words is %s\n", t,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002484 t->type, T_CMD_NAMES[t->type],
2485 ((t->words == NULL) ? "NULL" : t->words[0])));
2486
Eric Andersenff9eee42001-06-29 04:57:14 +00002487 rv = 0;
2488 a = areanum++;
2489 wp = (wp2 = t->words) != NULL
Eric Andersen8401eea2004-08-04 19:16:54 +00002490 ? eval(wp2, t->type == TCOM ? DOALL : DOALL & ~DOKEY)
2491 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002492
Eric Andersen8401eea2004-08-04 19:16:54 +00002493 switch (t->type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002494 case TDOT:
2495 DBGPRINTF3(("EXECUTE: TDOT\n"));
2496
2497 outtree_save = outtree;
2498
2499 newfile(evalstr(t->words[0], DOALL));
2500
2501 t->left = dowholefile(TLIST, 0);
2502 t->right = NULL;
2503
2504 outtree = outtree_save;
2505
2506 if (t->left)
2507 rv = execute(t->left, pin, pout, 0);
2508 if (t->right)
2509 rv = execute(t->right, pin, pout, 0);
2510 break;
2511
Eric Andersenff9eee42001-06-29 04:57:14 +00002512 case TPAREN:
Eric Andersen737f5fb2003-03-14 16:05:59 +00002513 rv = execute(t->left, pin, pout, 0);
2514 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002515
Eric Andersenff9eee42001-06-29 04:57:14 +00002516 case TCOM:
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002517 rv = forkexec(t, pin, pout, act, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002518 break;
2519
2520 case TPIPE:
2521 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002522 int pv[2];
2523
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002524 rv = openpipe(pv);
2525 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002526 break;
2527 pv[0] = remap(pv[0]);
2528 pv[1] = remap(pv[1]);
2529 (void) execute(t->left, pin, pv, 0);
2530 rv = execute(t->right, pv, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002531 }
2532 break;
2533
2534 case TLIST:
2535 (void) execute(t->left, pin, pout, 0);
2536 rv = execute(t->right, pin, pout, 0);
2537 break;
2538
2539 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002540 {
2541 int hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002542
Eric Andersen12de6cf2004-08-04 19:19:10 +00002543 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2544
Eric Andersen8401eea2004-08-04 19:16:54 +00002545 i = vfork();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002546 if (i == 0) { /* child */
Eric Andersen8401eea2004-08-04 19:16:54 +00002547 signal(SIGINT, SIG_IGN);
2548 signal(SIGQUIT, SIG_IGN);
2549 if (interactive)
2550 signal(SIGTERM, SIG_DFL);
2551 interactive = 0;
2552 if (pin == NULL) {
2553 close(0);
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002554 xopen(bb_dev_null, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00002555 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002556 _exit(execute(t->left, pin, pout, FEXEC));
Eric Andersenff9eee42001-06-29 04:57:14 +00002557 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002558 interactive = hinteractive;
2559 if (i != -1) {
2560 setval(lookup("!"), putn(i));
2561 if (pin != NULL)
2562 closepipe(pin);
2563 if (interactive) {
2564 prs(putn(i));
2565 prs("\n");
2566 }
2567 } else
2568 rv = -1;
2569 setstatus(rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002570 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002571 break;
2572
2573 case TOR:
2574 case TAND:
2575 rv = execute(t->left, pin, pout, 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002576 t1 = t->right;
2577 if (t1 != NULL && (rv == 0) == (t->type == TAND))
Eric Andersenff9eee42001-06-29 04:57:14 +00002578 rv = execute(t1, pin, pout, 0);
2579 break;
2580
2581 case TFOR:
2582 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002583 wp = dolv + 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002584 i = dolc;
2585 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002586 i = 0;
2587 } else {
2588 i = -1;
Eric Andersen8401eea2004-08-04 19:16:54 +00002589 while (*wp++ != NULL);
Eric Andersenff9eee42001-06-29 04:57:14 +00002590 }
2591 vp = lookup(t->str);
2592 while (setjmp(bc.brkpt))
2593 if (isbreak)
2594 goto broken;
2595 brkset(&bc);
2596 for (t1 = t->left; i-- && *wp != NULL;) {
2597 setval(vp, *wp++);
2598 rv = execute(t1, pin, pout, 0);
2599 }
2600 brklist = brklist->nextlev;
2601 break;
2602
2603 case TWHILE:
2604 case TUNTIL:
2605 while (setjmp(bc.brkpt))
2606 if (isbreak)
2607 goto broken;
2608 brkset(&bc);
2609 t1 = t->left;
2610 while ((execute(t1, pin, pout, 0) == 0) == (t->type == TWHILE))
2611 rv = execute(t->right, pin, pout, 0);
2612 brklist = brklist->nextlev;
2613 break;
2614
2615 case TIF:
2616 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002617 if (t->right != NULL) {
2618 rv = !execute(t->left, pin, pout, 0) ?
2619 execute(t->right->left, pin, pout, 0) :
2620 execute(t->right->right, pin, pout, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002621 }
2622 break;
2623
2624 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002625 cp = evalstr(t->str, DOSUB | DOTRIM);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002626 if (cp == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002627 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002628
2629 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2630 ((t->str == NULL) ? "NULL" : t->str),
2631 ((cp == NULL) ? "NULL" : cp)));
2632
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002633 t1 = findcase(t->left, cp);
2634 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002635 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002636 rv = execute(t1, pin, pout, 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002637 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002638 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002639 break;
2640
2641 case TBRACE:
2642/*
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002643 iopp = t->ioact;
2644 if (i)
Eric Andersenff9eee42001-06-29 04:57:14 +00002645 while (*iopp)
2646 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2647 rv = -1;
2648 break;
2649 }
2650*/
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002651 if (rv >= 0) {
2652 t1 = t->left;
2653 if (t1) {
2654 rv = execute(t1, pin, pout, 0);
2655 }
2656 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002657 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002658
2659 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002660
Denis Vlasenkoe4712752007-04-14 15:08:41 +00002661 broken:
Eric Andersenff9eee42001-06-29 04:57:14 +00002662 t->words = wp2;
2663 isbreak = 0;
2664 freehere(areanum);
2665 freearea(areanum);
2666 areanum = a;
2667 if (interactive && intr) {
2668 closeall();
2669 fail();
2670 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002671
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002672 i = trapset;
2673 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002674 trapset = 0;
2675 runtrap(i);
2676 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002677
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002678 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002679 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002680}
2681
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002682typedef int (*builtin_func_ptr)(struct op *);
2683
Denis Vlasenkoe4712752007-04-14 15:08:41 +00002684static builtin_func_ptr inbuilt(const char *s)
2685{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002686 const struct builtincmd *bp;
2687
Denis Vlasenko95cb3262007-04-09 03:06:34 +00002688 for (bp = builtincmds; bp->name; bp++)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002689 if (strcmp(bp->name, s) == 0)
2690 return bp->builtinfunc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002691 return NULL;
2692}
2693
2694static int forkexec(struct op *t, int *pin, int *pout, int act, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002695{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002696 pid_t newpid;
Eric Andersenff9eee42001-06-29 04:57:14 +00002697 int i, rv;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002698 builtin_func_ptr shcom = NULL;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002699 int f;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002700 const char *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002701 struct ioword **iopp;
2702 int resetsig;
2703 char **owp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002704 int forked = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002705
2706 int *hpin = pin;
2707 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002708 char *hwp;
2709 int hinteractive;
2710 int hintr;
Eric Andersen8401eea2004-08-04 19:16:54 +00002711 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002712 int hexecflg;
2713
2714#if __GNUC__
2715 /* Avoid longjmp clobbering */
2716 (void) &pin;
2717 (void) &pout;
2718 (void) &wp;
2719 (void) &shcom;
2720 (void) &cp;
2721 (void) &resetsig;
2722 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002723#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002724
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002725 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, act %d\n", t, pin,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002726 pout, act));
2727 DBGPRINTF7(("FORKEXEC: t->words is %s\n",
2728 ((t->words == NULL) ? "NULL" : t->words[0])));
2729
Eric Andersenff9eee42001-06-29 04:57:14 +00002730 owp = wp;
2731 resetsig = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002732 rv = -1; /* system-detected error */
Eric Andersenff9eee42001-06-29 04:57:14 +00002733 if (t->type == TCOM) {
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002734 while (*wp++ != NULL)
2735 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00002736 cp = *wp;
2737
2738 /* strip all initial assignments */
2739 /* not correct wrt PATH=yyy command etc */
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00002740 if (FLAG['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002741 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002742 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002743 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002744 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002745
Eric Andersenff9eee42001-06-29 04:57:14 +00002746 if (cp == NULL && t->ioact == NULL) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002747 while ((cp = *owp++) != NULL && assign(cp, COPYV))
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002748 continue;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002749 DBGPRINTF(("FORKEXEC: returning setstatus()\n"));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002750 return setstatus(0);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002751 }
2752 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002753 shcom = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002754 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002755 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002756
Eric Andersenff9eee42001-06-29 04:57:14 +00002757 t->words = wp;
2758 f = act;
Eric Andersenff9eee42001-06-29 04:57:14 +00002759
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002760 DBGPRINTF(("FORKEXEC: shcom %p, f&FEXEC 0x%x, owp %p\n", shcom,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002761 f & FEXEC, owp));
2762
2763 if (shcom == NULL && (f & FEXEC) == 0) {
2764 /* Save values in case the child process alters them */
Eric Andersenff9eee42001-06-29 04:57:14 +00002765 hpin = pin;
2766 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002767 hwp = *wp;
2768 hinteractive = interactive;
2769 hintr = intr;
2770 hbrklist = brklist;
2771 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002772
Eric Andersen12de6cf2004-08-04 19:19:10 +00002773 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
2774
2775 newpid = vfork();
2776
2777 if (newpid == -1) {
Denis Vlasenko89f0b342006-11-18 22:04:09 +00002778 DBGPRINTF(("FORKEXEC: ERROR, cannot vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002779 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002780 }
2781
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002782 if (newpid > 0) { /* Parent */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002783 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002784 pin = hpin;
2785 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002786 *wp = hwp;
2787 interactive = hinteractive;
2788 intr = hintr;
2789 brklist = hbrklist;
2790 execflg = hexecflg;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002791/* moved up
Eric Andersenff9eee42001-06-29 04:57:14 +00002792 if (i == -1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002793 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002794*/
Eric Andersenff9eee42001-06-29 04:57:14 +00002795 if (pin != NULL)
2796 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002797
2798 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002799 }
2800
Eric Andersen12de6cf2004-08-04 19:19:10 +00002801 /* Must be the child process, pid should be 0 */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002802 DBGPRINTF(("FORKEXEC: child process, shcom=%p\n", shcom));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002803
Eric Andersenff9eee42001-06-29 04:57:14 +00002804 if (interactive) {
2805 signal(SIGINT, SIG_IGN);
2806 signal(SIGQUIT, SIG_IGN);
2807 resetsig = 1;
2808 }
2809 interactive = 0;
2810 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002811 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002812 brklist = 0;
2813 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002814 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002815
Eric Andersenff9eee42001-06-29 04:57:14 +00002816 if (owp != NULL)
2817 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2818 if (shcom == NULL)
2819 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002820
Eric Andersenff9eee42001-06-29 04:57:14 +00002821#ifdef COMPIPE
2822 if ((pin != NULL || pout != NULL) && shcom != NULL && shcom != doexec) {
2823 err("piping to/from shell builtins not yet done");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002824 if (forked)
2825 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002826 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002827 }
2828#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00002829
Eric Andersenff9eee42001-06-29 04:57:14 +00002830 if (pin != NULL) {
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002831 xmove_fd(pin[0], 0);
2832 if (pin[1] != 0) close(pin[1]);
Eric Andersenff9eee42001-06-29 04:57:14 +00002833 }
2834 if (pout != NULL) {
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002835 xmove_fd(pout[1], 1);
2836 if (pout[1] != 1) close(pout[0]);
Eric Andersenff9eee42001-06-29 04:57:14 +00002837 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002838
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002839 iopp = t->ioact;
2840 if (iopp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002841 if (shcom != NULL && shcom != doexec) {
2842 prs(cp);
2843 err(": cannot redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002844 if (forked)
2845 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002846 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002847 }
2848 while (*iopp)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002849 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
2850 if (forked)
2851 _exit(rv);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002852 return rv;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002853 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002854 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002855
2856 if (shcom) {
2857 i = setstatus((*shcom) (t));
2858 if (forked)
2859 _exit(i);
2860 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002861 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002862 }
2863
Eric Andersenff9eee42001-06-29 04:57:14 +00002864 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002865 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002866 close(i);
2867 if (resetsig) {
2868 signal(SIGINT, SIG_DFL);
2869 signal(SIGQUIT, SIG_DFL);
2870 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002871
Eric Andersen12de6cf2004-08-04 19:19:10 +00002872 if (t->type == TPAREN)
2873 _exit(execute(t->left, NOPIPE, NOPIPE, FEXEC));
2874 if (wp[0] == NULL)
2875 _exit(0);
2876
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002877 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002878 prs(wp[0]);
2879 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002880 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002881 if (!execflg)
2882 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002883
2884 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", newpid));
2885
Eric Andersenff9eee42001-06-29 04:57:14 +00002886 leave();
2887 /* NOTREACHED */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002888 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002889}
2890
2891/*
2892 * 0< 1> are ignored as required
2893 * within pipelines.
2894 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002895static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002896{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002897 int u = -1;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002898 char *cp = NULL;
2899 const char *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002900
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002901 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002902 pipein, pipeout));
2903
Eric Andersenff9eee42001-06-29 04:57:14 +00002904 if (iop->io_unit == IODEFAULT) /* take default */
Eric Andersen8401eea2004-08-04 19:16:54 +00002905 iop->io_unit = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002906
Eric Andersenff9eee42001-06-29 04:57:14 +00002907 if (pipein && iop->io_unit == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002908 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002909
Eric Andersenff9eee42001-06-29 04:57:14 +00002910 if (pipeout && iop->io_unit == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002911 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002912
Eric Andersen8401eea2004-08-04 19:16:54 +00002913 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002914 if ((iop->io_flag & IOHERE) == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002915 cp = iop->io_name; /* huh?? */
2916 cp = evalstr(cp, DOSUB | DOTRIM);
2917 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002918 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002919 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002920
Eric Andersenff9eee42001-06-29 04:57:14 +00002921 if (iop->io_flag & IODUP) {
2922 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2923 prs(cp);
2924 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002925 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002926 }
2927 if (*cp == '-')
2928 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002929 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002930 }
2931 switch (iop->io_flag) {
2932 case IOREAD:
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002933 u = open(cp, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00002934 break;
2935
2936 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002937 case IOHERE | IOXHERE:
2938 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002939 cp = (char*)"here file";
Eric Andersenff9eee42001-06-29 04:57:14 +00002940 break;
2941
Eric Andersen8401eea2004-08-04 19:16:54 +00002942 case IOWRITE | IOCAT:
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002943 u = open(cp, O_WRONLY);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002944 if (u >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002945 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002946 break;
2947 }
2948 case IOWRITE:
2949 u = creat(cp, 0666);
2950 break;
2951
2952 case IODUP:
Eric Andersen8401eea2004-08-04 19:16:54 +00002953 u = dup2(*cp - '0', iop->io_unit);
Eric Andersenff9eee42001-06-29 04:57:14 +00002954 break;
2955
2956 case IOCLOSE:
2957 close(iop->io_unit);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002958 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002959 }
2960 if (u < 0) {
2961 prs(cp);
2962 prs(": cannot ");
2963 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002964 return 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002965 }
2966 if (u != iop->io_unit) {
2967 dup2(u, iop->io_unit);
2968 close(u);
Eric Andersenff9eee42001-06-29 04:57:14 +00002969 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002970 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002971}
2972
Eric Andersenff9eee42001-06-29 04:57:14 +00002973/*
2974 * Enter a new loop level (marked for break/continue).
2975 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002976static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00002977{
2978 bc->nextlev = brklist;
2979 brklist = bc;
2980}
2981
2982/*
2983 * Wait for the last process created.
2984 * Print a message for each process found
2985 * that was killed by a signal.
2986 * Ignore interrupt signals while waiting
2987 * unless `canintr' is true.
2988 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002989static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00002990{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002991 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002992 int s;
2993 int oheedint = heedint;
2994
2995 heedint = 0;
2996 rv = 0;
2997 do {
2998 pid = wait(&s);
2999 if (pid == -1) {
3000 if (errno != EINTR || canintr)
3001 break;
3002 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003003 rv = WAITSIG(s);
3004 if (rv != 0) {
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003005 if (rv < ARRAY_SIZE(signame)) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003006 if (signame[rv] != NULL) {
3007 if (pid != lastpid) {
3008 prn(pid);
3009 prs(": ");
3010 }
3011 prs(signame[rv]);
3012 }
3013 } else {
3014 if (pid != lastpid) {
3015 prn(pid);
3016 prs(": ");
3017 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003018 prs("Signal ");
3019 prn(rv);
3020 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003021 }
3022 if (WAITCORE(s))
3023 prs(" - core dumped");
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003024 if (rv >= ARRAY_SIZE(signame) || signame[rv])
Eric Andersenff9eee42001-06-29 04:57:14 +00003025 prs("\n");
3026 rv = -1;
3027 } else
3028 rv = WAITVAL(s);
3029 }
3030 } while (pid != lastpid);
3031 heedint = oheedint;
3032 if (intr) {
3033 if (interactive) {
3034 if (canintr)
3035 intr = 0;
3036 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003037 if (exstat == 0)
3038 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003039 onintr(0);
3040 }
3041 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003042 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003043}
3044
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003045static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003046{
3047 exstat = s;
3048 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003049 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003050}
3051
3052/*
3053 * PATH-searching interface to execve.
3054 * If getenv("PATH") were kept up-to-date,
3055 * execvp might be used.
3056 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003057static const char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003058{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003059 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003060 const char *sp;
3061 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003062 int eacces = 0, asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003063 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003064
Denis Vlasenko80d14be2007-04-10 23:03:30 +00003065 if (ENABLE_FEATURE_SH_STANDALONE) {
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003066 if (find_applet_by_name(name) >= 0) {
Rob Landleya299efb2006-08-10 21:46:43 +00003067 /* We have to exec here since we vforked. Running
Denis Vlasenkoe4f2d062007-04-11 17:03:19 +00003068 * run_applet_and_exit() won't work and bad things
Rob Landleya299efb2006-08-10 21:46:43 +00003069 * will happen. */
Denis Vlasenkobdbbb7e2007-06-08 15:02:55 +00003070 execve(bb_busybox_exec_path, v, envp);
Rob Landleya299efb2006-08-10 21:46:43 +00003071 }
Eric Andersen1c039232001-07-07 00:05:55 +00003072 }
Eric Andersen1c039232001-07-07 00:05:55 +00003073
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003074 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003075
Eric Andersen8401eea2004-08-04 19:16:54 +00003076 sp = any('/', c) ? "" : path->value;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003077 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003078 while (asis || *sp != '\0') {
3079 asis = 0;
3080 tp = e.linep;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003081 for (; *sp != '\0'; tp++) {
3082 *tp = *sp++;
3083 if (*tp == ':') {
3084 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003085 break;
3086 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003087 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003088 if (tp != e.linep)
3089 *tp++ = '/';
Eric Andersen8401eea2004-08-04 19:16:54 +00003090 for (i = 0; (*tp++ = c[i++]) != '\0';);
Eric Andersen1c039232001-07-07 00:05:55 +00003091
Eric Andersen12de6cf2004-08-04 19:19:10 +00003092 DBGPRINTF3(("REXECVE: e.linep is %s\n", e.linep));
3093
Eric Andersenff9eee42001-06-29 04:57:14 +00003094 execve(e.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003095
Eric Andersenff9eee42001-06-29 04:57:14 +00003096 switch (errno) {
3097 case ENOEXEC:
3098 *v = e.linep;
3099 tp = *--v;
3100 *v = e.linep;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003101 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003102 *v = tp;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003103 return "no Shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003104
3105 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003106 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003107
3108 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003109 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003110
3111 case EACCES:
3112 eacces++;
3113 break;
3114 }
3115 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003116 return errno == ENOENT ? "not found" : "cannot execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003117}
3118
3119/*
3120 * Run the command produced by generator `f'
3121 * applied to stream `arg'.
3122 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003123static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003124{
3125 struct op *otree;
3126 struct wdblock *swdlist;
3127 struct wdblock *siolist;
3128 jmp_buf ev, rt;
3129 xint *ofail;
3130 int rv;
3131
3132#if __GNUC__
3133 /* Avoid longjmp clobbering */
3134 (void) &rv;
3135#endif
3136
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003137 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003138 areanum, outtree, failpt));
3139
Eric Andersenff9eee42001-06-29 04:57:14 +00003140 areanum++;
3141 swdlist = wdlist;
3142 siolist = iolist;
3143 otree = outtree;
3144 ofail = failpt;
3145 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003146
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003147 errpt = ev;
3148 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003149 wdlist = 0;
3150 iolist = 0;
3151 pushio(argp, f);
3152 e.iobase = e.iop;
3153 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003154 failpt = rt;
3155 if (setjmp(failpt) == 0 && yyparse() == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003156 rv = execute(outtree, NOPIPE, NOPIPE, 0);
3157 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003158 } else {
3159 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003160 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003161
Eric Andersenff9eee42001-06-29 04:57:14 +00003162 wdlist = swdlist;
3163 iolist = siolist;
3164 failpt = ofail;
3165 outtree = otree;
3166 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003167
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003168 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003169}
3170
3171/* -------- do.c -------- */
3172
3173/*
3174 * built-in commands: doX
3175 */
3176
Eric Andersen8401eea2004-08-04 19:16:54 +00003177static int dohelp(struct op *t)
Eric Andersen1c039232001-07-07 00:05:55 +00003178{
3179 int col;
3180 const struct builtincmd *x;
3181
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003182 puts("\nBuilt-in commands:\n"
3183 "-------------------");
Eric Andersen1c039232001-07-07 00:05:55 +00003184
Denis Vlasenko95cb3262007-04-09 03:06:34 +00003185 col = 0;
3186 x = builtincmds;
3187 while (x->name) {
3188 col += printf("%c%s", ((col == 0) ? '\t' : ' '), x->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003189 if (col > 60) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00003190 bb_putchar('\n');
Eric Andersen1c039232001-07-07 00:05:55 +00003191 col = 0;
3192 }
Denis Vlasenko95cb3262007-04-09 03:06:34 +00003193 x++;
Eric Andersen1c039232001-07-07 00:05:55 +00003194 }
Denis Vlasenko80d14be2007-04-10 23:03:30 +00003195#if ENABLE_FEATURE_SH_STANDALONE
Eric Andersen1c039232001-07-07 00:05:55 +00003196 {
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003197 const char *applet = applet_names;
Eric Andersen1c039232001-07-07 00:05:55 +00003198
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003199 while (*applet) {
3200 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet);
Eric Andersen1c039232001-07-07 00:05:55 +00003201 if (col > 60) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00003202 bb_putchar('\n');
Eric Andersen1c039232001-07-07 00:05:55 +00003203 col = 0;
3204 }
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003205 applet += strlen(applet) + 1;
Eric Andersen1c039232001-07-07 00:05:55 +00003206 }
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
Eric Andersen8401eea2004-08-04 19:16:54 +00003213static int dolabel(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003214{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003215 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003216}
3217
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003218static int dochdir(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003219{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003220 const char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003221
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003222 cp = t->words[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003223 if (cp == NULL) {
3224 cp = homedir->value;
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003225 if (cp != NULL)
3226 goto do_cd;
3227 er = ": no home directory";
3228 } else {
3229 do_cd:
3230 if (chdir(cp) >= 0)
3231 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003232 er = ": bad directory";
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003233 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003234 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003235 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003236 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003237}
3238
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003239static int doshift(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003240{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003241 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003242
Eric Andersen8401eea2004-08-04 19:16:54 +00003243 n = t->words[1] ? getn(t->words[1]) : 1;
3244 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003245 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003246 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003247 }
3248 dolv[n] = dolv[0];
3249 dolv += n;
3250 dolc -= n;
3251 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003252 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003253}
3254
3255/*
3256 * execute login and newgrp directly
3257 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003258static int dologin(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003259{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003260 const char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003261
3262 if (interactive) {
3263 signal(SIGINT, SIG_DFL);
3264 signal(SIGQUIT, SIG_DFL);
3265 }
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003266 cp = rexecve(t->words[0], t->words, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00003267 prs(t->words[0]);
3268 prs(": ");
3269 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003270 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003271}
3272
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003273static int doumask(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003274{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003275 int i, n;
3276 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003277
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003278 cp = t->words[1];
3279 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003280 i = umask(0);
3281 umask(i);
Eric Andersen8401eea2004-08-04 19:16:54 +00003282 for (n = 3 * 4; (n -= 3) >= 0;)
Denis Vlasenko4daad902007-09-27 10:20:47 +00003283 fputc('0' + ((i >> n) & 07), stderr);
3284 fputc('\n', stderr);
Eric Andersenff9eee42001-06-29 04:57:14 +00003285 } else {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003286/* huh??? '8','9' are not allowed! */
Eric Andersen8401eea2004-08-04 19:16:54 +00003287 for (n = 0; *cp >= '0' && *cp <= '9'; cp++)
3288 n = n * 8 + (*cp - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003289 umask(n);
3290 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003291 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003292}
3293
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003294static int doexec(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003295{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003296 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00003297 jmp_buf ex;
3298 xint *ofail;
3299
3300 t->ioact = NULL;
Eric Andersen8401eea2004-08-04 19:16:54 +00003301 for (i = 0; (t->words[i] = t->words[i + 1]) != NULL; i++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003302 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003303 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003304 execflg = 1;
3305 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003306 failpt = ex;
3307 if (setjmp(failpt) == 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00003308 execute(t, NOPIPE, NOPIPE, FEXEC);
3309 failpt = ofail;
3310 execflg = 0;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003311 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003312}
3313
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003314static int dodot(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003315{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003316 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003317 const char *sp;
3318 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003319 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003320 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003321
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003322 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 +00003323
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003324 cp = t->words[1];
3325 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003326 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003327 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003328 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003329 DBGPRINTF(("DODOT: cp is %s\n", cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003330
Eric Andersen8401eea2004-08-04 19:16:54 +00003331 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003332
3333 DBGPRINTF(("DODOT: sp is %s, e.linep is %s\n",
3334 ((sp == NULL) ? "NULL" : sp),
3335 ((e.linep == NULL) ? "NULL" : e.linep)));
3336
Eric Andersenff9eee42001-06-29 04:57:14 +00003337 while (*sp) {
3338 tp = e.linep;
3339 while (*sp && (*tp = *sp++) != ':')
3340 tp++;
3341 if (tp != e.linep)
3342 *tp++ = '/';
Eric Andersen12de6cf2004-08-04 19:19:10 +00003343
Eric Andersen8401eea2004-08-04 19:16:54 +00003344 for (i = 0; (*tp++ = cp[i++]) != '\0';);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003345
3346 /* Original code */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00003347 i = open(e.linep, O_RDONLY);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003348 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003349 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003350 maltmp = remap(i);
3351 DBGPRINTF(("DODOT: remap=%d, exstat=%d, e.iofd %d, i %d, e.linep is %s\n", maltmp, exstat, e.iofd, i, e.linep));
3352
3353 next(maltmp); /* Basically a PUSHIO */
3354
3355 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3356
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003357 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003358 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003359 } /* while */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003360
Eric Andersenff9eee42001-06-29 04:57:14 +00003361 prs(cp);
3362 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003363
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003364 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003365}
3366
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003367static int dowait(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003368{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003369 int i;
3370 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003371
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003372 cp = t->words[1];
3373 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003374 i = getn(cp);
3375 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003376 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003377 } else
3378 i = -1;
3379 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003380 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003381}
3382
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003383static int doread(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003384{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003385 char *cp, **wp;
3386 int nb = 0;
3387 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003388
3389 if (t->words[1] == NULL) {
3390 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003391 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003392 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003393 for (wp = t->words + 1; *wp; wp++) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003394 for (cp = e.linep; !nl && cp < elinep - 1; cp++) {
3395 nb = read(0, cp, sizeof(*cp));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003396 if (nb != sizeof(*cp))
Eric Andersenff9eee42001-06-29 04:57:14 +00003397 break;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003398 nl = (*cp == '\n');
3399 if (nl || (wp[1] && any(*cp, ifs->value)))
3400 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003401 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003402 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003403 if (nb <= 0)
3404 break;
3405 setval(lookup(*wp), e.linep);
3406 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003407 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003408}
3409
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003410static int doeval(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003411{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003412 return RUN(awordlist, t->words + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003413}
3414
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003415static int dotrap(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003416{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003417 int n, i;
3418 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003419
3420 if (t->words[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003421 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003422 if (trap[i]) {
3423 prn(i);
3424 prs(": ");
3425 prs(trap[i]);
3426 prs("\n");
3427 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003428 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003429 }
3430 resetsig = isdigit(*t->words[1]);
3431 for (i = resetsig ? 1 : 2; t->words[i] != NULL; ++i) {
3432 n = getsig(t->words[i]);
3433 freecell(trap[n]);
3434 trap[n] = 0;
3435 if (!resetsig) {
3436 if (*t->words[1] != '\0') {
3437 trap[n] = strsave(t->words[1], 0);
3438 setsig(n, sig);
3439 } else
3440 setsig(n, SIG_IGN);
3441 } else {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003442 if (interactive) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003443 if (n == SIGINT)
3444 setsig(n, onintr);
3445 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003446 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003447 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00003448 setsig(n, SIG_DFL);
3449 }
3450 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003451 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003452}
3453
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003454static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003455{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003456 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003457
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003458 n = getn(s);
3459 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003460 err("trap: bad signal number");
3461 n = 0;
3462 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003463 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003464}
3465
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003466static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003467{
3468 if (n == 0)
3469 return;
3470 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3471 ourtrap[n] = 1;
3472 signal(n, f);
3473 }
3474}
3475
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003476static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003477{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003478 char *s;
3479 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003480
3481 s = as;
3482 m = 1;
3483 if (*s == '-') {
3484 m = -1;
3485 s++;
3486 }
3487 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003488 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003489 if (*s) {
3490 prs(as);
3491 err(": bad number");
3492 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003493 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003494}
3495
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003496static int dobreak(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003497{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003498 return brkcontin(t->words[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003499}
3500
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003501static int docontinue(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003502{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003503 return brkcontin(t->words[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003504}
3505
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003506static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003507{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003508 struct brkcon *bc;
3509 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003510
Eric Andersen8401eea2004-08-04 19:16:54 +00003511 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003512 if (nl <= 0)
3513 nl = 999;
3514 do {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003515 bc = brklist;
3516 if (bc == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003517 break;
3518 brklist = bc->nextlev;
3519 } while (--nl);
3520 if (nl) {
3521 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003522 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003523 }
3524 isbreak = val;
3525 longjmp(bc->brkpt, 1);
3526 /* NOTREACHED */
3527}
3528
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003529static int doexit(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003530{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003531 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003532
3533 execflg = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003534 cp = t->words[1];
3535 if (cp != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003536 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003537
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003538 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003539
Eric Andersenff9eee42001-06-29 04:57:14 +00003540 leave();
3541 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003542 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003543}
3544
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003545static int doexport(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003546{
Eric Andersen8401eea2004-08-04 19:16:54 +00003547 rdexp(t->words + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003548 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003549}
3550
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003551static int doreadonly(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003552{
Eric Andersen8401eea2004-08-04 19:16:54 +00003553 rdexp(t->words + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003554 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003555}
3556
Eric Andersen8401eea2004-08-04 19:16:54 +00003557static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003558{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003559 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003560 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3561
Eric Andersenff9eee42001-06-29 04:57:14 +00003562 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003563 for (; *wp != NULL; wp++) {
3564 if (isassign(*wp)) {
3565 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003566
Matt Kraaif69bfc72001-07-12 19:39:59 +00003567 assign(*wp, COPYV);
Eric Andersen8401eea2004-08-04 19:16:54 +00003568 for (cp = *wp; *cp != '='; cp++);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003569 *cp = '\0';
3570 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003571 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003572 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003573 else
3574 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003575 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003576 } else
3577 putvlist(key, 1);
3578}
3579
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003580static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003581{
3582 prs(s);
3583 err(": bad identifier");
3584}
3585
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003586static int doset(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003587{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003588 struct var *vp;
3589 char *cp;
3590 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003591
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003592 cp = t->words[1];
3593 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003594 for (vp = vlist; vp; vp = vp->next)
3595 varput(vp->name, 1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003596 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003597 }
3598 if (*cp == '-') {
3599 /* bad: t->words++; */
Eric Andersen8401eea2004-08-04 19:16:54 +00003600 for (n = 0; (t->words[n] = t->words[n + 1]) != NULL; n++);
Eric Andersenff9eee42001-06-29 04:57:14 +00003601 if (*++cp == 0)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003602 FLAG['x'] = FLAG['v'] = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003603 else {
3604 for (; *cp; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003605 switch (*cp) {
3606 case 'e':
3607 if (!interactive)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003608 FLAG['e']++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003609 break;
3610
3611 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003612 if (*cp >= 'a' && *cp <= 'z')
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003613 FLAG[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003614 break;
3615 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003616 }
3617 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003618 setdash();
3619 }
3620 if (t->words[1]) {
3621 t->words[0] = dolv[0];
Eric Andersen8401eea2004-08-04 19:16:54 +00003622 for (n = 1; t->words[n]; n++)
3623 setarea((char *) t->words[n], 0);
3624 dolc = n - 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003625 dolv = t->words;
3626 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003627 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003628 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003629 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003630}
3631
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003632static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003633{
Matt Kraai69edfec2001-08-06 14:14:18 +00003634 if (isalnum(*s) || *s == '_') {
Eric Andersenff9eee42001-06-29 04:57:14 +00003635 write(out, s, strlen(s));
3636 write(out, "\n", 1);
3637 }
3638}
3639
3640
3641/*
3642 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3643 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003644 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003645static int dotimes(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00003646{
3647 struct tms buf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003648 long clk_tck = sysconf(_SC_CLK_TCK);
Eric Andersenff9eee42001-06-29 04:57:14 +00003649
3650 times(&buf);
3651 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
Eric Andersen8401eea2004-08-04 19:16:54 +00003652 (int) (buf.tms_utime / clk_tck / 60),
3653 ((double) buf.tms_utime) / clk_tck,
3654 (int) (buf.tms_stime / clk_tck / 60),
3655 ((double) buf.tms_stime) / clk_tck,
3656 (int) (buf.tms_cutime / clk_tck / 60),
3657 ((double) buf.tms_cutime) / clk_tck,
3658 (int) (buf.tms_cstime / clk_tck / 60),
3659 ((double) buf.tms_cstime) / clk_tck);
Eric Andersenff9eee42001-06-29 04:57:14 +00003660 return 0;
3661}
3662
3663
Eric Andersenff9eee42001-06-29 04:57:14 +00003664/* -------- eval.c -------- */
3665
3666/*
3667 * ${}
3668 * `command`
3669 * blank interpretation
3670 * quoting
3671 * glob
3672 */
3673
Eric Andersen8401eea2004-08-04 19:16:54 +00003674static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003675{
3676 struct wdblock *wb;
3677 char **wp;
3678 char **wf;
3679 jmp_buf ev;
3680
3681#if __GNUC__
3682 /* Avoid longjmp clobbering */
3683 (void) &wp;
3684 (void) &ap;
3685#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003686
3687 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3688
Eric Andersenff9eee42001-06-29 04:57:14 +00003689 wp = NULL;
3690 wb = NULL;
3691 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003692 errpt = ev;
3693 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003694 while (*ap && isassign(*ap))
3695 expand(*ap++, &wb, f & ~DOGLOB);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003696 if (FLAG['k']) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003697 for (wf = ap; *wf; wf++) {
3698 if (isassign(*wf))
3699 expand(*wf, &wb, f & ~DOGLOB);
3700 }
3701 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003702 for (wb = addword((char *) 0, wb); *ap; ap++) {
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003703 if (!FLAG['k'] || !isassign(*ap))
Eric Andersenff9eee42001-06-29 04:57:14 +00003704 expand(*ap, &wb, f & ~DOKEY);
3705 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003706 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003707 wp = getwords(wb);
3708 quitenv();
3709 } else
3710 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003711
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003712 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003713}
3714
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003715
Eric Andersenff9eee42001-06-29 04:57:14 +00003716/*
3717 * Make the exported environment from the exported
3718 * names in the dictionary. Keyword assignments
3719 * will already have been done.
3720 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003721static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003722{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003723 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003724
3725 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003726
Eric Andersenff9eee42001-06-29 04:57:14 +00003727 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003728 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003729 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003730 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003731 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003732}
3733
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003734static int expand(const char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003735{
3736 jmp_buf ev;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003737 char *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003738
3739#if __GNUC__
3740 /* Avoid longjmp clobbering */
3741 (void) &cp;
3742#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003743
3744 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3745
Eric Andersenff9eee42001-06-29 04:57:14 +00003746 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003747
Eric Andersenff9eee42001-06-29 04:57:14 +00003748 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003749 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003750
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003751 if (!anys("$`'\"", cp) && !anys(ifs->value, cp)
3752 && ((f & DOGLOB) == 0 || !anys("[*?", cp))
3753 ) {
3754 xp = strsave(cp, areanum);
Eric Andersenff9eee42001-06-29 04:57:14 +00003755 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003756 unquote(xp);
3757 *wbp = addword(xp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003758 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003759 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003760 errpt = ev;
3761 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003762 PUSHIO(aword, cp, strchar);
3763 e.iobase = e.iop;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003764 while ((xp = blank(f)) && gflg == 0) {
3765 e.linep = xp;
3766 xp = strsave(xp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003767 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003768 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003769 unquote(xp);
3770 *wbp = addword(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003771 } else
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003772 *wbp = glob(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003773 }
3774 quitenv();
3775 } else
3776 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003777 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003778}
3779
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003780static char *evalstr(char *cp, int f)
3781{
3782 struct wdblock *wb;
3783
3784 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
3785
3786 wb = NULL;
3787 if (expand(cp, &wb, f)) {
3788 if (wb == NULL || wb->w_nword == 0
3789 || (cp = wb->w_words[0]) == NULL
3790 ) {
Denis Vlasenko8e858e22007-03-07 09:35:43 +00003791// TODO: I suspect that
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003792// char *evalstr(char *cp, int f) is actually
3793// const char *evalstr(const char *cp, int f)!
3794 cp = (char*)"";
3795 }
3796 DELETE(wb);
3797 } else
3798 cp = NULL;
3799 return cp;
3800}
3801
3802
Eric Andersenff9eee42001-06-29 04:57:14 +00003803/*
3804 * Blank interpretation and quoting
3805 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003806static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003807{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003808 int c, c1;
3809 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003810 int scanequals, foundequals;
3811
Eric Andersen12de6cf2004-08-04 19:19:10 +00003812 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3813
Eric Andersenff9eee42001-06-29 04:57:14 +00003814 sp = e.linep;
3815 scanequals = f & DOKEY;
3816 foundequals = 0;
3817
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003818 loop:
3819 c = subgetc('"', foundequals);
3820 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003821 case 0:
3822 if (sp == e.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003823 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003824 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003825 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003826
3827 default:
3828 if (f & DOBLANK && any(c, ifs->value))
3829 goto loop;
3830 break;
3831
3832 case '"':
3833 case '\'':
3834 scanequals = 0;
3835 if (INSUB())
3836 break;
3837 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3838 if (c == 0)
3839 break;
3840 if (c == '\'' || !any(c, "$`\""))
3841 c |= QUOTE;
3842 *e.linep++ = c;
3843 }
3844 c = 0;
3845 }
3846 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003847 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003848 scanequals = 0;
3849 for (;;) {
3850 c = subgetc('"', foundequals);
3851 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003852 f & (DOBLANK && any(c, ifs->value)) ||
3853 (!INSUB() && any(c, "\"'"))) {
3854 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003855 unget(c);
3856 if (any(c, "\"'"))
3857 goto loop;
3858 break;
3859 }
3860 if (scanequals) {
3861 if (c == '=') {
3862 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003863 scanequals = 0;
3864 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003865 scanequals = 0;
3866 }
3867 *e.linep++ = c;
3868 }
3869 *e.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003870 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003871}
3872
3873/*
3874 * Get characters, substituting for ` and $
3875 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003876static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003877{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003878 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003879
3880 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003881
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003882 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003883 c = my_getc(ec);
3884 if (!INSUB() && ec != '\'') {
3885 if (c == '`') {
3886 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003887 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003888 e.iop->task = XGRAVE;
3889 goto again;
3890 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003891 if (c == '$') {
3892 c = dollar(quoted);
3893 if (c == 0) {
3894 e.iop->task = XDOLL;
3895 goto again;
3896 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003897 }
3898 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003899 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003900}
3901
3902/*
3903 * Prepare to generate the string returned by ${} substitution.
3904 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003905static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003906{
3907 int otask;
3908 struct io *oiop;
3909 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003910 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003911 struct var *vp;
3912
Eric Andersen12de6cf2004-08-04 19:19:10 +00003913 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3914
Eric Andersenff9eee42001-06-29 04:57:14 +00003915 c = readc();
3916 s = e.linep;
3917 if (c != '{') {
3918 *e.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003919 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003920 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Eric Andersenff9eee42001-06-29 04:57:14 +00003921 if (e.linep < elinep)
3922 *e.linep++ = c;
3923 unget(c);
3924 }
3925 c = 0;
3926 } else {
3927 oiop = e.iop;
3928 otask = e.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003929
Eric Andersenff9eee42001-06-29 04:57:14 +00003930 e.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003931 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00003932 if (e.linep < elinep)
3933 *e.linep++ = c;
3934 if (oiop == e.iop)
3935 e.iop->task = otask;
3936 if (c != '}') {
3937 err("unclosed ${");
3938 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003939 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003940 }
3941 }
3942 if (e.linep >= elinep) {
3943 err("string in ${} too long");
3944 gflg++;
3945 e.linep -= 10;
3946 }
3947 *e.linep = 0;
3948 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003949 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003950 if (any(*cp, "=-+?")) {
3951 c = *cp;
3952 *cp++ = 0;
3953 break;
3954 }
3955 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3956 if (dolc > 1) {
3957 /* currently this does not distinguish $* and $@ */
3958 /* should check dollar */
3959 e.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00003960 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003961 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003962 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00003963 s[0] = '1';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003964 s[1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003965 }
3966 }
3967 vp = lookup(s);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003968 dolp = vp->value;
3969 if (dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003970 switch (c) {
3971 case '=':
3972 if (isdigit(*s)) {
3973 err("cannot use ${...=...} with $n");
3974 gflg++;
3975 break;
3976 }
3977 setval(vp, cp);
3978 dolp = vp->value;
3979 break;
3980
3981 case '-':
3982 dolp = strsave(cp, areanum);
3983 break;
3984
3985 case '?':
3986 if (*cp == 0) {
3987 prs("missing value for ");
3988 err(s);
3989 } else
3990 err(cp);
3991 gflg++;
3992 break;
3993 }
3994 } else if (c == '+')
3995 dolp = strsave(cp, areanum);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003996 if (FLAG['u'] && dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003997 prs("unset variable: ");
3998 err(s);
3999 gflg++;
4000 }
4001 e.linep = s;
4002 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004003 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004004}
4005
4006/*
4007 * Run the command in `...` and read its output.
4008 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004009
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004010static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004011{
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004012 /* moved to G: static char child_cmd[LINELIM]; */
4013
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];
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004018 const char *src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004019 char *dest;
4020 int count;
4021 int ignore;
4022 int ignore_once;
4023 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004024 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004025
4026#if __GNUC__
4027 /* Avoid longjmp clobbering */
4028 (void) &cp;
4029#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004030
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004031 for (cp = e.iop->argp->aword; *cp != '`'; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004032 if (*cp == 0) {
4033 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004034 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004035 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004036 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004037
4038 /* string copy with dollar expansion */
4039 src = e.iop->argp->aword;
4040 dest = child_cmd;
4041 count = 0;
4042 ignore = 0;
4043 ignore_once = 0;
4044 while ((*src != '`') && (count < LINELIM)) {
4045 if (*src == '\'')
4046 ignore = !ignore;
4047 if (*src == '\\')
4048 ignore_once = 1;
4049 if (*src == '$' && !ignore && !ignore_once) {
4050 struct var *vp;
Denis Vlasenkoab801872007-12-02 08:35:37 +00004051 /* moved to G to reduce stack usage
Eric Andersen737f5fb2003-03-14 16:05:59 +00004052 char var_name[LINELIM];
4053 char alt_value[LINELIM];
Denis Vlasenkoab801872007-12-02 08:35:37 +00004054 */
4055#define var_name (G.grave__var_name)
4056#define alt_value (G.grave__alt_value)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004057 int var_index = 0;
4058 int alt_index = 0;
4059 char operator = 0;
4060 int braces = 0;
4061 char *value;
4062
4063 src++;
4064 if (*src == '{') {
4065 braces = 1;
4066 src++;
4067 }
4068
4069 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004070 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004071 var_name[var_index++] = *src++;
4072 var_name[var_index] = 0;
4073
4074 if (braces) {
4075 switch (*src) {
4076 case '}':
4077 break;
4078 case '-':
4079 case '=':
4080 case '+':
4081 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004082 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004083 break;
4084 default:
4085 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004086 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004087 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004088 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004089 src++;
4090 while (*src && (*src != '}')) {
4091 alt_value[alt_index++] = *src++;
4092 }
4093 alt_value[alt_index] = 0;
4094 if (*src != '}') {
4095 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004096 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004097 }
4098 }
4099 src++;
4100 }
4101
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004102 if (isalpha(*var_name)) {
4103 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004104
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004105 char *namep = var_name;
4106
4107 *dest++ = '$';
4108 if (braces)
4109 *dest++ = '{';
4110 while (*namep)
4111 *dest++ = *namep++;
4112 if (operator) {
4113 char *altp = alt_value;
4114 *dest++ = operator;
4115 while (*altp)
4116 *dest++ = *altp++;
4117 }
4118 if (braces)
4119 *dest++ = '}';
4120
4121 wb = addword(lookup(var_name)->name, wb);
4122 } else {
4123 /* expand */
4124
4125 vp = lookup(var_name);
4126 if (vp->value != null)
4127 value = (operator == '+') ?
4128 alt_value : vp->value;
4129 else if (operator == '?') {
4130 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004131 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004132 } else if (alt_index && (operator != '+')) {
4133 value = alt_value;
4134 if (operator == '=')
4135 setval(vp, value);
4136 } else
4137 continue;
4138
4139 while (*value && (count < LINELIM)) {
4140 *dest++ = *value++;
4141 count++;
4142 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004143 }
Denis Vlasenkoab801872007-12-02 08:35:37 +00004144#undef var_name
4145#undef alt_value
Eric Andersen737f5fb2003-03-14 16:05:59 +00004146 } else {
4147 *dest++ = *src++;
4148 count++;
4149 ignore_once = 0;
4150 }
4151 }
4152 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004153
Eric Andersenff9eee42001-06-29 04:57:14 +00004154 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004155 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004156
Eric Andersen8401eea2004-08-04 19:16:54 +00004157 while ((i = vfork()) == -1 && errno == EAGAIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004158
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004159 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004160
Eric Andersen737f5fb2003-03-14 16:05:59 +00004161 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004162 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004163 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004164 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004165 }
4166 if (i != 0) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004167 waitpid(i, NULL, 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004168 e.iop->argp->aword = ++cp;
4169 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004170 PUSHIO(afile, remap(pf[0]),
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004171 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004172 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004173 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004174 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004175 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004176 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004177 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4178 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004179
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00004180 /* Testcase where below checks are needed:
4181 * close stdout & run this script:
4182 * files=`ls`
4183 * echo "$files" >zz
4184 */
4185 xmove_fd(pf[1], 1);
4186 if (pf[0] != 1) close(pf[0]);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004187
Eric Andersen8401eea2004-08-04 19:16:54 +00004188 argument_list[0] = (char *) DEFAULT_SHELL;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004189 argument_list[1] = (char *) "-c";
Eric Andersen737f5fb2003-03-14 16:05:59 +00004190 argument_list[2] = child_cmd;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004191 argument_list[3] = NULL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004192
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004193 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004194 prs(argument_list[0]);
4195 prs(": ");
4196 err(cp);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004197 _exit(1);
Eric Andersenff9eee42001-06-29 04:57:14 +00004198}
4199
Eric Andersen737f5fb2003-03-14 16:05:59 +00004200
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004201static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004202{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004203 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004204
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004205 s = as;
4206 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004207 while (*s)
4208 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004209 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004210}
4211
4212/* -------- glob.c -------- */
4213
4214/*
4215 * glob
4216 */
4217
4218#define scopy(x) strsave((x), areanum)
4219#define BLKSIZ 512
4220#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4221
Eric Andersen8401eea2004-08-04 19:16:54 +00004222static struct wdblock *cl, *nl;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00004223static const char spcl[] ALIGN1= "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004224
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004225static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004226{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004227 int i;
4228 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004229
4230 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004231 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004232 i = 0;
4233 for (pp = cp; *pp; pp++)
4234 if (any(*pp, spcl))
4235 i++;
4236 else if (!any(*pp & ~QUOTE, spcl))
4237 *pp &= ~QUOTE;
4238 if (i != 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004239 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004240 nl = newword(cl->w_nword * 2);
4241 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004242 for (pp = cl->w_words[i]; *pp; pp++)
4243 if (any(*pp, spcl)) {
4244 globname(cl->w_words[i], pp);
4245 break;
4246 }
4247 if (*pp == '\0')
4248 nl = addword(scopy(cl->w_words[i]), nl);
4249 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004250 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004251 DELETE(cl->w_words[i]);
4252 DELETE(cl);
4253 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004254 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004255 unquote(cl->w_words[i]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004256 glob0((char *) cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
Eric Andersenff9eee42001-06-29 04:57:14 +00004257 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004258 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004259 wb = addword(cl->w_words[i], wb);
4260 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004261 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004262 }
4263 }
4264 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004265 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004266}
4267
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004268static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004269{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004270 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004271 char *name, *gp, *dp;
4272 int k;
4273 DIR *dirp;
4274 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004275 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004276 struct stat dbuf;
4277
4278 for (np = we; np != pp; pp--)
4279 if (pp[-1] == '/')
4280 break;
Eric Andersen8401eea2004-08-04 19:16:54 +00004281 for (dp = cp = space((int) (pp - np) + 3); np < pp;)
Eric Andersenff9eee42001-06-29 04:57:14 +00004282 *cp++ = *np++;
4283 *cp++ = '.';
4284 *cp = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004285 for (gp = cp = space(strlen(pp) + 1); *np && *np != '/';)
Eric Andersenff9eee42001-06-29 04:57:14 +00004286 *cp++ = *np++;
4287 *cp = '\0';
4288 dirp = opendir(dp);
4289 if (dirp == 0) {
4290 DELETE(dp);
4291 DELETE(gp);
4292 return;
4293 }
4294 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004295 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004296 /* XXX Hmmm... What this could be? (abial) */
4297 /*
Eric Andersen8401eea2004-08-04 19:16:54 +00004298 if (ent[j].d_ino == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004299 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004300 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004301 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004302 if (dname[0] == '.')
4303 if (*gp != '.')
4304 continue;
4305 for (k = 0; k < NAME_MAX; k++)
4306 if (any(dname[k], spcl))
4307 dname[k] |= QUOTE;
4308 if (gmatch(dname, gp)) {
4309 name = generate(we, pp, dname, np);
4310 if (*np && !anys(np, spcl)) {
4311 if (stat(name, &dbuf)) {
4312 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004313 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004314 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004315 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004316 nl = addword(name, nl);
4317 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004318 }
4319 closedir(dirp);
4320 DELETE(dp);
4321 DELETE(gp);
4322}
4323
4324/*
4325 * generate a pathname as below.
4326 * start..end1 / middle end
4327 * the slashes come for free
4328 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004329static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004330{
4331 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004332 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004333
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004334 p = op = space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004335 for (xp = start1; xp != end1;)
4336 *op++ = *xp++;
Eric Andersen8401eea2004-08-04 19:16:54 +00004337 for (xp = middle; (*op++ = *xp++) != '\0';);
Eric Andersenff9eee42001-06-29 04:57:14 +00004338 op--;
Eric Andersen8401eea2004-08-04 19:16:54 +00004339 for (xp = end; (*op++ = *xp++) != '\0';);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004340 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004341}
4342
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004343static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004344{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004345 int i;
4346 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004347
4348 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004349 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004350 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004351 return 1;
4352 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004353}
4354
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004355static int xstrcmp(char *p1, char *p2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004356{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004357 return strcmp(*(char **) p1, *(char **) p2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004358}
4359
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004360
Eric Andersenff9eee42001-06-29 04:57:14 +00004361/* -------- word.c -------- */
4362
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004363static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004364{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004365 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004366
Eric Andersen8401eea2004-08-04 19:16:54 +00004367 wb = (struct wdblock *) space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004368 wb->w_bsize = nw;
4369 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004370 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004371}
4372
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004373static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004374{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004375 struct wdblock *wb2;
4376 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004377
4378 if (wb == NULL)
4379 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004380 nw = wb->w_nword;
4381 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004382 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004383 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4384 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004385 wb2->w_nword = nw;
4386 DELETE(wb);
4387 wb = wb2;
4388 }
4389 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004390 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004391}
Eric Andersen8401eea2004-08-04 19:16:54 +00004392
Denis Vlasenkoe4712752007-04-14 15:08:41 +00004393static char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004394{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004395 char **wd;
4396 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004397
4398 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004399 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004400 if (wb->w_nword == 0) {
4401 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004402 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004403 }
4404 wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
Eric Andersen8401eea2004-08-04 19:16:54 +00004405 memcpy((char *) wd, (char *) wb->w_words, nb);
4406 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004407 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004408}
4409
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +00004410static int (*func) (char *, char *);
4411static int globv;
Eric Andersenff9eee42001-06-29 04:57:14 +00004412
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004413static void glob3(char *i, char *j, char *k)
Eric Andersenff9eee42001-06-29 04:57:14 +00004414{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004415 char *index1, *index2, *index3;
4416 int c;
4417 int m;
4418
4419 m = globv;
4420 index1 = i;
4421 index2 = j;
4422 index3 = k;
4423 do {
4424 c = *index1;
4425 *index1++ = *index3;
4426 *index3++ = *index2;
4427 *index2++ = c;
4428 } while (--m);
4429}
4430
4431static void glob2(char *i, char *j)
4432{
4433 char *index1, *index2, c;
4434 int m;
4435
4436 m = globv;
4437 index1 = i;
4438 index2 = j;
4439 do {
4440 c = *index1;
4441 *index1++ = *index2;
4442 *index2++ = c;
4443 } while (--m);
Eric Andersenff9eee42001-06-29 04:57:14 +00004444}
4445
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004446static void glob1(char *base, char *lim)
Eric Andersenff9eee42001-06-29 04:57:14 +00004447{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004448 char *i, *j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004449 int v2;
4450 char *lptr, *hptr;
4451 int c;
4452 unsigned n;
4453
Eric Andersenff9eee42001-06-29 04:57:14 +00004454 v2 = globv;
4455
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004456 top:
4457 n = (int) (lim - base);
4458 if (n <= v2)
Eric Andersenff9eee42001-06-29 04:57:14 +00004459 return;
Eric Andersen8401eea2004-08-04 19:16:54 +00004460 n = v2 * (n / (2 * v2));
4461 hptr = lptr = base + n;
Eric Andersenff9eee42001-06-29 04:57:14 +00004462 i = base;
Eric Andersen8401eea2004-08-04 19:16:54 +00004463 j = lim - v2;
4464 for (;;) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004465 if (i < lptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004466 c = (*func) (i, lptr);
4467 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004468 lptr -= v2;
4469 glob2(i, lptr);
Eric Andersenff9eee42001-06-29 04:57:14 +00004470 continue;
4471 }
4472 if (c < 0) {
4473 i += v2;
4474 continue;
4475 }
4476 }
4477
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004478 begin:
Eric Andersenff9eee42001-06-29 04:57:14 +00004479 if (j > hptr) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004480 c = (*func) (hptr, j);
4481 if (c == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004482 hptr += v2;
4483 glob2(hptr, j);
Eric Andersenff9eee42001-06-29 04:57:14 +00004484 goto begin;
4485 }
4486 if (c > 0) {
4487 if (i == lptr) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004488 hptr += v2;
4489 glob3(i, hptr, j);
4490 i = (lptr += v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004491 goto begin;
4492 }
4493 glob2(i, j);
4494 j -= v2;
4495 i += v2;
4496 continue;
4497 }
4498 j -= v2;
4499 goto begin;
4500 }
4501
4502
4503 if (i == lptr) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004504 if (lptr - base >= lim - hptr) {
4505 glob1(hptr + v2, lim);
Eric Andersenff9eee42001-06-29 04:57:14 +00004506 lim = lptr;
4507 } else {
4508 glob1(base, lptr);
Eric Andersen8401eea2004-08-04 19:16:54 +00004509 base = hptr + v2;
Eric Andersenff9eee42001-06-29 04:57:14 +00004510 }
4511 goto top;
4512 }
4513
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004514 lptr -= v2;
4515 glob3(j, lptr, i);
4516 j = (hptr -= v2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004517 }
4518}
4519
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004520static void glob0(char *a0, unsigned a1, int a2, int (*a3) (char *, char *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004521{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004522 func = a3;
4523 globv = a2;
4524 glob1(a0, a0 + a1 * a2);
Eric Andersenff9eee42001-06-29 04:57:14 +00004525}
4526
Eric Andersenff9eee42001-06-29 04:57:14 +00004527
4528/* -------- io.c -------- */
4529
4530/*
4531 * shell IO
4532 */
4533
Eric Andersen8401eea2004-08-04 19:16:54 +00004534static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004535{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004536 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004537
Eric Andersen8401eea2004-08-04 19:16:54 +00004538 if (e.linep > elinep) {
4539 while ((c = readc()) != '\n' && c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004540 err("input line too long");
4541 gflg++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004542 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004543 }
4544 c = readc();
Eric Andersen737f5fb2003-03-14 16:05:59 +00004545 if ((ec != '\'') && (ec != '`') && (e.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004546 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004547 c = readc();
4548 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004549 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004550 c |= QUOTE;
4551 }
4552 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004553 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004554}
4555
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004556static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004557{
4558 if (e.iop >= e.iobase)
4559 e.iop->peekc = c;
4560}
4561
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004562static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004563{
Eric Andersen8401eea2004-08-04 19:16:54 +00004564 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004565}
4566
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004567static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004568{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004569 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004570
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004571 RCPRINTF(("READC: e.iop %p, e.iobase %p\n", e.iop, e.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004572
4573 for (; e.iop >= e.iobase; e.iop--) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004574 RCPRINTF(("READC: e.iop %p, peekc 0x%x\n", e.iop, e.iop->peekc));
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004575 c = e.iop->peekc;
4576 if (c != '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004577 e.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004578 return c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004579 }
4580 if (e.iop->prev != 0) {
4581 c = (*e.iop->iofn)(e.iop->argp, e.iop);
4582 if (c != '\0') {
4583 if (c == -1) {
4584 e.iop++;
4585 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004586 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004587 if (e.iop == iostack)
4588 ioecho(c);
4589 e.iop->prev = c;
4590 return e.iop->prev;
Eric Andersenff9eee42001-06-29 04:57:14 +00004591 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004592 if (e.iop->task == XIO && e.iop->prev != '\n') {
4593 e.iop->prev = 0;
4594 if (e.iop == iostack)
4595 ioecho('\n');
4596 return '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004597 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004598 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004599 if (e.iop->task == XIO) {
4600 if (multiline) {
4601 e.iop->prev = 0;
4602 return e.iop->prev;
4603 }
4604 if (interactive && e.iop == iostack + 1) {
4605#if ENABLE_FEATURE_EDITING
4606 current_prompt = prompt->value;
4607#else
4608 prs(prompt->value);
4609#endif
4610 }
4611 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004612 } /* FOR */
4613
4614 if (e.iop >= iostack) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004615 RCPRINTF(("READC: return 0, e.iop %p\n", e.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004616 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004617 }
4618
4619 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004620 leave();
Eric Andersen12de6cf2004-08-04 19:19:10 +00004621
Eric Andersenff9eee42001-06-29 04:57:14 +00004622 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004623 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004624}
4625
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004626static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004627{
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00004628 if (FLAG['v'])
Eric Andersenff9eee42001-06-29 04:57:14 +00004629 write(2, &c, sizeof c);
4630}
4631
Eric Andersen12de6cf2004-08-04 19:19:10 +00004632
Eric Andersen8401eea2004-08-04 19:16:54 +00004633static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004634{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004635 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, e.iop %p\n", argp,
Eric Andersen12de6cf2004-08-04 19:19:10 +00004636 argp->afid, e.iop));
4637
4638 /* Set env ptr for io source to next array spot and check for array overflow */
Eric Andersenff9eee42001-06-29 04:57:14 +00004639 if (++e.iop >= &iostack[NPUSH]) {
4640 e.iop--;
4641 err("Shell input nested too deeply");
4642 gflg++;
4643 return;
4644 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004645
4646 /* We did not overflow the NPUSH array spots so setup data structs */
4647
4648 e.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004649
4650 if (argp->afid != AFID_NOBUF)
Eric Andersen8401eea2004-08-04 19:16:54 +00004651 e.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004652 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004653
4654 e.iop->argp = ioargstack + (e.iop - iostack); /* MAL - index into stack */
4655 *e.iop->argp = *argp; /* copy data from temp area into stack spot */
4656
4657 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4658
4659 if (e.iop == &iostack[0])
4660 e.iop->argp->afbuf = &mainbuf;
4661 else
4662 e.iop->argp->afbuf = &sharedbuf;
4663
4664 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4665 /* This line appears to be active when running scripts from command line */
4666 if ((isatty(e.iop->argp->afile) == 0)
4667 && (e.iop == &iostack[0]
Denis Vlasenkoea620772006-10-14 02:23:43 +00004668 || lseek(e.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004669 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4670 bufid = AFID_ID; /* AFID_ID = 0 */
4671
4672 e.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004673 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004674
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004675 DBGPRINTF(("PUSHIO: iostack %p, e.iop %p, afbuf %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004676 iostack, e.iop, e.iop->argp->afbuf));
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004677 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, e.iop %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00004678 &mainbuf, &sharedbuf, bufid, e.iop));
4679
Eric Andersenff9eee42001-06-29 04:57:14 +00004680 }
4681
Eric Andersen8401eea2004-08-04 19:16:54 +00004682 e.iop->prev = ~'\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004683 e.iop->peekc = 0;
4684 e.iop->xchar = 0;
4685 e.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004686
Eric Andersenff9eee42001-06-29 04:57:14 +00004687 if (fn == filechar || fn == linechar)
4688 e.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004689 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004690 || fn == (int (*)(struct ioarg *)) qgravechar)
Eric Andersenff9eee42001-06-29 04:57:14 +00004691 e.iop->task = XGRAVE;
4692 else
4693 e.iop->task = XOTHER;
4694}
4695
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004696static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004697{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004698 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004699
4700 xp = e.iobase;
4701 e.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004702 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004703}
4704
4705/*
4706 * Input generating functions
4707 */
4708
4709/*
4710 * Produce the characters of a string, then a newline, then EOF.
4711 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004712static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004713{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004714 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004715
4716 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004717 return 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004718 c = *ap->aword++;
4719 if (c == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004720 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004721 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004722 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004723 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004724}
4725
4726/*
4727 * Given a list of words, produce the characters
4728 * in them, with a space after each word.
4729 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004730static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004731{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004732 char c;
4733 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004734
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004735 wl = ap->awordlist;
4736 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004737 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004738 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004739 c = *(*wl)++;
4740 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004741 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004742 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004743 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004744 }
4745 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004746 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004747}
4748
4749/*
4750 * Return the characters of a list of words,
4751 * producing a space between them.
4752 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004753static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004754{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004755 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004756
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004757 wp = *ap->awordlist++;
4758 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004759 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004760 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004761 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004762 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004763}
4764
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004765static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004766{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004767 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004768
4769 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004770 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004771 c = *ap->aword++;
4772 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004773 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004774 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004775 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004776 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004777}
4778
4779/*
4780 * Produce the characters from a single word (string).
4781 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004782static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004783{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004784 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004785 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004786 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004787}
4788
4789/*
4790 * Produce quoted characters from a single word (string).
4791 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004792static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004793{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004794 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004795
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004796 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004797 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004798 c = *ap->aword++;
4799 if (c)
4800 c |= QUOTE;
4801 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004802}
4803
4804/*
4805 * Return the characters from a file.
4806 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004807static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004808{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004809 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004810 char c;
4811 struct iobuf *bp = ap->afbuf;
4812
4813 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004814 i = (ap->afid != bp->id);
4815 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004816 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004817 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004818
Eric Andersen8401eea2004-08-04 19:16:54 +00004819 i = safe_read(ap->afile, bp->buf, sizeof(bp->buf));
4820 if (i <= 0) {
4821 closef(ap->afile);
4822 return 0;
4823 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004824
Eric Andersen8401eea2004-08-04 19:16:54 +00004825 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004826 bp->bufp = bp->buf;
4827 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004828 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004829
Eric Andersen8401eea2004-08-04 19:16:54 +00004830 ap->afpos++;
4831 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004832 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00004833#if ENABLE_FEATURE_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004834 if (interactive && isatty(ap->afile)) {
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004835 /* moved to G: static char filechar_cmdbuf[BUFSIZ]; */
Eric Andersen8401eea2004-08-04 19:16:54 +00004836 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004837
Eric Andersen8401eea2004-08-04 19:16:54 +00004838 while (size == 0 || position >= size) {
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004839 read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state);
4840 size = strlen(filechar_cmdbuf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004841 position = 0;
4842 }
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004843 c = filechar_cmdbuf[position];
Eric Andersen8401eea2004-08-04 19:16:54 +00004844 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004845 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004846 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004847#endif
4848 i = safe_read(ap->afile, &c, sizeof(c));
4849 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004850}
4851
4852/*
4853 * Return the characters from a here temp file.
4854 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004855static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004856{
4857 char c;
4858
Eric Andersenff9eee42001-06-29 04:57:14 +00004859 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
4860 close(ap->afile);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004861 c = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00004862 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004863 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004864}
4865
4866/*
4867 * Return the characters produced by a process (`...`).
4868 * Quote them if required, and remove any trailing newline characters.
4869 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004870static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004871{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004872 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004873
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004874 c = qgravechar(ap, iop) & ~QUOTE;
4875 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004876 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004877 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004878}
4879
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004880static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004881{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004882 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004883
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004884 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004885
4886 if (iop->xchar) {
4887 if (iop->nlcount) {
4888 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004889 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004890 }
4891 c = iop->xchar;
4892 iop->xchar = 0;
4893 } else if ((c = filechar(ap)) == '\n') {
4894 iop->nlcount = 1;
4895 while ((c = filechar(ap)) == '\n')
4896 iop->nlcount++;
4897 iop->xchar = c;
4898 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004899 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004900 iop->nlcount--;
4901 c = '\n';
4902 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004903 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004904}
4905
4906/*
4907 * Return a single command (usually the first line) from a file.
4908 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004909static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004910{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004911 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004912
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004913 c = filechar(ap);
4914 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004915 if (!multiline) {
4916 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004917 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004918 }
4919 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004920 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004921}
4922
Eric Andersenff9eee42001-06-29 04:57:14 +00004923/*
4924 * remap fd into Shell's fd space
4925 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004926static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004927{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004928 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004929 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004930 int newfd;
4931
Eric Andersen12de6cf2004-08-04 19:19:10 +00004932 DBGPRINTF(("REMAP: fd=%d, e.iofd=%d\n", fd, e.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004933
4934 if (fd < e.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004935 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004936 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004937
Eric Andersenff9eee42001-06-29 04:57:14 +00004938 do {
4939 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004940 newfd = dup(fd);
4941 fd = newfd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004942 } while (fd >= 0 && fd < e.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004943
Eric Andersen8401eea2004-08-04 19:16:54 +00004944 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004945 if (map[i])
4946 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004947
Eric Andersenff9eee42001-06-29 04:57:14 +00004948 if (fd < 0)
4949 err("too many files open in shell");
4950 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004951
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004952 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004953}
4954
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004955static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004956{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004957 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004958
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004959 i = pipe(pv);
4960 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004961 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004962 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004963}
4964
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004965static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004966{
4967 if (pv != NULL) {
4968 close(*pv++);
4969 close(*pv);
4970 }
4971}
4972
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004973
Eric Andersenff9eee42001-06-29 04:57:14 +00004974/* -------- here.c -------- */
4975
4976/*
4977 * here documents
4978 */
4979
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004980static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004981{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004982 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004983
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004984 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00004985
4986 h = (struct here *) space(sizeof(struct here));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004987 if (h == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004988 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004989
Eric Andersenff9eee42001-06-29 04:57:14 +00004990 h->h_tag = evalstr(s, DOSUB);
4991 if (h->h_tag == 0)
4992 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004993
Eric Andersenff9eee42001-06-29 04:57:14 +00004994 h->h_iop = iop;
4995 iop->io_name = 0;
4996 h->h_next = NULL;
4997 if (inhere == 0)
4998 inhere = h;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004999 else {
5000 for (lh = inhere; lh != NULL; lh = lh->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005001 if (lh->h_next == 0) {
5002 lh->h_next = h;
5003 break;
5004 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005005 }
5006 }
Eric Andersen8401eea2004-08-04 19:16:54 +00005007 iop->io_flag |= IOHERE | IOXHERE;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005008 for (s = h->h_tag; *s; s++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005009 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005010 iop->io_flag &= ~IOXHERE;
5011 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005012 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005013 }
Eric Andersenff9eee42001-06-29 04:57:14 +00005014 h->h_dosub = iop->io_flag & IOXHERE;
5015}
5016
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005017static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005018{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005019 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005020
5021 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005022
5023 /* Scan here files first leaving inhere list in place */
5024 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Eric Andersen8401eea2004-08-04 19:16:54 +00005025 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub ? 0 : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00005026
5027 /* Make inhere list active - keep list intact for scraphere */
5028 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005029 hp->h_next = acthere;
5030 acthere = inhere;
5031 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00005032 }
5033}
5034
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005035static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00005036{
5037 int tf;
5038 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005039 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00005040 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00005041 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00005042 char *thenext;
5043
Mike Frysinger02d8fa42006-05-05 20:32:31 +00005044 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00005045
Eric Andersenff9eee42001-06-29 04:57:14 +00005046 tf = mkstemp(tname);
5047 if (tf < 0)
5048 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005049
Eric Andersenff9eee42001-06-29 04:57:14 +00005050 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00005051 errpt = ev;
5052 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00005053 unlink(tname);
5054 else {
Eric Andersen8401eea2004-08-04 19:16:54 +00005055 pushio(e.iop->argp, (int (*)(struct ioarg *)) e.iop->iofn);
Eric Andersenff9eee42001-06-29 04:57:14 +00005056 e.iobase = e.iop;
5057 for (;;) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005058 if (interactive && e.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00005059#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00005060 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00005061#else
Eric Andersen8401eea2004-08-04 19:16:54 +00005062 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00005063#endif
5064 }
5065 thenext = myline;
5066 while ((c = my_getc(ec)) != '\n' && c) {
5067 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00005068 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005069 if (thenext >= &myline[LINELIM]) {
5070 c = 0;
5071 break;
5072 }
5073 *thenext++ = c;
5074 }
5075 *thenext = 0;
5076 if (strcmp(s, myline) == 0 || c == 0)
5077 break;
5078 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00005079 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00005080 }
5081 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005082 prs("here document `");
5083 prs(s);
5084 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00005085 }
5086 quitenv();
5087 }
5088 close(tf);
5089}
5090
5091/*
5092 * open here temp file.
5093 * if unquoted here, expand here temp file into second temp file.
5094 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005095static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005096{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005097 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005098 int tf;
5099
5100#if __GNUC__
5101 /* Avoid longjmp clobbering */
5102 (void) &tf;
5103#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005104 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005105 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005106
5107 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5108
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005109 hf = open(hname, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00005110 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005111 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005112
Eric Andersenff9eee42001-06-29 04:57:14 +00005113 if (xdoll) {
5114 char c;
5115 char tname[30] = ".msh_XXXXXX";
5116 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005117
Eric Andersenff9eee42001-06-29 04:57:14 +00005118 tf = mkstemp(tname);
5119 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005120 return -1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005121 errpt = ev;
5122 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005123 PUSHIO(afile, hf, herechar);
5124 setbase(e.iop);
5125 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005126 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005127 write(tf, &c, sizeof c);
5128 }
5129 quitenv();
5130 } else
5131 unlink(tname);
5132 close(tf);
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005133 tf = open(tname, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00005134 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005135 return tf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005136 }
5137 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005138}
5139
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005140static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005141{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005142 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005143
5144 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005145
5146 for (h = inhere; h != NULL; h = h->h_next) {
5147 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005148 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005149 }
5150 inhere = NULL;
5151}
5152
5153/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005154static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005155{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005156 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005157
5158 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005159
5160 hl = NULL;
5161 for (h = acthere; h != NULL; h = h->h_next)
5162 if (getarea((char *) h) >= area) {
5163 if (h->h_iop->io_name != NULL)
5164 unlink(h->h_iop->io_name);
5165 if (hl == NULL)
5166 acthere = h->h_next;
5167 else
5168 hl->h_next = h->h_next;
5169 } else
5170 hl = h;
5171}
5172
5173
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005174/* -------- sh.c -------- */
5175/*
5176 * shell
5177 */
5178
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00005179int msh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005180int msh_main(int argc, char **argv)
5181{
5182 int f;
5183 char *s;
5184 int cflag;
5185 char *name, **ap;
5186 int (*iof) (struct ioarg *);
5187
Denis Vlasenkoab801872007-12-02 08:35:37 +00005188 INIT_G();
5189
Denis Vlasenko55f30b02007-03-24 22:42:29 +00005190 sharedbuf.id = AFID_NOBUF;
5191 mainbuf.id = AFID_NOBUF;
5192 e.linep = line;
5193 elinep = line + sizeof(line) - 5;
5194
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005195#if ENABLE_FEATURE_EDITING
5196 line_input_state = new_line_input_t(FOR_SHELL);
5197#endif
5198
5199 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
5200
5201 initarea();
5202 ap = environ;
5203 if (ap != NULL) {
5204 while (*ap)
5205 assign(*ap++, !COPYV);
5206 for (ap = environ; *ap;)
5207 export(lookup(*ap++));
5208 }
5209 closeall();
5210 areanum = 1;
5211
5212 shell = lookup("SHELL");
5213 if (shell->value == null)
5214 setval(shell, (char *)DEFAULT_SHELL);
5215 export(shell);
5216
5217 homedir = lookup("HOME");
5218 if (homedir->value == null)
5219 setval(homedir, "/");
5220 export(homedir);
5221
5222 setval(lookup("$"), putn(getpid()));
5223
5224 path = lookup("PATH");
5225 if (path->value == null) {
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005226 /* Can be merged with same string elsewhere in bbox */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005227 if (geteuid() == 0)
Denis Vlasenkof5f75c52007-06-12 22:35:19 +00005228 setval(path, bb_default_root_path);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005229 else
Denis Vlasenkof5f75c52007-06-12 22:35:19 +00005230 setval(path, bb_default_path);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005231 }
5232 export(path);
5233
5234 ifs = lookup("IFS");
5235 if (ifs->value == null)
5236 setval(ifs, " \t\n");
5237
5238#ifdef MSHDEBUG
5239 mshdbg_var = lookup("MSHDEBUG");
5240 if (mshdbg_var->value == null)
5241 setval(mshdbg_var, "0");
5242#endif
5243
5244 prompt = lookup("PS1");
5245#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5246 if (prompt->value == null)
5247#endif
5248 setval(prompt, DEFAULT_USER_PROMPT);
5249 if (geteuid() == 0) {
5250 setval(prompt, DEFAULT_ROOT_PROMPT);
5251 prompt->status &= ~EXPORT;
5252 }
5253 cprompt = lookup("PS2");
5254#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5255 if (cprompt->value == null)
5256#endif
5257 setval(cprompt, "> ");
5258
5259 iof = filechar;
5260 cflag = 0;
5261 name = *argv++;
5262 if (--argc >= 1) {
5263 if (argv[0][0] == '-' && argv[0][1] != '\0') {
5264 for (s = argv[0] + 1; *s; s++)
5265 switch (*s) {
5266 case 'c':
5267 prompt->status &= ~EXPORT;
5268 cprompt->status &= ~EXPORT;
5269 setval(prompt, "");
5270 setval(cprompt, "");
5271 cflag = 1;
5272 if (--argc > 0)
5273 PUSHIO(aword, *++argv, iof = nlchar);
5274 break;
5275
5276 case 'q':
5277 qflag = SIG_DFL;
5278 break;
5279
5280 case 's':
5281 /* standard input */
5282 break;
5283
5284 case 't':
5285 prompt->status &= ~EXPORT;
5286 setval(prompt, "");
5287 iof = linechar;
5288 break;
5289
5290 case 'i':
5291 interactive++;
5292 default:
5293 if (*s >= 'a' && *s <= 'z')
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00005294 FLAG[(int) *s]++;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005295 }
5296 } else {
5297 argv--;
5298 argc++;
5299 }
5300
5301 if (iof == filechar && --argc > 0) {
5302 setval(prompt, "");
5303 setval(cprompt, "");
5304 prompt->status &= ~EXPORT;
5305 cprompt->status &= ~EXPORT;
5306
5307/* Shell is non-interactive, activate printf-based debug */
5308#ifdef MSHDEBUG
5309 mshdbg = (int) (((char) (mshdbg_var->value[0])) - '0');
5310 if (mshdbg < 0)
5311 mshdbg = 0;
5312#endif
5313 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
5314
5315 name = *++argv;
5316 if (newfile(name))
5317 exit(1); /* Exit on error */
5318 }
5319 }
5320
5321 setdash();
5322
5323 /* This won't be true if PUSHIO has been called, say from newfile() above */
5324 if (e.iop < iostack) {
5325 PUSHIO(afile, 0, iof);
5326 if (isatty(0) && isatty(1) && !cflag) {
5327 interactive++;
5328#if !ENABLE_FEATURE_SH_EXTRA_QUIET
5329#ifdef MSHDEBUG
Denis Vlasenkoca525b42007-06-13 12:27:17 +00005330 printf("\n\n%s built-in shell (msh with debug)\n", bb_banner);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005331#else
Denis Vlasenkoca525b42007-06-13 12:27:17 +00005332 printf("\n\n%s built-in shell (msh)\n", bb_banner);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005333#endif
5334 printf("Enter 'help' for a list of built-in commands.\n\n");
5335#endif
5336 }
5337 }
5338
5339 signal(SIGQUIT, qflag);
5340 if (name && name[0] == '-') {
5341 interactive++;
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005342 f = open(".profile", O_RDONLY);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005343 if (f >= 0)
5344 next(remap(f));
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005345 f = open("/etc/profile", O_RDONLY);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005346 if (f >= 0)
5347 next(remap(f));
5348 }
5349 if (interactive)
5350 signal(SIGTERM, sig);
5351
5352 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
5353 signal(SIGINT, onintr);
5354 dolv = argv;
5355 dolc = argc;
5356 dolv[0] = name;
5357 if (dolc > 1) {
5358 for (ap = ++argv; --argc > 0;) {
5359 *ap = *argv++;
5360 if (assign(*ap, !COPYV)) {
5361 dolc--; /* keyword */
5362 } else {
5363 ap++;
5364 }
5365 }
5366 }
5367 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
5368
5369 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, e.iop %p, iostack %p\n", interactive, e.iop, iostack));
5370
5371 for (;;) {
5372 if (interactive && e.iop <= iostack) {
5373#if ENABLE_FEATURE_EDITING
5374 current_prompt = prompt->value;
5375#else
5376 prs(prompt->value);
5377#endif
5378 }
5379 onecommand();
5380 /* Ensure that getenv("PATH") stays current */
5381 setenv("PATH", path->value, 1);
5382 }
5383
5384 DBGPRINTF(("MSH_MAIN: returning.\n"));
5385}
5386
5387
Eric Andersenff9eee42001-06-29 04:57:14 +00005388/*
5389 * Copyright (c) 1987,1997, Prentice Hall
5390 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005391 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005392 * Redistribution and use of the MINIX operating system in source and
5393 * binary forms, with or without modification, are permitted provided
5394 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005395 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005396 * Redistributions of source code must retain the above copyright
5397 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005398 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005399 * Redistributions in binary form must reproduce the above
5400 * copyright notice, this list of conditions and the following
5401 * disclaimer in the documentation and/or other materials provided
5402 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005403 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005404 * Neither the name of Prentice Hall nor the names of the software
5405 * authors or contributors may be used to endorse or promote
5406 * products derived from this software without specific prior
5407 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005408 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005409 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5410 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5411 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5412 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5413 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5414 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5415 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5416 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5417 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5418 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5419 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5420 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5421 *
5422 */