blob: dffacf02adac12befb6f19d093b60b185f532ce5 [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 */
Denis Vlasenko95cb3262007-04-09 03:06:34 +000015#include <sys/times.h>
16#include <setjmp.h>
Denis Vlasenko55f30b02007-03-24 22:42:29 +000017
Mike Frysinger67a32ad2007-03-09 08:25:24 +000018#ifdef STANDALONE
19# ifndef _GNU_SOURCE
20# define _GNU_SOURCE
21# endif
Mike Frysinger67a32ad2007-03-09 08:25:24 +000022# include <sys/types.h>
23# include <sys/stat.h>
24# include <sys/wait.h>
25# include <signal.h>
26# include <stdio.h>
27# include <stdlib.h>
28# include <unistd.h>
29# include <string.h>
30# include <errno.h>
31# include <dirent.h>
32# include <fcntl.h>
33# include <ctype.h>
34# include <assert.h>
35# define bb_dev_null "/dev/null"
36# define DEFAULT_SHELL "/proc/self/exe"
Denis Vlasenkoca525b42007-06-13 12:27:17 +000037# define bb_banner "busybox standalone"
Denis Vlasenko80d14be2007-04-10 23:03:30 +000038# define ENABLE_FEATURE_SH_STANDALONE 0
Mike Frysinger67a32ad2007-03-09 08:25:24 +000039# define bb_msg_memory_exhausted "memory exhausted"
40# define xmalloc(size) malloc(size)
41# define msh_main(argc,argv) main(argc,argv)
42# define safe_read(fd,buf,count) read(fd,buf,count)
Denis Vlasenkoe376d452008-02-20 22:23:24 +000043# define nonblock_safe_read(fd,buf,count) read(fd,buf,count)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000044# define NOT_LONE_DASH(s) ((s)[0] != '-' || (s)[1])
45# define LONE_CHAR(s,c) ((s)[0] == (c) && !(s)[1])
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +000046# define NORETURN __attribute__ ((__noreturn__))
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000047static int find_applet_by_name(const char *applet)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000048{
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000049 return -1;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000050}
Denis Vlasenko10457b92007-03-27 22:01:31 +000051static char *utoa_to_buf(unsigned n, char *buf, unsigned buflen)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000052{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000053 unsigned i, out, res;
54 assert(sizeof(unsigned) == 4);
55 if (buflen) {
56 out = 0;
57 for (i = 1000000000; i; i /= 10) {
58 res = n / i;
59 if (res || out || i == 1) {
Denis Vlasenko4b924f32007-05-30 00:29:55 +000060 if (!--buflen) break;
61 out++;
62 n -= res*i;
63 *buf++ = '0' + res;
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000064 }
65 }
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000066 }
Denis Vlasenko10457b92007-03-27 22:01:31 +000067 return buf;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000068}
Denis Vlasenko10457b92007-03-27 22:01:31 +000069static char *itoa_to_buf(int n, char *buf, unsigned buflen)
Mike Frysinger67a32ad2007-03-09 08:25:24 +000070{
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000071 if (buflen && n < 0) {
72 n = -n;
73 *buf++ = '-';
74 buflen--;
75 }
Denis Vlasenko10457b92007-03-27 22:01:31 +000076 return utoa_to_buf((unsigned)n, buf, buflen);
Mike Frysinger67a32ad2007-03-09 08:25:24 +000077}
78static char local_buf[12];
79static char *itoa(int n)
80{
Denis Vlasenko10457b92007-03-27 22:01:31 +000081 *(itoa_to_buf(n, local_buf, sizeof(local_buf))) = '\0';
Denis Vlasenkoc86e0522007-03-20 11:30:28 +000082 return local_buf;
Mike Frysinger67a32ad2007-03-09 08:25:24 +000083}
84#else
Denis Vlasenko1aa7e472007-11-28 06:49:03 +000085# include "busybox.h" /* for applet_names */
Mike Frysinger67a32ad2007-03-09 08:25:24 +000086#endif
Eric Andersenff9eee42001-06-29 04:57:14 +000087
Denis Vlasenko7e497522008-02-12 09:51:03 +000088//#define MSHDEBUG 4
Eric Andersen12de6cf2004-08-04 19:19:10 +000089
90#ifdef MSHDEBUG
Denis Vlasenko509697f2008-03-02 12:49:39 +000091static int mshdbg = MSHDEBUG;
Eric Andersen12de6cf2004-08-04 19:19:10 +000092
Denis Vlasenkoed9d6212008-06-09 07:44:19 +000093#define DBGPRINTF(x) if (mshdbg > 0) printf x
94#define DBGPRINTF0(x) if (mshdbg > 0) printf x
95#define DBGPRINTF1(x) if (mshdbg > 1) printf x
96#define DBGPRINTF2(x) if (mshdbg > 2) printf x
97#define DBGPRINTF3(x) if (mshdbg > 3) printf x
98#define DBGPRINTF4(x) if (mshdbg > 4) printf x
99#define DBGPRINTF5(x) if (mshdbg > 5) printf x
100#define DBGPRINTF6(x) if (mshdbg > 6) printf x
101#define DBGPRINTF7(x) if (mshdbg > 7) printf x
102#define DBGPRINTF8(x) if (mshdbg > 8) printf x
103#define DBGPRINTF9(x) if (mshdbg > 9) printf x
Eric Andersen12de6cf2004-08-04 19:19:10 +0000104
Denis Vlasenko509697f2008-03-02 12:49:39 +0000105static int mshdbg_rc = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000106
Denis Vlasenko51742f42007-04-12 00:32:05 +0000107#define RCPRINTF(x) if (mshdbg_rc) printf x
Eric Andersen12de6cf2004-08-04 19:19:10 +0000108
109#else
110
111#define DBGPRINTF(x)
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000112#define DBGPRINTF0(x) ((void)0)
113#define DBGPRINTF1(x) ((void)0)
114#define DBGPRINTF2(x) ((void)0)
115#define DBGPRINTF3(x) ((void)0)
116#define DBGPRINTF4(x) ((void)0)
117#define DBGPRINTF5(x) ((void)0)
118#define DBGPRINTF6(x) ((void)0)
119#define DBGPRINTF7(x) ((void)0)
120#define DBGPRINTF8(x) ((void)0)
121#define DBGPRINTF9(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000122
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000123#define RCPRINTF(x) ((void)0)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000124
Denis Vlasenkoed9d6212008-06-09 07:44:19 +0000125#endif /* MSHDEBUG */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000126
127
Denis Vlasenko38f63192007-01-22 09:03:07 +0000128#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
Mike Frysinger2a131752006-06-06 06:26:12 +0000129# define DEFAULT_ROOT_PROMPT "\\u:\\w> "
130# define DEFAULT_USER_PROMPT "\\u:\\w$ "
131#else
132# define DEFAULT_ROOT_PROMPT "# "
133# define DEFAULT_USER_PROMPT "$ "
134#endif
135
136
Eric Andersenff9eee42001-06-29 04:57:14 +0000137/* -------- sh.h -------- */
138/*
139 * shell
140 */
141
Denis Vlasenkoed9d6212008-06-09 07:44:19 +0000142#define LINELIM 2100
143#define NPUSH 8 /* limit to input nesting */
Eric Andersenff9eee42001-06-29 04:57:14 +0000144
Eric Andersen392947c2002-12-11 07:42:46 +0000145#undef NOFILE
Denis Vlasenkoed9d6212008-06-09 07:44:19 +0000146#define NOFILE 20 /* Number of open files */
147#define NUFILE 10 /* Number of user-accessible files */
148#define FDBASE 10 /* First file usable by Shell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000149
150/*
151 * values returned by wait
152 */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000153#define WAITSIG(s) ((s) & 0177)
154#define WAITVAL(s) (((s) >> 8) & 0377)
155#define WAITCORE(s) (((s) & 0200) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +0000156
157/*
Eric Andersenaff114c2004-04-14 17:51:38 +0000158 * library and system definitions
Eric Andersenff9eee42001-06-29 04:57:14 +0000159 */
Denis Vlasenkoed9d6212008-06-09 07:44:19 +0000160typedef void xint; /* base type of jmp_buf, for not broken compilers */
Eric Andersenff9eee42001-06-29 04:57:14 +0000161
162/*
163 * shell components
164 */
Eric Andersenff9eee42001-06-29 04:57:14 +0000165#define NOBLOCK ((struct op *)NULL)
166#define NOWORD ((char *)NULL)
167#define NOWORDS ((char **)NULL)
168#define NOPIPE ((int *)NULL)
169
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000170/*
171 * redirection
172 */
173struct ioword {
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +0000174 smallint io_flag; /* action (below) */
175 int io_fd; /* fd affected */
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000176 char *io_name; /* file name */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000177};
178
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000179#define IOREAD 1 /* < */
180#define IOHERE 2 /* << (here file) */
181#define IOWRITE 4 /* > */
182#define IOCAT 8 /* >> */
183#define IOXHERE 16 /* ${}, ` in << */
184#define IODUP 32 /* >&digit */
185#define IOCLOSE 64 /* >&- */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000186
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +0000187#define IODEFAULT (-1) /* "default" IO fd */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000188
189
Eric Andersenff9eee42001-06-29 04:57:14 +0000190/*
191 * Description of a command or an operation on commands.
192 * Might eventually use a union.
193 */
194struct op {
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +0000195 smallint op_type; /* operation type, see Txxxx below */
Denis Vlasenko509697f2008-03-02 12:49:39 +0000196 char **op_words; /* arguments to a command */
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000197 struct ioword **ioact; /* IO actions (eg, < > >>) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000198 struct op *left;
199 struct op *right;
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000200 char *str; /* identifier for case and for */
Eric Andersenff9eee42001-06-29 04:57:14 +0000201};
202
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000203#define TCOM 1 /* command */
204#define TPAREN 2 /* (c-list) */
205#define TPIPE 3 /* a | b */
206#define TLIST 4 /* a [&;] b */
207#define TOR 5 /* || */
208#define TAND 6 /* && */
209#define TFOR 7
210#define TDO 8
211#define TCASE 9
212#define TIF 10
213#define TWHILE 11
214#define TUNTIL 12
215#define TELIF 13
216#define TPAT 14 /* pattern in case */
217#define TBRACE 15 /* {c-list} */
218#define TASYNC 16 /* c & */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000219/* Added to support "." file expansion */
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000220#define TDOT 17
Eric Andersen12de6cf2004-08-04 19:19:10 +0000221
222/* Strings for names to make debug easier */
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000223#ifdef MSHDEBUG
Denis Vlasenkoe27f1562007-01-01 06:00:38 +0000224static const char *const T_CMD_NAMES[] = {
Eric Andersen12de6cf2004-08-04 19:19:10 +0000225 "PLACEHOLDER",
226 "TCOM",
227 "TPAREN",
228 "TPIPE",
229 "TLIST",
230 "TOR",
231 "TAND",
232 "TFOR",
233 "TDO",
234 "TCASE",
235 "TIF",
236 "TWHILE",
237 "TUNTIL",
238 "TELIF",
239 "TPAT",
240 "TBRACE",
241 "TASYNC",
242 "TDOT",
243};
"Vladimir N. Oleynik"ac973172005-09-22 14:38:17 +0000244#endif
Eric Andersenff9eee42001-06-29 04:57:14 +0000245
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000246#define AREASIZE (90000)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000247
Eric Andersenff9eee42001-06-29 04:57:14 +0000248/*
249 * flags to control evaluation of words
250 */
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000251#define DOSUB 1 /* interpret $, `, and quotes */
252#define DOBLANK 2 /* perform blank interpretation */
253#define DOGLOB 4 /* interpret [?* */
254#define DOKEY 8 /* move words with `=' to 2nd arg. list */
255#define DOTRIM 16 /* trim resulting string */
Eric Andersenff9eee42001-06-29 04:57:14 +0000256
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000257#define DOALL (DOSUB|DOBLANK|DOGLOB|DOKEY|DOTRIM)
Eric Andersenff9eee42001-06-29 04:57:14 +0000258
Eric Andersenff9eee42001-06-29 04:57:14 +0000259
Eric Andersen8401eea2004-08-04 19:16:54 +0000260struct brkcon {
261 jmp_buf brkpt;
262 struct brkcon *nextlev;
263};
Eric Andersenff9eee42001-06-29 04:57:14 +0000264
Eric Andersen12de6cf2004-08-04 19:19:10 +0000265
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000266static smallint trapset; /* trap pending (signal number) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000267
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000268static smallint yynerrs; /* yacc (flag) */
Eric Andersenff9eee42001-06-29 04:57:14 +0000269
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000270/* moved to G: static char line[LINELIM]; */
Eric Andersenff9eee42001-06-29 04:57:14 +0000271
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000272#if ENABLE_FEATURE_EDITING
273static char *current_prompt;
274static line_input_t *line_input_state;
275#endif
276
Eric Andersen12de6cf2004-08-04 19:19:10 +0000277
Eric Andersenff9eee42001-06-29 04:57:14 +0000278/*
279 * other functions
280 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000281static const char *rexecve(char *c, char **v, char **envp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000282static char *evalstr(char *cp, int f);
283static char *putn(int n);
Eric Andersen8401eea2004-08-04 19:16:54 +0000284static char *unquote(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000285static int rlookup(char *n);
286static struct wdblock *glob(char *cp, struct wdblock *wb);
287static int my_getc(int ec);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000288static int subgetc(char ec, int quoted);
Eric Andersenfd7a4c82004-09-02 23:13:10 +0000289static char **makenv(int all, struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000290static char **eval(char **ap, int f);
291static int setstatus(int s);
292static int waitfor(int lastpid, int canintr);
Eric Andersenff9eee42001-06-29 04:57:14 +0000293
Eric Andersen8401eea2004-08-04 19:16:54 +0000294static void onintr(int s); /* SIGINT handler */
Eric Andersenff9eee42001-06-29 04:57:14 +0000295
Eric Andersen8401eea2004-08-04 19:16:54 +0000296static int newenv(int f);
297static void quitenv(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000298static void next(int f);
299static void setdash(void);
300static void onecommand(void);
301static void runtrap(int i);
Eric Andersenff9eee42001-06-29 04:57:14 +0000302
Eric Andersen12de6cf2004-08-04 19:19:10 +0000303
Eric Andersenff9eee42001-06-29 04:57:14 +0000304/* -------- area stuff -------- */
305
Denis Vlasenko5f9468e2007-04-14 13:22:09 +0000306#define REGSIZE sizeof(struct region)
307#define GROWBY (256)
308/* #define SHRINKBY (64) */
309#undef SHRINKBY
310#define FREE (32767)
311#define BUSY (0)
312#define ALIGN (sizeof(int)-1)
Eric Andersenff9eee42001-06-29 04:57:14 +0000313
314
315struct region {
Eric Andersen8401eea2004-08-04 19:16:54 +0000316 struct region *next;
317 int area;
Eric Andersenff9eee42001-06-29 04:57:14 +0000318};
319
320
Eric Andersenff9eee42001-06-29 04:57:14 +0000321/* -------- grammar stuff -------- */
322typedef union {
Eric Andersen8401eea2004-08-04 19:16:54 +0000323 char *cp;
324 char **wp;
325 int i;
326 struct op *o;
Eric Andersenff9eee42001-06-29 04:57:14 +0000327} YYSTYPE;
Eric Andersen8401eea2004-08-04 19:16:54 +0000328
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000329#define WORD 256
330#define LOGAND 257
331#define LOGOR 258
332#define BREAK 259
333#define IF 260
334#define THEN 261
335#define ELSE 262
336#define ELIF 263
337#define FI 264
338#define CASE 265
339#define ESAC 266
340#define FOR 267
341#define WHILE 268
342#define UNTIL 269
343#define DO 270
344#define DONE 271
345#define IN 272
Eric Andersen12de6cf2004-08-04 19:19:10 +0000346/* Added for "." file expansion */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000347#define DOT 273
Eric Andersen12de6cf2004-08-04 19:19:10 +0000348
Eric Andersenff9eee42001-06-29 04:57:14 +0000349#define YYERRCODE 300
350
351/* flags to yylex */
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000352#define CONTIN 01 /* skip new lines to complete command */
Eric Andersenff9eee42001-06-29 04:57:14 +0000353
Eric Andersen8401eea2004-08-04 19:16:54 +0000354static struct op *pipeline(int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000355static struct op *andor(void);
356static struct op *c_list(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000357static int synio(int cf);
358static void musthave(int c, int cf);
Eric Andersenff9eee42001-06-29 04:57:14 +0000359static struct op *simple(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000360static struct op *nested(int type, int mark);
361static struct op *command(int cf);
362static struct op *dogroup(int onlydone);
Eric Andersenff9eee42001-06-29 04:57:14 +0000363static struct op *thenpart(void);
364static struct op *elsepart(void);
365static struct op *caselist(void);
366static struct op *casepart(void);
367static char **pattern(void);
368static char **wordlist(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000369static struct op *list(struct op *t1, struct op *t2);
370static struct op *block(int type, struct op *t1, struct op *t2, char **wp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000371static struct op *newtp(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000372static struct op *namelist(struct op *t);
Eric Andersenff9eee42001-06-29 04:57:14 +0000373static char **copyw(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000374static void word(char *cp);
Eric Andersenff9eee42001-06-29 04:57:14 +0000375static struct ioword **copyio(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000376static struct ioword *io(int u, int f, char *cp);
Eric Andersen8401eea2004-08-04 19:16:54 +0000377static int yylex(int cf);
378static int collect(int c, int c1);
379static int dual(int c);
380static void diag(int ec);
381static char *tree(unsigned size);
Eric Andersenff9eee42001-06-29 04:57:14 +0000382
383/* -------- var.h -------- */
384
Eric Andersen8401eea2004-08-04 19:16:54 +0000385struct var {
386 char *value;
387 char *name;
388 struct var *next;
389 char status;
Eric Andersenff9eee42001-06-29 04:57:14 +0000390};
Eric Andersenff9eee42001-06-29 04:57:14 +0000391
Eric Andersen8401eea2004-08-04 19:16:54 +0000392#define COPYV 1 /* flag to setval, suggesting copy */
393#define RONLY 01 /* variable is read-only */
394#define EXPORT 02 /* variable is to be exported */
395#define GETCELL 04 /* name & value space was got with getcell */
Eric Andersenff9eee42001-06-29 04:57:14 +0000396
Eric Andersen8401eea2004-08-04 19:16:54 +0000397static int yyparse(void);
Eric Andersen8401eea2004-08-04 19:16:54 +0000398
Eric Andersen12de6cf2004-08-04 19:19:10 +0000399
Eric Andersenff9eee42001-06-29 04:57:14 +0000400/* -------- io.h -------- */
401/* io buffer */
402struct iobuf {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000403 unsigned id; /* buffer id */
404 char buf[512]; /* buffer */
405 char *bufp; /* pointer into buffer */
406 char *ebufp; /* pointer to end of buffer */
Eric Andersenff9eee42001-06-29 04:57:14 +0000407};
408
409/* possible arguments to an IO function */
410struct ioarg {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000411 const char *aword;
Eric Andersen8401eea2004-08-04 19:16:54 +0000412 char **awordlist;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000413 int afile; /* file descriptor */
414 unsigned afid; /* buffer id */
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000415 off_t afpos; /* file position */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000416 struct iobuf *afbuf; /* buffer for this file */
Eric Andersenff9eee42001-06-29 04:57:14 +0000417};
Eric Andersen8401eea2004-08-04 19:16:54 +0000418
Eric Andersenff9eee42001-06-29 04:57:14 +0000419/* an input generator's state */
Eric Andersen8401eea2004-08-04 19:16:54 +0000420struct io {
421 int (*iofn) (struct ioarg *, struct io *);
422 struct ioarg *argp;
423 int peekc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000424 char prev; /* previous character read by readc() */
425 char nlcount; /* for `'s */
426 char xchar; /* for `'s */
427 char task; /* reason for pushed IO */
Eric Andersenff9eee42001-06-29 04:57:14 +0000428};
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000429/* ->task: */
430#define XOTHER 0 /* none of the below */
431#define XDOLL 1 /* expanding ${} */
432#define XGRAVE 2 /* expanding `'s */
433#define XIO 3 /* file IO */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000434
435
436/*
Eric Andersenff9eee42001-06-29 04:57:14 +0000437 * input generators for IO structure
438 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000439static int nlchar(struct ioarg *ap);
440static int strchar(struct ioarg *ap);
441static int qstrchar(struct ioarg *ap);
442static int filechar(struct ioarg *ap);
443static int herechar(struct ioarg *ap);
444static int linechar(struct ioarg *ap);
445static int gravechar(struct ioarg *ap, struct io *iop);
446static int qgravechar(struct ioarg *ap, struct io *iop);
447static int dolchar(struct ioarg *ap);
448static int wdchar(struct ioarg *ap);
449static void scraphere(void);
450static void freehere(int area);
451static void gethere(void);
452static void markhere(char *s, struct ioword *iop);
453static int herein(char *hname, int xdoll);
454static int run(struct ioarg *argp, int (*f) (struct ioarg *));
Eric Andersenff9eee42001-06-29 04:57:14 +0000455
Eric Andersen12de6cf2004-08-04 19:19:10 +0000456
Eric Andersen8401eea2004-08-04 19:16:54 +0000457static int eofc(void);
458static int readc(void);
459static void unget(int c);
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +0000460static void ioecho(char c);
Eric Andersenff9eee42001-06-29 04:57:14 +0000461
Eric Andersen12de6cf2004-08-04 19:19:10 +0000462
Eric Andersenff9eee42001-06-29 04:57:14 +0000463/*
464 * IO control
465 */
Eric Andersen8401eea2004-08-04 19:16:54 +0000466static void pushio(struct ioarg *argp, int (*f) (struct ioarg *));
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000467#define PUSHIO(what,arg,gen) ((temparg.what = (arg)), pushio(&temparg,(gen)))
Eric Andersen8401eea2004-08-04 19:16:54 +0000468static int remap(int fd);
469static int openpipe(int *pv);
470static void closepipe(int *pv);
471static struct io *setbase(struct io *ip);
Eric Andersenff9eee42001-06-29 04:57:14 +0000472
Eric Andersenff9eee42001-06-29 04:57:14 +0000473/* -------- word.h -------- */
474
Eric Andersen8401eea2004-08-04 19:16:54 +0000475#define NSTART 16 /* default number of words to allow for initially */
Eric Andersenff9eee42001-06-29 04:57:14 +0000476
Eric Andersen8401eea2004-08-04 19:16:54 +0000477struct wdblock {
478 short w_bsize;
479 short w_nword;
Eric Andersenff9eee42001-06-29 04:57:14 +0000480 /* bounds are arbitrary */
Eric Andersen8401eea2004-08-04 19:16:54 +0000481 char *w_words[1];
Eric Andersenff9eee42001-06-29 04:57:14 +0000482};
483
Eric Andersen8401eea2004-08-04 19:16:54 +0000484static struct wdblock *addword(char *wd, struct wdblock *wb);
485static struct wdblock *newword(int nw);
486static char **getwords(struct wdblock *wb);
Eric Andersenff9eee42001-06-29 04:57:14 +0000487
Eric Andersenff9eee42001-06-29 04:57:14 +0000488/* -------- misc stuff -------- */
489
Denis Vlasenkofe218832008-03-01 09:35:39 +0000490static int dolabel(struct op *t, char **args);
491static int dohelp(struct op *t, char **args);
492static int dochdir(struct op *t, char **args);
493static int doshift(struct op *t, char **args);
494static int dologin(struct op *t, char **args);
495static int doumask(struct op *t, char **args);
496static int doexec(struct op *t, char **args);
497static int dodot(struct op *t, char **args);
498static int dowait(struct op *t, char **args);
499static int doread(struct op *t, char **args);
500static int doeval(struct op *t, char **args);
501static int dotrap(struct op *t, char **args);
502static int dobreak(struct op *t, char **args);
503static int doexit(struct op *t, char **args);
504static int doexport(struct op *t, char **args);
505static int doreadonly(struct op *t, char **args);
506static int doset(struct op *t, char **args);
507static int dotimes(struct op *t, char **args);
508static int docontinue(struct op *t, char **args);
509
Denis Vlasenko7e497522008-02-12 09:51:03 +0000510static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp);
511static int execute(struct op *t, int *pin, int *pout, int no_fork);
Eric Andersen8401eea2004-08-04 19:16:54 +0000512static int iosetup(struct ioword *iop, int pipein, int pipeout);
Eric Andersen8401eea2004-08-04 19:16:54 +0000513static void brkset(struct brkcon *bc);
Eric Andersen8401eea2004-08-04 19:16:54 +0000514static int getsig(char *s);
515static void setsig(int n, sighandler_t f);
516static int getn(char *as);
Eric Andersen8401eea2004-08-04 19:16:54 +0000517static int brkcontin(char *cp, int val);
Eric Andersen8401eea2004-08-04 19:16:54 +0000518static void rdexp(char **wp, void (*f) (struct var *), int key);
519static void badid(char *s);
Eric Andersen8401eea2004-08-04 19:16:54 +0000520static void varput(char *s, int out);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000521static int expand(const char *cp, struct wdblock **wbp, int f);
Eric Andersen8401eea2004-08-04 19:16:54 +0000522static char *blank(int f);
523static int dollar(int quoted);
524static int grave(int quoted);
525static void globname(char *we, char *pp);
526static char *generate(char *start1, char *end1, char *middle, char *end);
527static int anyspcl(struct wdblock *wb);
Eric Andersen8401eea2004-08-04 19:16:54 +0000528static void readhere(char **name, char *s, int ec);
Eric Andersen8401eea2004-08-04 19:16:54 +0000529static int xxchar(struct ioarg *ap);
Eric Andersenff9eee42001-06-29 04:57:14 +0000530
Eric Andersen8401eea2004-08-04 19:16:54 +0000531struct here {
532 char *h_tag;
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000533 char h_dosub;
Eric Andersen8401eea2004-08-04 19:16:54 +0000534 struct ioword *h_iop;
535 struct here *h_next;
Eric Andersenff9eee42001-06-29 04:57:14 +0000536};
537
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000538static const char *const signame[] = {
Eric Andersenff9eee42001-06-29 04:57:14 +0000539 "Signal 0",
540 "Hangup",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000541 NULL, /* interrupt */
Eric Andersenff9eee42001-06-29 04:57:14 +0000542 "Quit",
543 "Illegal instruction",
544 "Trace/BPT trap",
545 "Abort",
546 "Bus error",
547 "Floating Point Exception",
548 "Killed",
549 "SIGUSR1",
550 "SIGSEGV",
551 "SIGUSR2",
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000552 NULL, /* broken pipe */
Eric Andersenff9eee42001-06-29 04:57:14 +0000553 "Alarm clock",
Denis Vlasenko6ca409e2007-08-12 20:58:27 +0000554 "Terminated"
Eric Andersenff9eee42001-06-29 04:57:14 +0000555};
Eric Andersen8401eea2004-08-04 19:16:54 +0000556
Denis Vlasenko80b8b392007-06-25 10:55:35 +0000557
Denis Vlasenkofe218832008-03-01 09:35:39 +0000558typedef int (*builtin_func_ptr)(struct op *, char **);
Denis Vlasenko7e497522008-02-12 09:51:03 +0000559
Eric Andersen1c039232001-07-07 00:05:55 +0000560struct builtincmd {
561 const char *name;
Denis Vlasenko7e497522008-02-12 09:51:03 +0000562 builtin_func_ptr builtinfunc;
Eric Andersenff9eee42001-06-29 04:57:14 +0000563};
Denis Vlasenko7e497522008-02-12 09:51:03 +0000564
Eric Andersen8401eea2004-08-04 19:16:54 +0000565static const struct builtincmd builtincmds[] = {
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000566 { "." , dodot },
567 { ":" , dolabel },
568 { "break" , dobreak },
569 { "cd" , dochdir },
570 { "continue", docontinue },
571 { "eval" , doeval },
572 { "exec" , doexec },
573 { "exit" , doexit },
574 { "export" , doexport },
575 { "help" , dohelp },
576 { "login" , dologin },
577 { "newgrp" , dologin },
578 { "read" , doread },
579 { "readonly", doreadonly },
580 { "set" , doset },
581 { "shift" , doshift },
582 { "times" , dotimes },
583 { "trap" , dotrap },
584 { "umask" , doumask },
585 { "wait" , dowait },
586 { NULL , NULL },
Eric Andersenff9eee42001-06-29 04:57:14 +0000587};
588
Denis Vlasenko68404f12008-03-17 09:00:54 +0000589static struct op *dowholefile(int /*, int*/);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000590
Eric Andersen12de6cf2004-08-04 19:19:10 +0000591
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000592/* Globals */
Eric Andersen8401eea2004-08-04 19:16:54 +0000593static char **dolv;
594static int dolc;
Denis Vlasenko447bd662008-05-30 22:28:32 +0000595static uint8_t exstat;
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000596static smallint gflg; /* (seems to be a parse error indicator) */
597static smallint interactive; /* Is this an interactive shell */
598static smallint execflg;
599static smallint isbreak; /* "break" statement was seen */
600static int multiline; /* '\n' changed to ';' (counter) */
601static struct op *outtree; /* result from parser */
Eric Andersen8401eea2004-08-04 19:16:54 +0000602static xint *failpt;
603static xint *errpt;
604static struct brkcon *brklist;
Eric Andersen8401eea2004-08-04 19:16:54 +0000605static struct wdblock *wdlist;
606static struct wdblock *iolist;
Eric Andersen12de6cf2004-08-04 19:19:10 +0000607
608#ifdef MSHDEBUG
609static struct var *mshdbg_var;
610#endif
Eric Andersen8401eea2004-08-04 19:16:54 +0000611static struct var *vlist; /* dictionary */
612static struct var *homedir; /* home directory */
613static struct var *prompt; /* main prompt */
614static struct var *cprompt; /* continuation prompt */
615static struct var *path; /* search path for commands */
616static struct var *shell; /* shell to interpret command files */
617static struct var *ifs; /* field separators */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000618
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000619static int areanum; /* current allocation area */
Denis Vlasenko648b44f2008-02-12 06:04:06 +0000620static smallint intr; /* interrupt pending (bool) */
621static smallint heedint = 1; /* heed interrupt signals (bool) */
Eric Andersen8401eea2004-08-04 19:16:54 +0000622static int inparse;
Denis Vlasenko95cb3262007-04-09 03:06:34 +0000623static char *null = (char*)""; /* null value for variable */
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000624static void (*qflag)(int) = SIG_IGN;
Eric Andersen8401eea2004-08-04 19:16:54 +0000625static int startl;
626static int peeksym;
627static int nlseen;
628static int iounit = IODEFAULT;
629static YYSTYPE yylval;
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000630static char *elinep; /* done in main(): = line + sizeof(line) - 5 */
Eric Andersen12de6cf2004-08-04 19:19:10 +0000631
Denis Vlasenko00ccf952007-02-01 01:39:24 +0000632static struct here *inhere; /* list of hear docs while parsing */
633static struct here *acthere; /* list of active here documents */
634static struct region *areabot; /* bottom of area */
635static struct region *areatop; /* top of area */
636static struct region *areanxt; /* starting point of scan */
Eric Andersen8401eea2004-08-04 19:16:54 +0000637static void *brktop;
638static void *brkaddr;
Eric Andersenff9eee42001-06-29 04:57:14 +0000639
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000640#define AFID_NOBUF (~0)
641#define AFID_ID 0
642
643
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000644/*
645 * parsing & execution environment
646 */
647struct env {
648 char *linep;
649 struct io *iobase;
650 struct io *iop;
651 xint *errpt; /* void * */
652 int iofd;
653 struct env *oenv;
654};
655
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000656
657struct globals {
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000658 struct env global_env;
659 struct ioarg temparg; // = { .afid = AFID_NOBUF }; /* temporary for PUSHIO */
660 unsigned bufid; // = AFID_ID; /* buffer id counter */
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000661 char ourtrap[_NSIG + 1];
662 char *trap[_NSIG + 1];
663 struct iobuf sharedbuf; /* in main(): set to { AFID_NOBUF } */
664 struct iobuf mainbuf; /* in main(): set to { AFID_NOBUF } */
665 struct ioarg ioargstack[NPUSH];
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000666 /*
667 * flags:
668 * -e: quit on error
669 * -k: look for name=value everywhere on command line
670 * -n: no execution
671 * -t: exit after reading and executing one command
672 * -v: echo as read
673 * -x: trace
674 * -u: unset variables net diagnostic
675 */
676 char flags['z' - 'a' + 1];
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000677 char filechar_cmdbuf[BUFSIZ];
678 char line[LINELIM];
679 char child_cmd[LINELIM];
Denis Vlasenkoab801872007-12-02 08:35:37 +0000680
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000681 struct io iostack[NPUSH];
682
Denis Vlasenkoab801872007-12-02 08:35:37 +0000683 char grave__var_name[LINELIM];
684 char grave__alt_value[LINELIM];
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000685};
686
687#define G (*ptr_to_globals)
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000688#define global_env (G.global_env )
689#define temparg (G.temparg )
690#define bufid (G.bufid )
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000691#define ourtrap (G.ourtrap )
692#define trap (G.trap )
693#define sharedbuf (G.sharedbuf )
694#define mainbuf (G.mainbuf )
695#define ioargstack (G.ioargstack )
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000696/* this looks weird, but is OK ... we index FLAG with 'a'...'z' */
697#define FLAG (G.flags - 'a' )
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000698#define filechar_cmdbuf (G.filechar_cmdbuf)
699#define line (G.line )
700#define child_cmd (G.child_cmd )
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000701#define iostack (G.iostack )
Denis Vlasenkoab801872007-12-02 08:35:37 +0000702#define INIT_G() do { \
Denis Vlasenko574f2f42008-02-27 18:41:59 +0000703 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000704 global_env.linep = line; \
705 global_env.iobase = iostack; \
706 global_env.iop = iostack - 1; \
707 global_env.iofd = FDBASE; \
708 temparg.afid = AFID_NOBUF; \
709 bufid = AFID_ID; \
Denis Vlasenkoab801872007-12-02 08:35:37 +0000710} while (0)
Denis Vlasenko55f30b02007-03-24 22:42:29 +0000711
712
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000713/* in substitution */
714#define INSUB() (global_env.iop->task == XGRAVE || global_env.iop->task == XDOLL)
715
716#define RUN(what, arg, gen) ((temparg.what = (arg)), run(&temparg, (gen)))
717
Eric Andersen12de6cf2004-08-04 19:19:10 +0000718#ifdef MSHDEBUG
Denis Vlasenko509697f2008-03-02 12:49:39 +0000719static void print_tree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +0000720{
721 if (head == NULL) {
722 DBGPRINTF(("PRINT_TREE: no tree\n"));
723 return;
724 }
725
Denis Vlasenkoed9d6212008-06-09 07:44:19 +0000726 DBGPRINTF(("NODE: %p, left %p, right %p\n", head, head->left,
Eric Andersen12de6cf2004-08-04 19:19:10 +0000727 head->right));
728
729 if (head->left)
730 print_tree(head->left);
731
732 if (head->right)
733 print_tree(head->right);
Eric Andersen12de6cf2004-08-04 19:19:10 +0000734}
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000735#endif /* MSHDEBUG */
736
737
738/*
739 * IO functions
740 */
741static void prs(const char *s)
742{
743 if (*s)
Denis Vlasenko73c571a2009-03-09 00:12:37 +0000744 xwrite_str(STDERR_FILENO, s);
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000745}
746
747static void prn(unsigned u)
748{
749 prs(itoa(u));
750}
751
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000752static void echo(char **wp)
753{
754 int i;
755
756 prs("+");
757 for (i = 0; wp[i]; i++) {
758 if (i)
759 prs(" ");
760 prs(wp[i]);
761 }
762 prs("\n");
763}
764
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000765static void closef(int i)
766{
767 if (i > 2)
768 close(i);
769}
770
771static void closeall(void)
772{
773 int u;
774
775 for (u = NUFILE; u < NOFILE;)
776 close(u++);
777}
Eric Andersen12de6cf2004-08-04 19:19:10 +0000778
Eric Andersenff9eee42001-06-29 04:57:14 +0000779
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000780/* fail but return to process next command */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000781static void fail(void) NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000782static void fail(void)
783{
784 longjmp(failpt, 1);
785 /* NOTREACHED */
786}
Eric Andersenff9eee42001-06-29 04:57:14 +0000787
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000788/* abort shell (or fail in subshell) */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000789static void leave(void) NORETURN;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000790static void leave(void)
791{
792 DBGPRINTF(("LEAVE: leave called!\n"));
793
794 if (execflg)
795 fail();
796 scraphere();
797 freehere(1);
798 runtrap(0);
799 _exit(exstat);
800 /* NOTREACHED */
801}
802
803static void warn(const char *s)
804{
805 if (*s) {
806 prs(s);
Denis Vlasenko447bd662008-05-30 22:28:32 +0000807 if (!exstat)
808 exstat = 255;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000809 }
810 prs("\n");
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000811 if (FLAG['e'])
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000812 leave();
813}
814
815static void err(const char *s)
816{
817 warn(s);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +0000818 if (FLAG['n'])
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000819 return;
820 if (!interactive)
821 leave();
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000822 if (global_env.errpt)
823 longjmp(global_env.errpt, 1);
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000824 closeall();
Denis Vlasenkoc794c512007-12-16 17:21:29 +0000825 global_env.iop = global_env.iobase = iostack;
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000826}
827
Denis Vlasenko6b50f732007-02-01 01:43:39 +0000828
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000829/* -------- area.c -------- */
830
Eric Andersenff9eee42001-06-29 04:57:14 +0000831/*
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000832 * All memory between (char *)areabot and (char *)(areatop+1) is
833 * exclusively administered by the area management routines.
834 * It is assumed that sbrk() and brk() manipulate the high end.
Eric Andersenff9eee42001-06-29 04:57:14 +0000835 */
836
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000837#define sbrk(X) ({ \
838 void * __q = (void *)-1; \
839 if (brkaddr + (int)(X) < brktop) { \
840 __q = brkaddr; \
841 brkaddr += (int)(X); \
842 } \
843 __q; \
844})
Eric Andersenff9eee42001-06-29 04:57:14 +0000845
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000846static void initarea(void)
Eric Andersenff9eee42001-06-29 04:57:14 +0000847{
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000848 brkaddr = xmalloc(AREASIZE);
849 brktop = brkaddr + AREASIZE;
Eric Andersenff9eee42001-06-29 04:57:14 +0000850
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000851 while ((long) sbrk(0) & ALIGN)
852 sbrk(1);
853 areabot = (struct region *) sbrk(REGSIZE);
Denis Vlasenko8e1c7152007-01-22 07:21:38 +0000854
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000855 areabot->next = areabot;
856 areabot->area = BUSY;
857 areatop = areabot;
858 areanxt = areabot;
Eric Andersenff9eee42001-06-29 04:57:14 +0000859}
860
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000861static char *getcell(unsigned nbytes)
862{
863 int nregio;
864 struct region *p, *q;
865 int i;
866
867 if (nbytes == 0) {
868 puts("getcell(0)");
869 abort();
870 }
871 /* silly and defeats the algorithm */
872 /*
873 * round upwards and add administration area
874 */
875 nregio = (nbytes + (REGSIZE - 1)) / REGSIZE + 1;
876 p = areanxt;
877 for (;;) {
878 if (p->area > areanum) {
879 /*
880 * merge free cells
881 */
882 while ((q = p->next)->area > areanum && q != areanxt)
883 p->next = q->next;
884 /*
885 * exit loop if cell big enough
886 */
887 if (q >= p + nregio)
888 goto found;
889 }
890 p = p->next;
891 if (p == areanxt)
892 break;
893 }
894 i = nregio >= GROWBY ? nregio : GROWBY;
895 p = (struct region *) sbrk(i * REGSIZE);
896 if (p == (struct region *) -1)
897 return NULL;
898 p--;
899 if (p != areatop) {
900 puts("not contig");
901 abort(); /* allocated areas are contiguous */
902 }
903 q = p + i;
904 p->next = q;
905 p->area = FREE;
906 q->next = areabot;
907 q->area = BUSY;
908 areatop = q;
909 found:
910 /*
911 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
912 */
913 areanxt = p + nregio;
914 if (areanxt < q) {
915 /*
916 * split into requested area and rest
917 */
918 if (areanxt + 1 > q) {
919 puts("OOM");
920 abort(); /* insufficient space left for admin */
921 }
922 areanxt->next = q;
923 areanxt->area = FREE;
924 p->next = areanxt;
925 }
926 p->area = areanum;
927 return (char *) (p + 1);
928}
929
930static void freecell(char *cp)
931{
932 struct region *p;
933
934 p = (struct region *) cp;
935 if (p != NULL) {
936 p--;
937 if (p < areanxt)
938 areanxt = p;
939 p->area = FREE;
940 }
941}
942#define DELETE(obj) freecell((char *)obj)
943
944static void freearea(int a)
945{
946 struct region *p, *top;
947
948 top = areatop;
949 for (p = areabot; p != top; p = p->next)
950 if (p->area >= a)
951 p->area = FREE;
952}
953
954static void setarea(char *cp, int a)
955{
956 struct region *p;
957
958 p = (struct region *) cp;
959 if (p != NULL)
960 (p - 1)->area = a;
961}
962
963static int getarea(char *cp)
964{
965 return ((struct region *) cp - 1)->area;
966}
967
968static void garbage(void)
969{
970 struct region *p, *q, *top;
971
972 top = areatop;
973 for (p = areabot; p != top; p = p->next) {
974 if (p->area > areanum) {
975 while ((q = p->next)->area > areanum)
976 p->next = q->next;
977 areanxt = p;
978 }
979 }
980#ifdef SHRINKBY
981 if (areatop >= q + SHRINKBY && q->area > areanum) {
982 brk((char *) (q + 1));
983 q->next = areabot;
984 q->area = BUSY;
985 areatop = q;
986 }
987#endif
988}
989
Denis Vlasenko509697f2008-03-02 12:49:39 +0000990static void *get_space(int n)
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000991{
992 char *cp;
993
994 cp = getcell(n);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +0000995 if (cp == NULL)
Denis Vlasenko489f93e2007-02-01 01:43:16 +0000996 err("out of string space");
997 return cp;
998}
999
1000static char *strsave(const char *s, int a)
1001{
1002 char *cp;
1003
Denis Vlasenko509697f2008-03-02 12:49:39 +00001004 cp = get_space(strlen(s) + 1);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001005 if (cp == NULL) {
1006// FIXME: I highly doubt this is good.
1007 return (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001008 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001009 setarea(cp, a);
1010 strcpy(cp, s);
1011 return cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001012}
1013
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001014
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001015/* -------- var.c -------- */
1016
1017static int eqname(const char *n1, const char *n2)
1018{
1019 for (; *n1 != '=' && *n1 != '\0'; n1++)
1020 if (*n2++ != *n1)
1021 return 0;
1022 return *n2 == '\0' || *n2 == '=';
1023}
1024
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001025static const char *findeq(const char *cp)
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001026{
1027 while (*cp != '\0' && *cp != '=')
1028 cp++;
1029 return cp;
1030}
1031
1032/*
1033 * Find the given name in the dictionary
1034 * and return its value. If the name was
1035 * not previously there, enter it now and
1036 * return a null value.
1037 */
1038static struct var *lookup(const char *n)
1039{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001040// FIXME: dirty hack
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001041 static struct var dummy;
1042
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001043 struct var *vp;
1044 const char *cp;
1045 char *xp;
1046 int c;
1047
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001048 if (isdigit(*n)) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001049 dummy.name = (char*)n;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001050 for (c = 0; isdigit(*n) && c < 1000; n++)
1051 c = c * 10 + *n - '0';
1052 dummy.status = RONLY;
1053 dummy.value = (c <= dolc ? dolv[c] : null);
1054 return &dummy;
1055 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001056
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001057 for (vp = vlist; vp; vp = vp->next)
1058 if (eqname(vp->name, n))
1059 return vp;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001060
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001061 cp = findeq(n);
Denis Vlasenko509697f2008-03-02 12:49:39 +00001062 vp = get_space(sizeof(*vp));
1063 if (vp == 0 || (vp->name = get_space((int) (cp - n) + 2)) == NULL) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001064 dummy.name = dummy.value = (char*)"";
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001065 return &dummy;
1066 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001067
1068 xp = vp->name;
1069 while ((*xp = *n++) != '\0' && *xp != '=')
1070 xp++;
1071 *xp++ = '=';
1072 *xp = '\0';
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001073 setarea((char *) vp, 0);
1074 setarea((char *) vp->name, 0);
1075 vp->value = null;
1076 vp->next = vlist;
1077 vp->status = GETCELL;
1078 vlist = vp;
1079 return vp;
1080}
1081
1082/*
1083 * if name is not NULL, it must be
1084 * a prefix of the space `val',
1085 * and end with `='.
1086 * this is all so that exporting
1087 * values is reasonably painless.
1088 */
1089static void nameval(struct var *vp, const char *val, const char *name)
1090{
1091 const char *cp;
1092 char *xp;
1093 int fl;
1094
1095 if (vp->status & RONLY) {
1096 xp = vp->name;
1097 while (*xp && *xp != '=')
Denis Vlasenko4daad902007-09-27 10:20:47 +00001098 fputc(*xp++, stderr);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001099 err(" is read-only");
1100 return;
1101 }
1102 fl = 0;
1103 if (name == NULL) {
Denis Vlasenko509697f2008-03-02 12:49:39 +00001104 xp = get_space(strlen(vp->name) + strlen(val) + 2);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001105 if (xp == NULL)
1106 return;
1107 /* make string: name=value */
1108 setarea(xp, 0);
1109 name = xp;
1110 cp = vp->name;
1111 while ((*xp = *cp++) != '\0' && *xp != '=')
1112 xp++;
1113 *xp++ = '=';
1114 strcpy(xp, val);
1115 val = xp;
1116 fl = GETCELL;
1117 }
1118 if (vp->status & GETCELL)
1119 freecell(vp->name); /* form new string `name=value' */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001120 vp->name = (char*)name;
1121 vp->value = (char*)val;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001122 vp->status |= fl;
1123}
1124
1125/*
1126 * give variable at `vp' the value `val'.
1127 */
1128static void setval(struct var *vp, const char *val)
1129{
1130 nameval(vp, val, NULL);
1131}
1132
1133static void export(struct var *vp)
1134{
1135 vp->status |= EXPORT;
1136}
1137
1138static void ronly(struct var *vp)
1139{
1140 if (isalpha(vp->name[0]) || vp->name[0] == '_') /* not an internal symbol */
1141 vp->status |= RONLY;
1142}
1143
1144static int isassign(const char *s)
1145{
1146 unsigned char c;
1147 DBGPRINTF7(("ISASSIGN: enter, s=%s\n", s));
1148
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001149 c = *s;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001150 /* no isalpha() - we shouldn't use locale */
1151 /* c | 0x20 - lowercase (Latin) letters */
1152 if (c != '_' && (unsigned)((c|0x20) - 'a') > 25)
1153 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001154 return 0;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001155
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001156 while (1) {
1157 c = *++s;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001158 if (c == '=')
1159 return 1;
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001160 if (c == '\0')
1161 return 0;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001162 if (c != '_'
1163 && (unsigned)(c - '0') > 9 /* not number */
Denis Vlasenko5b27fbe2007-03-24 14:06:51 +00001164 && (unsigned)((c|0x20) - 'a') > 25 /* not letter */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001165 ) {
1166 return 0;
1167 }
1168 }
1169}
1170
1171static int assign(const char *s, int cf)
1172{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001173 const char *cp;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001174 struct var *vp;
1175
1176 DBGPRINTF7(("ASSIGN: enter, s=%s, cf=%d\n", s, cf));
1177
1178 if (!isalpha(*s) && *s != '_')
1179 return 0;
1180 for (cp = s; *cp != '='; cp++)
1181 if (*cp == '\0' || (!isalnum(*cp) && *cp != '_'))
1182 return 0;
1183 vp = lookup(s);
1184 nameval(vp, ++cp, cf == COPYV ? NULL : s);
1185 if (cf != COPYV)
1186 vp->status &= ~GETCELL;
1187 return 1;
1188}
1189
1190static int checkname(char *cp)
1191{
1192 DBGPRINTF7(("CHECKNAME: enter, cp=%s\n", cp));
1193
1194 if (!isalpha(*cp++) && *(cp - 1) != '_')
1195 return 0;
1196 while (*cp)
1197 if (!isalnum(*cp++) && *(cp - 1) != '_')
1198 return 0;
1199 return 1;
1200}
1201
1202static void putvlist(int f, int out)
1203{
1204 struct var *vp;
1205
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001206 for (vp = vlist; vp; vp = vp->next) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001207 if (vp->status & f && (isalpha(*vp->name) || *vp->name == '_')) {
1208 if (vp->status & EXPORT)
1209 write(out, "export ", 7);
1210 if (vp->status & RONLY)
1211 write(out, "readonly ", 9);
1212 write(out, vp->name, (int) (findeq(vp->name) - vp->name));
1213 write(out, "\n", 1);
1214 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001215 }
Denis Vlasenko489f93e2007-02-01 01:43:16 +00001216}
1217
1218
1219/*
1220 * trap handling
1221 */
1222static void sig(int i)
1223{
1224 trapset = i;
1225 signal(i, sig);
1226}
1227
1228static void runtrap(int i)
1229{
1230 char *trapstr;
1231
1232 trapstr = trap[i];
1233 if (trapstr == NULL)
1234 return;
1235
1236 if (i == 0)
1237 trap[i] = NULL;
1238
1239 RUN(aword, trapstr, nlchar);
1240}
1241
1242
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001243static void setdash(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001244{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001245 char *cp;
1246 int c;
Eric Andersen8401eea2004-08-04 19:16:54 +00001247 char m['z' - 'a' + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00001248
1249 cp = m;
Eric Andersen8401eea2004-08-04 19:16:54 +00001250 for (c = 'a'; c <= 'z'; c++)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00001251 if (FLAG[c])
Eric Andersenff9eee42001-06-29 04:57:14 +00001252 *cp++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001253 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001254 setval(lookup("-"), m);
1255}
1256
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001257static int newfile(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001258{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001259 int f;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001260
1261 DBGPRINTF7(("NEWFILE: opening %s\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00001262
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001263 f = 0;
Denis Vlasenko9f739442006-12-16 23:49:13 +00001264 if (NOT_LONE_DASH(s)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001265 DBGPRINTF(("NEWFILE: s is %s\n", s));
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00001266 f = open(s, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00001267 if (f < 0) {
1268 prs(s);
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00001269 err(": can't open");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001270 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001271 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001272 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001273
Eric Andersenff9eee42001-06-29 04:57:14 +00001274 next(remap(f));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001275 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001276}
1277
Eric Andersen12de6cf2004-08-04 19:19:10 +00001278
Denis Vlasenkobc1918a2008-04-15 01:17:50 +00001279#ifdef UNUSED
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001280struct op *scantree(struct op *head)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001281{
1282 struct op *dotnode;
1283
1284 if (head == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001285 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001286
1287 if (head->left != NULL) {
1288 dotnode = scantree(head->left);
1289 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001290 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001291 }
1292
1293 if (head->right != NULL) {
1294 dotnode = scantree(head->right);
1295 if (dotnode)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001296 return dotnode;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001297 }
1298
Denis Vlasenko509697f2008-03-02 12:49:39 +00001299 if (head->op_words == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001300 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001301
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001302 DBGPRINTF5(("SCANTREE: checking node %p\n", head));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001303
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001304 if ((head->op_type != TDOT) && LONE_CHAR(head->op_words[0], '.')) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001305 DBGPRINTF5(("SCANTREE: dot found in node %p\n", head));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001306 return head;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001307 }
1308
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001309 return NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001310}
Denis Vlasenkobc1918a2008-04-15 01:17:50 +00001311#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00001312
1313
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001314static void onecommand(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001315{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001316 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00001317 jmp_buf m1;
1318
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001319 DBGPRINTF(("ONECOMMAND: enter, outtree=%p\n", outtree));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001320
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001321 while (global_env.oenv)
Eric Andersenff9eee42001-06-29 04:57:14 +00001322 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001323
Eric Andersenff9eee42001-06-29 04:57:14 +00001324 areanum = 1;
1325 freehere(areanum);
1326 freearea(areanum);
1327 garbage();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001328 wdlist = NULL;
1329 iolist = NULL;
1330 global_env.errpt = NULL;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001331 global_env.linep = line;
Eric Andersenff9eee42001-06-29 04:57:14 +00001332 yynerrs = 0;
1333 multiline = 0;
1334 inparse = 1;
1335 intr = 0;
1336 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001337
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001338 failpt = m1;
1339 setjmp(failpt); /* Bruce Evans' fix */
1340 failpt = m1;
1341 if (setjmp(failpt) || yyparse() || intr) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001342 DBGPRINTF(("ONECOMMAND: this is not good.\n"));
1343
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001344 while (global_env.oenv)
Eric Andersenff9eee42001-06-29 04:57:14 +00001345 quitenv();
1346 scraphere();
1347 if (!interactive && intr)
1348 leave();
1349 inparse = 0;
1350 intr = 0;
1351 return;
1352 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001353
Eric Andersenff9eee42001-06-29 04:57:14 +00001354 inparse = 0;
1355 brklist = 0;
1356 intr = 0;
1357 execflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001358
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00001359 if (!FLAG['n']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001360 DBGPRINTF(("ONECOMMAND: calling execute, t=outtree=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00001361 outtree));
Denis Vlasenko7e497522008-02-12 09:51:03 +00001362 execute(outtree, NOPIPE, NOPIPE, /* no_fork: */ 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001363 }
1364
Eric Andersenff9eee42001-06-29 04:57:14 +00001365 if (!interactive && intr) {
1366 execflg = 0;
1367 leave();
1368 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001369
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001370 i = trapset;
1371 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001372 trapset = 0;
1373 runtrap(i);
1374 }
1375}
1376
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001377static int newenv(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001378{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001379 struct env *ep;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001380
1381 DBGPRINTF(("NEWENV: f=%d (indicates quitenv and return)\n", f));
Eric Andersenff9eee42001-06-29 04:57:14 +00001382
1383 if (f) {
1384 quitenv();
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001385 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001386 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001387
Denis Vlasenko509697f2008-03-02 12:49:39 +00001388 ep = get_space(sizeof(*ep));
Eric Andersenff9eee42001-06-29 04:57:14 +00001389 if (ep == NULL) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001390 while (global_env.oenv)
Eric Andersenff9eee42001-06-29 04:57:14 +00001391 quitenv();
1392 fail();
1393 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001394 *ep = global_env;
1395 global_env.oenv = ep;
1396 global_env.errpt = errpt;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001397
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001398 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001399}
1400
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001401static void quitenv(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001402{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001403 struct env *ep;
1404 int fd;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001405
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001406 DBGPRINTF(("QUITENV: global_env.oenv=%p\n", global_env.oenv));
Eric Andersenff9eee42001-06-29 04:57:14 +00001407
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001408 ep = global_env.oenv;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001409 if (ep != NULL) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001410 fd = global_env.iofd;
1411 global_env = *ep;
Eric Andersenff9eee42001-06-29 04:57:14 +00001412 /* should close `'d files */
1413 DELETE(ep);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001414 while (--fd >= global_env.iofd)
Eric Andersenff9eee42001-06-29 04:57:14 +00001415 close(fd);
1416 }
1417}
1418
1419/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001420 * Is character c in s?
Eric Andersenff9eee42001-06-29 04:57:14 +00001421 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001422static int any(int c, const char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00001423{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001424 while (*s)
1425 if (*s++ == c)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001426 return 1;
1427 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001428}
1429
1430/*
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001431 * Is any character from s1 in s2?
Eric Andersenff9eee42001-06-29 04:57:14 +00001432 */
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001433static int anys(const char *s1, const char *s2)
Eric Andersenff9eee42001-06-29 04:57:14 +00001434{
Denis Vlasenkob6aae0f2007-01-29 22:51:25 +00001435 while (*s1)
1436 if (any(*s1++, s2))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001437 return 1;
1438 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001439}
1440
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001441static char *putn(int n)
Eric Andersenff9eee42001-06-29 04:57:14 +00001442{
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001443 return itoa(n);
Eric Andersenff9eee42001-06-29 04:57:14 +00001444}
1445
Eric Andersen8401eea2004-08-04 19:16:54 +00001446static void next(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00001447{
1448 PUSHIO(afile, f, filechar);
1449}
1450
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001451static void onintr(int s UNUSED_PARAM) /* ANSI C requires a parameter */
Eric Andersenff9eee42001-06-29 04:57:14 +00001452{
1453 signal(SIGINT, onintr);
1454 intr = 1;
1455 if (interactive) {
1456 if (inparse) {
1457 prs("\n");
1458 fail();
1459 }
Eric Andersen8401eea2004-08-04 19:16:54 +00001460 } else if (heedint) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001461 execflg = 0;
1462 leave();
1463 }
1464}
1465
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001466
Eric Andersenff9eee42001-06-29 04:57:14 +00001467/* -------- gmatch.c -------- */
1468/*
1469 * int gmatch(string, pattern)
1470 * char *string, *pattern;
1471 *
1472 * Match a pattern as in sh(1).
1473 */
1474
1475#define CMASK 0377
1476#define QUOTE 0200
Denis Vlasenko55f30b02007-03-24 22:42:29 +00001477#define QMASK (CMASK & ~QUOTE)
Eric Andersen8401eea2004-08-04 19:16:54 +00001478#define NOT '!' /* might use ^ */
Eric Andersenff9eee42001-06-29 04:57:14 +00001479
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001480static const char *cclass(const char *p, int sub)
1481{
1482 int c, d, not, found;
1483
1484 not = (*p == NOT);
1485 if (not != 0)
1486 p++;
1487 found = not;
1488 do {
1489 if (*p == '\0')
1490 return NULL;
1491 c = *p & CMASK;
1492 if (p[1] == '-' && p[2] != ']') {
1493 d = p[2] & CMASK;
1494 p++;
1495 } else
1496 d = c;
1497 if (c == sub || (c <= sub && sub <= d))
1498 found = !not;
1499 } while (*++p != ']');
1500 return found ? p + 1 : NULL;
1501}
1502
1503static int gmatch(const char *s, const char *p)
Eric Andersenff9eee42001-06-29 04:57:14 +00001504{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001505 int sc, pc;
Eric Andersenff9eee42001-06-29 04:57:14 +00001506
1507 if (s == NULL || p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001508 return 0;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00001509
Eric Andersenff9eee42001-06-29 04:57:14 +00001510 while ((pc = *p++ & CMASK) != '\0') {
1511 sc = *s++ & QMASK;
1512 switch (pc) {
1513 case '[':
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001514 p = cclass(p, sc);
1515 if (p == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001516 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001517 break;
1518
1519 case '?':
1520 if (sc == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001521 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001522 break;
1523
1524 case '*':
1525 s--;
1526 do {
1527 if (*p == '\0' || gmatch(s, p))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001528 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001529 } while (*s++ != '\0');
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001530 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001531
1532 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00001533 if (sc != (pc & ~QUOTE))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001534 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001535 }
1536 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001537 return *s == '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00001538}
1539
Eric Andersenff9eee42001-06-29 04:57:14 +00001540
Eric Andersenff9eee42001-06-29 04:57:14 +00001541/* -------- csyn.c -------- */
1542/*
1543 * shell: syntax (C version)
1544 */
1545
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001546static void yyerror(const char *s) NORETURN;
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001547static void yyerror(const char *s)
1548{
Denis Vlasenko648b44f2008-02-12 06:04:06 +00001549 yynerrs = 1;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00001550 if (interactive && global_env.iop <= iostack) {
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001551 multiline = 0;
Denis Vlasenko648b44f2008-02-12 06:04:06 +00001552 while (eofc() == 0 && yylex(0) != '\n')
1553 continue;
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001554 }
1555 err(s);
1556 fail();
1557}
1558
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00001559static void zzerr(void) NORETURN;
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001560static void zzerr(void)
1561{
1562 yyerror("syntax error");
1563}
1564
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001565int yyparse(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001566{
Eric Andersen12de6cf2004-08-04 19:19:10 +00001567 DBGPRINTF7(("YYPARSE: enter...\n"));
1568
Eric Andersen8401eea2004-08-04 19:16:54 +00001569 startl = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001570 peeksym = 0;
1571 yynerrs = 0;
1572 outtree = c_list();
1573 musthave('\n', 0);
Denis Vlasenko648b44f2008-02-12 06:04:06 +00001574 return yynerrs; /* 0/1 */
Eric Andersenff9eee42001-06-29 04:57:14 +00001575}
1576
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001577static struct op *pipeline(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001578{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001579 struct op *t, *p;
1580 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001581
1582 DBGPRINTF7(("PIPELINE: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001583
1584 t = command(cf);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001585
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001586 DBGPRINTF9(("PIPELINE: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001587
Eric Andersenff9eee42001-06-29 04:57:14 +00001588 if (t != NULL) {
1589 while ((c = yylex(0)) == '|') {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001590 p = command(CONTIN);
1591 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001592 DBGPRINTF8(("PIPELINE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001593 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001594 }
1595
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001596 if (t->op_type != TPAREN && t->op_type != TCOM) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001597 /* shell statement */
1598 t = block(TPAREN, t, NOBLOCK, NOWORDS);
1599 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001600
Eric Andersenff9eee42001-06-29 04:57:14 +00001601 t = block(TPIPE, t, p, NOWORDS);
1602 }
1603 peeksym = c;
1604 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001605
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001606 DBGPRINTF7(("PIPELINE: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001607 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001608}
1609
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001610static struct op *andor(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001611{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001612 struct op *t, *p;
1613 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001614
1615 DBGPRINTF7(("ANDOR: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001616
1617 t = pipeline(0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001618
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001619 DBGPRINTF9(("ANDOR: t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001620
Eric Andersenff9eee42001-06-29 04:57:14 +00001621 if (t != NULL) {
1622 while ((c = yylex(0)) == LOGAND || c == LOGOR) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001623 p = pipeline(CONTIN);
1624 if (p == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001625 DBGPRINTF8(("ANDOR: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001626 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001627 }
1628
Eric Andersen8401eea2004-08-04 19:16:54 +00001629 t = block(c == LOGAND ? TAND : TOR, t, p, NOWORDS);
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001630 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001631
Eric Andersenff9eee42001-06-29 04:57:14 +00001632 peeksym = c;
1633 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001634
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001635 DBGPRINTF7(("ANDOR: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001636 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001637}
1638
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001639static struct op *c_list(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001640{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001641 struct op *t, *p;
1642 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001643
1644 DBGPRINTF7(("C_LIST: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001645
1646 t = andor();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001647
Eric Andersenff9eee42001-06-29 04:57:14 +00001648 if (t != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001649 peeksym = yylex(0);
1650 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001651 t = block(TASYNC, t, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001652
Eric Andersen8401eea2004-08-04 19:16:54 +00001653 while ((c = yylex(0)) == ';' || c == '&'
Denis Vlasenko509697f2008-03-02 12:49:39 +00001654 || (multiline && c == '\n')
1655 ) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001656 p = andor();
1657 if (p== NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001658 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001659
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001660 peeksym = yylex(0);
1661 if (peeksym == '&')
Eric Andersenff9eee42001-06-29 04:57:14 +00001662 p = block(TASYNC, p, NOBLOCK, NOWORDS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001663
Eric Andersenff9eee42001-06-29 04:57:14 +00001664 t = list(t, p);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001665 } /* WHILE */
1666
Eric Andersenff9eee42001-06-29 04:57:14 +00001667 peeksym = c;
1668 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001669 /* IF */
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001670 DBGPRINTF7(("C_LIST: returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001671 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001672}
1673
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001674static int synio(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001675{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001676 struct ioword *iop;
1677 int i;
1678 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001679
1680 DBGPRINTF7(("SYNIO: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001681
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001682 c = yylex(cf);
1683 if (c != '<' && c != '>') {
Eric Andersenff9eee42001-06-29 04:57:14 +00001684 peeksym = c;
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001685 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00001686 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001687
Eric Andersenff9eee42001-06-29 04:57:14 +00001688 i = yylval.i;
1689 musthave(WORD, 0);
1690 iop = io(iounit, i, yylval.cp);
1691 iounit = IODEFAULT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001692
Eric Andersenff9eee42001-06-29 04:57:14 +00001693 if (i & IOHERE)
1694 markhere(yylval.cp, iop);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001695
1696 DBGPRINTF7(("SYNIO: returning 1\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00001697 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00001698}
1699
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001700static void musthave(int c, int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001701{
Denis Vlasenko00ccf952007-02-01 01:39:24 +00001702 peeksym = yylex(cf);
1703 if (peeksym != c) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00001704 DBGPRINTF7(("MUSTHAVE: error!\n"));
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001705 zzerr();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001706 }
1707
Eric Andersenff9eee42001-06-29 04:57:14 +00001708 peeksym = 0;
1709}
1710
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001711static struct op *simple(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001712{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001713 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001714
1715 t = NULL;
1716 for (;;) {
1717 switch (peeksym = yylex(0)) {
1718 case '<':
1719 case '>':
1720 (void) synio(0);
1721 break;
1722
1723 case WORD:
1724 if (t == NULL) {
1725 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001726 t->op_type = TCOM;
Eric Andersenff9eee42001-06-29 04:57:14 +00001727 }
1728 peeksym = 0;
1729 word(yylval.cp);
1730 break;
1731
1732 default:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001733 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001734 }
1735 }
1736}
1737
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001738static struct op *nested(int type, int mark)
Eric Andersenff9eee42001-06-29 04:57:14 +00001739{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001740 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001741
1742 DBGPRINTF3(("NESTED: enter, type=%d, mark=%d\n", type, mark));
Eric Andersenff9eee42001-06-29 04:57:14 +00001743
1744 multiline++;
1745 t = c_list();
1746 musthave(mark, 0);
1747 multiline--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001748 return block(type, t, NOBLOCK, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00001749}
1750
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001751static struct op *command(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00001752{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001753 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001754 struct wdblock *iosave;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001755 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001756
1757 DBGPRINTF(("COMMAND: enter, cf=%d\n", cf));
Eric Andersenff9eee42001-06-29 04:57:14 +00001758
1759 iosave = iolist;
1760 iolist = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001761
Eric Andersenff9eee42001-06-29 04:57:14 +00001762 if (multiline)
1763 cf |= CONTIN;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001764
Eric Andersenff9eee42001-06-29 04:57:14 +00001765 while (synio(cf))
1766 cf = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001767
1768 c = yylex(cf);
1769
1770 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001771 default:
1772 peeksym = c;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001773 t = simple();
1774 if (t == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001775 if (iolist == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001776 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001777 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001778 t->op_type = TCOM;
Eric Andersenff9eee42001-06-29 04:57:14 +00001779 }
1780 break;
1781
1782 case '(':
1783 t = nested(TPAREN, ')');
1784 break;
1785
1786 case '{':
1787 t = nested(TBRACE, '}');
1788 break;
1789
1790 case FOR:
1791 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001792 t->op_type = TFOR;
Eric Andersenff9eee42001-06-29 04:57:14 +00001793 musthave(WORD, 0);
1794 startl = 1;
1795 t->str = yylval.cp;
1796 multiline++;
Denis Vlasenko509697f2008-03-02 12:49:39 +00001797 t->op_words = wordlist();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001798 c = yylex(0);
1799 if (c != '\n' && c != ';')
Eric Andersenff9eee42001-06-29 04:57:14 +00001800 peeksym = c;
1801 t->left = dogroup(0);
1802 multiline--;
1803 break;
1804
1805 case WHILE:
1806 case UNTIL:
1807 multiline++;
1808 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001809 t->op_type = (c == WHILE ? TWHILE : TUNTIL);
Eric Andersenff9eee42001-06-29 04:57:14 +00001810 t->left = c_list();
1811 t->right = dogroup(1);
Denis Vlasenko509697f2008-03-02 12:49:39 +00001812 /* t->op_words = NULL; - newtp() did this */
Eric Andersenff9eee42001-06-29 04:57:14 +00001813 multiline--;
1814 break;
1815
1816 case CASE:
1817 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001818 t->op_type = TCASE;
Eric Andersenff9eee42001-06-29 04:57:14 +00001819 musthave(WORD, 0);
1820 t->str = yylval.cp;
1821 startl++;
1822 multiline++;
1823 musthave(IN, CONTIN);
1824 startl++;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001825
Eric Andersenff9eee42001-06-29 04:57:14 +00001826 t->left = caselist();
Eric Andersen12de6cf2004-08-04 19:19:10 +00001827
Eric Andersenff9eee42001-06-29 04:57:14 +00001828 musthave(ESAC, 0);
1829 multiline--;
1830 break;
1831
1832 case IF:
1833 multiline++;
1834 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001835 t->op_type = TIF;
Eric Andersenff9eee42001-06-29 04:57:14 +00001836 t->left = c_list();
1837 t->right = thenpart();
1838 musthave(FI, 0);
1839 multiline--;
1840 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001841
1842 case DOT:
1843 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001844 t->op_type = TDOT;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001845
Denis Vlasenko509697f2008-03-02 12:49:39 +00001846 musthave(WORD, 0); /* gets name of file */
Eric Andersen12de6cf2004-08-04 19:19:10 +00001847 DBGPRINTF7(("COMMAND: DOT clause, yylval.cp is %s\n", yylval.cp));
1848
Denis Vlasenko509697f2008-03-02 12:49:39 +00001849 word(yylval.cp); /* add word to wdlist */
1850 word(NOWORD); /* terminate wdlist */
1851 t->op_words = copyw(); /* dup wdlist */
Eric Andersen12de6cf2004-08-04 19:19:10 +00001852 break;
1853
Eric Andersenff9eee42001-06-29 04:57:14 +00001854 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00001855
Denis Vlasenko509697f2008-03-02 12:49:39 +00001856 while (synio(0))
1857 continue;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001858
Eric Andersenff9eee42001-06-29 04:57:14 +00001859 t = namelist(t);
1860 iolist = iosave;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001861
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001862 DBGPRINTF(("COMMAND: returning %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001863
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001864 return t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001865}
1866
Denis Vlasenko68404f12008-03-17 09:00:54 +00001867static struct op *dowholefile(int type /*, int mark*/)
Eric Andersen12de6cf2004-08-04 19:19:10 +00001868{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001869 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001870
Denis Vlasenko68404f12008-03-17 09:00:54 +00001871 DBGPRINTF(("DOWHOLEFILE: enter, type=%d\n", type /*, mark*/));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001872
1873 multiline++;
1874 t = c_list();
1875 multiline--;
1876 t = block(type, t, NOBLOCK, NOWORDS);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001877 DBGPRINTF(("DOWHOLEFILE: return t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001878 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001879}
1880
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001881static struct op *dogroup(int onlydone)
Eric Andersenff9eee42001-06-29 04:57:14 +00001882{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001883 int c;
1884 struct op *mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001885
1886 c = yylex(CONTIN);
1887 if (c == DONE && onlydone)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001888 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001889 if (c != DO)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001890 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001891 mylist = c_list();
1892 musthave(DONE, 0);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001893 return mylist;
Eric Andersenff9eee42001-06-29 04:57:14 +00001894}
1895
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001896static struct op *thenpart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001897{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001898 int c;
1899 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001900
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001901 c = yylex(0);
1902 if (c != THEN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001903 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001904 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001905 }
1906 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001907 /*t->op_type = 0; - newtp() did this */
Eric Andersenff9eee42001-06-29 04:57:14 +00001908 t->left = c_list();
1909 if (t->left == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001910 zzerr();
Eric Andersenff9eee42001-06-29 04:57:14 +00001911 t->right = elsepart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001912 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001913}
1914
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001915static struct op *elsepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001916{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001917 int c;
1918 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001919
1920 switch (c = yylex(0)) {
1921 case ELSE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001922 t = c_list();
1923 if (t == NULL)
Denis Vlasenko6b50f732007-02-01 01:43:39 +00001924 zzerr();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001925 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001926
1927 case ELIF:
1928 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001929 t->op_type = TELIF;
Eric Andersenff9eee42001-06-29 04:57:14 +00001930 t->left = c_list();
1931 t->right = thenpart();
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001932 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001933
1934 default:
1935 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001936 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001937 }
1938}
1939
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001940static struct op *caselist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001941{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001942 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001943
1944 t = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001945 while ((peeksym = yylex(CONTIN)) != ESAC) {
1946 DBGPRINTF(("CASELIST, doing yylex, peeksym=%d\n", peeksym));
Eric Andersenff9eee42001-06-29 04:57:14 +00001947 t = list(t, casepart());
Eric Andersen12de6cf2004-08-04 19:19:10 +00001948 }
1949
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001950 DBGPRINTF(("CASELIST, returning t=%p\n", t));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001951 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001952}
1953
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001954static struct op *casepart(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001955{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001956 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00001957
1958 DBGPRINTF7(("CASEPART: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00001959
1960 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00001961 t->op_type = TPAT;
Denis Vlasenko509697f2008-03-02 12:49:39 +00001962 t->op_words = pattern();
Eric Andersenff9eee42001-06-29 04:57:14 +00001963 musthave(')', 0);
1964 t->left = c_list();
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001965 peeksym = yylex(CONTIN);
1966 if (peeksym != ESAC)
Eric Andersenff9eee42001-06-29 04:57:14 +00001967 musthave(BREAK, CONTIN);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001968
Mike Frysinger02d8fa42006-05-05 20:32:31 +00001969 DBGPRINTF7(("CASEPART: made newtp(TPAT, t=%p)\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00001970
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001971 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00001972}
1973
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001974static char **pattern(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001975{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001976 int c, cf;
Eric Andersenff9eee42001-06-29 04:57:14 +00001977
1978 cf = CONTIN;
1979 do {
1980 musthave(WORD, cf);
1981 word(yylval.cp);
1982 cf = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001983 c = yylex(0);
1984 } while (c == '|');
Eric Andersenff9eee42001-06-29 04:57:14 +00001985 peeksym = c;
1986 word(NOWORD);
Eric Andersen12de6cf2004-08-04 19:19:10 +00001987
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001988 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00001989}
1990
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00001991static char **wordlist(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00001992{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00001993 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00001994
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00001995 c = yylex(0);
1996 if (c != IN) {
Eric Andersenff9eee42001-06-29 04:57:14 +00001997 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00001998 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00001999 }
2000 startl = 0;
2001 while ((c = yylex(0)) == WORD)
2002 word(yylval.cp);
2003 word(NOWORD);
2004 peeksym = c;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002005 return copyw();
Eric Andersenff9eee42001-06-29 04:57:14 +00002006}
2007
2008/*
2009 * supporting functions
2010 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002011static struct op *list(struct op *t1, struct op *t2)
Eric Andersenff9eee42001-06-29 04:57:14 +00002012{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002013 DBGPRINTF7(("LIST: enter, t1=%p, t2=%p\n", t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002014
Eric Andersenff9eee42001-06-29 04:57:14 +00002015 if (t1 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002016 return t2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002017 if (t2 == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002018 return t1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002019
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002020 return block(TLIST, t1, t2, NOWORDS);
Eric Andersenff9eee42001-06-29 04:57:14 +00002021}
2022
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002023static struct op *block(int type, struct op *t1, struct op *t2, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002024{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002025 struct op *t;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002026
2027 DBGPRINTF7(("BLOCK: enter, type=%d (%s)\n", type, T_CMD_NAMES[type]));
Eric Andersenff9eee42001-06-29 04:57:14 +00002028
2029 t = newtp();
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002030 t->op_type = type;
Eric Andersenff9eee42001-06-29 04:57:14 +00002031 t->left = t1;
2032 t->right = t2;
Denis Vlasenko509697f2008-03-02 12:49:39 +00002033 t->op_words = wp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002034
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002035 DBGPRINTF7(("BLOCK: inserted %p between %p and %p\n", t, t1, t2));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002036
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002037 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002038}
2039
Eric Andersen12de6cf2004-08-04 19:19:10 +00002040/* See if given string is a shell multiline (FOR, IF, etc) */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002041static int rlookup(char *n)
Eric Andersenff9eee42001-06-29 04:57:14 +00002042{
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002043 struct res {
2044 char r_name[6];
2045 int16_t r_val;
2046 };
2047 static const struct res restab[] = {
2048 { "for" , FOR },
2049 { "case" , CASE },
2050 { "esac" , ESAC },
2051 { "while", WHILE },
2052 { "do" , DO },
2053 { "done" , DONE },
2054 { "if" , IF },
2055 { "in" , IN },
2056 { "then" , THEN },
2057 { "else" , ELSE },
2058 { "elif" , ELIF },
2059 { "until", UNTIL },
2060 { "fi" , FI },
2061 { ";;" , BREAK },
2062 { "||" , LOGOR },
2063 { "&&" , LOGAND },
2064 { "{" , '{' },
2065 { "}" , '}' },
2066 { "." , DOT },
2067 { },
2068 };
2069
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002070 const struct res *rp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002071
2072 DBGPRINTF7(("RLOOKUP: enter, n is %s\n", n));
Eric Andersenff9eee42001-06-29 04:57:14 +00002073
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002074 for (rp = restab; rp->r_name[0]; rp++)
Eric Andersen12de6cf2004-08-04 19:19:10 +00002075 if (strcmp(rp->r_name, n) == 0) {
2076 DBGPRINTF7(("RLOOKUP: match, returning %d\n", rp->r_val));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002077 return rp->r_val; /* Return numeric code for shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002078 }
2079
2080 DBGPRINTF7(("RLOOKUP: NO match, returning 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002081 return 0; /* Not a shell multiline */
Eric Andersenff9eee42001-06-29 04:57:14 +00002082}
2083
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002084static struct op *newtp(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002085{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002086 struct op *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002087
Eric Andersen8401eea2004-08-04 19:16:54 +00002088 t = (struct op *) tree(sizeof(*t));
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002089 memset(t, 0, sizeof(*t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002090
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002091 DBGPRINTF3(("NEWTP: allocated %p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002092
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002093 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002094}
2095
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002096static struct op *namelist(struct op *t)
Eric Andersenff9eee42001-06-29 04:57:14 +00002097{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002098 DBGPRINTF7(("NAMELIST: enter, t=%p, type %s, iolist=%p\n", t,
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002099 T_CMD_NAMES[t->op_type], iolist));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002100
Eric Andersenff9eee42001-06-29 04:57:14 +00002101 if (iolist) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002102 iolist = addword((char *) NULL, iolist);
Eric Andersenff9eee42001-06-29 04:57:14 +00002103 t->ioact = copyio();
2104 } else
2105 t->ioact = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002106
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002107 if (t->op_type != TCOM) {
2108 if (t->op_type != TPAREN && t->ioact != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002109 t = block(TPAREN, t, NOBLOCK, NOWORDS);
2110 t->ioact = t->left->ioact;
2111 t->left->ioact = NULL;
2112 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002113 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002114 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002115
Eric Andersenff9eee42001-06-29 04:57:14 +00002116 word(NOWORD);
Denis Vlasenko509697f2008-03-02 12:49:39 +00002117 t->op_words = copyw();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002118
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002119 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002120}
2121
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002122static char **copyw(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002123{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002124 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002125
2126 wd = getwords(wdlist);
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002127 wdlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002128 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00002129}
2130
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002131static void word(char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002132{
2133 wdlist = addword(cp, wdlist);
2134}
2135
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002136static struct ioword **copyio(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00002137{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002138 struct ioword **iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002139
2140 iop = (struct ioword **) getwords(iolist);
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002141 iolist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002142 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002143}
2144
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002145static struct ioword *io(int u, int f, char *cp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002146{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002147 struct ioword *iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002148
2149 iop = (struct ioword *) tree(sizeof(*iop));
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002150 iop->io_fd = u;
Eric Andersenff9eee42001-06-29 04:57:14 +00002151 iop->io_flag = f;
2152 iop->io_name = cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00002153 iolist = addword((char *) iop, iolist);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002154 return iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00002155}
2156
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002157static int yylex(int cf)
Eric Andersenff9eee42001-06-29 04:57:14 +00002158{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002159 int c, c1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002160 int atstart;
2161
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002162 c = peeksym;
2163 if (c > 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002164 peeksym = 0;
2165 if (c == '\n')
2166 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002167 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002168 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002169
Eric Andersenff9eee42001-06-29 04:57:14 +00002170 nlseen = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002171 atstart = startl;
2172 startl = 0;
2173 yylval.i = 0;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002174 global_env.linep = line;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002175
2176/* MALAMO */
2177 line[LINELIM - 1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00002178
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002179 loop:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002180 while ((c = my_getc(0)) == ' ' || c == '\t') /* Skip whitespace */
Denis Vlasenko509697f2008-03-02 12:49:39 +00002181 continue;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002182
Eric Andersenff9eee42001-06-29 04:57:14 +00002183 switch (c) {
2184 default:
2185 if (any(c, "0123456789")) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002186 c1 = my_getc(0);
2187 unget(c1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002188 if (c1 == '<' || c1 == '>') {
2189 iounit = c - '0';
2190 goto loop;
2191 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002192 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002193 c = c1;
2194 }
2195 break;
2196
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002197 case '#': /* Comment, skip to next newline or End-of-string */
Denis Vlasenko509697f2008-03-02 12:49:39 +00002198 while ((c = my_getc(0)) != '\0' && c != '\n')
2199 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00002200 unget(c);
2201 goto loop;
2202
2203 case 0:
Eric Andersen12de6cf2004-08-04 19:19:10 +00002204 DBGPRINTF5(("YYLEX: return 0, c=%d\n", c));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002205 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002206
2207 case '$':
Eric Andersen12de6cf2004-08-04 19:19:10 +00002208 DBGPRINTF9(("YYLEX: found $\n"));
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002209 *global_env.linep++ = c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002210 c = my_getc(0);
2211 if (c == '{') {
2212 c = collect(c, '}');
2213 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002214 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002215 goto pack;
2216 }
2217 break;
2218
2219 case '`':
2220 case '\'':
2221 case '"':
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002222 c = collect(c, c);
2223 if (c != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002224 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002225 goto pack;
2226
2227 case '|':
2228 case '&':
2229 case ';':
Eric Andersenff9eee42001-06-29 04:57:14 +00002230 startl = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002231 /* If more chars process them, else return NULL char */
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002232 c1 = dual(c);
2233 if (c1 != '\0')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002234 return c1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002235 return c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002236
Eric Andersenff9eee42001-06-29 04:57:14 +00002237 case '^':
2238 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002239 return '|';
Eric Andersenff9eee42001-06-29 04:57:14 +00002240 case '>':
2241 case '<':
2242 diag(c);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002243 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002244
2245 case '\n':
2246 nlseen++;
2247 gethere();
2248 startl = 1;
2249 if (multiline || cf & CONTIN) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002250 if (interactive && global_env.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002251#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002252 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002253#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002254 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002255#endif
2256 }
2257 if (cf & CONTIN)
2258 goto loop;
2259 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002260 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002261
2262 case '(':
2263 case ')':
2264 startl = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002265 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002266 }
2267
2268 unget(c);
2269
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002270 pack:
2271 while ((c = my_getc(0)) != '\0' && !any(c, "`$ '\"\t;&<>()|^\n")) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002272 if (global_env.linep >= elinep)
Eric Andersenff9eee42001-06-29 04:57:14 +00002273 err("word too long");
2274 else
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002275 *global_env.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002276 };
2277
Eric Andersenff9eee42001-06-29 04:57:14 +00002278 unget(c);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002279
Eric Andersen8401eea2004-08-04 19:16:54 +00002280 if (any(c, "\"'`$"))
Eric Andersenff9eee42001-06-29 04:57:14 +00002281 goto loop;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002282
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002283 *global_env.linep++ = '\0';
Eric Andersen12de6cf2004-08-04 19:19:10 +00002284
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002285 if (atstart) {
2286 c = rlookup(line);
2287 if (c != 0) {
2288 startl = 1;
2289 return c;
2290 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002291 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002292
Eric Andersenff9eee42001-06-29 04:57:14 +00002293 yylval.cp = strsave(line, areanum);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002294 return WORD;
Eric Andersenff9eee42001-06-29 04:57:14 +00002295}
2296
Eric Andersen12de6cf2004-08-04 19:19:10 +00002297
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002298static int collect(int c, int c1)
Eric Andersenff9eee42001-06-29 04:57:14 +00002299{
2300 char s[2];
2301
Eric Andersen12de6cf2004-08-04 19:19:10 +00002302 DBGPRINTF8(("COLLECT: enter, c=%d, c1=%d\n", c, c1));
2303
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002304 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002305 while ((c = my_getc(c1)) != c1) {
2306 if (c == 0) {
2307 unget(c);
2308 s[0] = c1;
2309 s[1] = 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00002310 prs("no closing ");
2311 yyerror(s);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002312 return YYERRCODE;
Eric Andersenff9eee42001-06-29 04:57:14 +00002313 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002314 if (interactive && c == '\n' && global_env.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00002315#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00002316 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00002317#else
Eric Andersen8401eea2004-08-04 19:16:54 +00002318 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00002319#endif
2320 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002321 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00002322 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002323
Denis Vlasenkoc794c512007-12-16 17:21:29 +00002324 *global_env.linep++ = c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002325
2326 DBGPRINTF8(("COLLECT: return 0, line is %s\n", line));
2327
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002328 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002329}
2330
Eric Andersen12de6cf2004-08-04 19:19:10 +00002331/* "multiline commands" helper func */
2332/* see if next 2 chars form a shell multiline */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002333static int dual(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00002334{
2335 char s[3];
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002336 char *cp = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00002337
Eric Andersen12de6cf2004-08-04 19:19:10 +00002338 DBGPRINTF8(("DUAL: enter, c=%d\n", c));
2339
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002340 *cp++ = c; /* c is the given "peek" char */
2341 *cp++ = my_getc(0); /* get next char of input */
2342 *cp = '\0'; /* add EOS marker */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002343
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002344 c = rlookup(s); /* see if 2 chars form a shell multiline */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002345 if (c == 0)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002346 unget(*--cp); /* String is not a shell multiline, put peek char back */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002347
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002348 return c; /* String is multiline, return numeric multiline (restab) code */
Eric Andersenff9eee42001-06-29 04:57:14 +00002349}
2350
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002351static void diag(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00002352{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002353 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002354
2355 DBGPRINTF8(("DIAG: enter, ec=%d\n", ec));
Eric Andersenff9eee42001-06-29 04:57:14 +00002356
2357 c = my_getc(0);
2358 if (c == '>' || c == '<') {
2359 if (c != ec)
2360 zzerr();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002361 yylval.i = (ec == '>' ? IOWRITE | IOCAT : IOHERE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002362 c = my_getc(0);
2363 } else
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002364 yylval.i = (ec == '>' ? IOWRITE : IOREAD);
Eric Andersenff9eee42001-06-29 04:57:14 +00002365 if (c != '&' || yylval.i == IOHERE)
2366 unget(c);
2367 else
2368 yylval.i |= IODUP;
2369}
2370
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002371static char *tree(unsigned size)
Eric Andersenff9eee42001-06-29 04:57:14 +00002372{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002373 char *t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002374
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002375 t = getcell(size);
2376 if (t == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002377 DBGPRINTF2(("TREE: getcell(%d) failed!\n", size));
Eric Andersenff9eee42001-06-29 04:57:14 +00002378 prs("command line too complicated\n");
2379 fail();
2380 /* NOTREACHED */
2381 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002382 return t;
Eric Andersenff9eee42001-06-29 04:57:14 +00002383}
2384
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002385
Eric Andersenff9eee42001-06-29 04:57:14 +00002386/* VARARGS1 */
2387/* ARGSUSED */
2388
2389/* -------- exec.c -------- */
2390
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002391static struct op **find1case(struct op *t, const char *w)
2392{
2393 struct op *t1;
2394 struct op **tp;
2395 char **wp;
2396 char *cp;
2397
2398 if (t == NULL) {
2399 DBGPRINTF3(("FIND1CASE: enter, t==NULL, returning.\n"));
2400 return NULL;
2401 }
2402
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002403 DBGPRINTF3(("FIND1CASE: enter, t->op_type=%d (%s)\n", t->op_type,
2404 T_CMD_NAMES[t->op_type]));
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002405
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002406 if (t->op_type == TLIST) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002407 tp = find1case(t->left, w);
2408 if (tp != NULL) {
2409 DBGPRINTF3(("FIND1CASE: found one to the left, returning tp=%p\n", tp));
2410 return tp;
2411 }
2412 t1 = t->right; /* TPAT */
2413 } else
2414 t1 = t;
2415
Denis Vlasenko509697f2008-03-02 12:49:39 +00002416 for (wp = t1->op_words; *wp;) {
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002417 cp = evalstr(*wp++, DOSUB);
2418 if (cp && gmatch(w, cp)) {
2419 DBGPRINTF3(("FIND1CASE: returning &t1->left= %p.\n",
2420 &t1->left));
2421 return &t1->left;
2422 }
2423 }
2424
2425 DBGPRINTF(("FIND1CASE: returning NULL\n"));
2426 return NULL;
2427}
2428
2429static struct op *findcase(struct op *t, const char *w)
2430{
2431 struct op **tp;
2432
2433 tp = find1case(t, w);
2434 return tp != NULL ? *tp : NULL;
2435}
2436
Eric Andersenff9eee42001-06-29 04:57:14 +00002437/*
2438 * execute tree
2439 */
2440
Denis Vlasenko7e497522008-02-12 09:51:03 +00002441static int execute(struct op *t, int *pin, int *pout, int no_fork)
Eric Andersenff9eee42001-06-29 04:57:14 +00002442{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002443 struct op *t1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002444 volatile int i, rv, a;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002445 const char *cp;
2446 char **wp, **wp2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002447 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002448 struct op *outtree_save;
Eric Andersenff9eee42001-06-29 04:57:14 +00002449 struct brkcon bc;
2450
2451#if __GNUC__
2452 /* Avoid longjmp clobbering */
2453 (void) &wp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002454#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002455
Eric Andersen12de6cf2004-08-04 19:19:10 +00002456 if (t == NULL) {
2457 DBGPRINTF4(("EXECUTE: enter, t==null, returning.\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002458 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002459 }
2460
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002461 DBGPRINTF(("EXECUTE: t=%p, t->op_type=%d (%s), t->op_words is %s\n", t,
2462 t->op_type, T_CMD_NAMES[t->op_type],
Denis Vlasenko509697f2008-03-02 12:49:39 +00002463 ((t->op_words == NULL) ? "NULL" : t->op_words[0])));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002464
Eric Andersenff9eee42001-06-29 04:57:14 +00002465 rv = 0;
2466 a = areanum++;
Denis Vlasenko509697f2008-03-02 12:49:39 +00002467 wp2 = t->op_words;
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002468 wp = (wp2 != NULL)
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002469 ? eval(wp2, t->op_type == TCOM ? DOALL : DOALL & ~DOKEY)
Eric Andersen8401eea2004-08-04 19:16:54 +00002470 : NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00002471
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002472 switch (t->op_type) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002473 case TDOT:
2474 DBGPRINTF3(("EXECUTE: TDOT\n"));
2475
2476 outtree_save = outtree;
2477
Denis Vlasenko509697f2008-03-02 12:49:39 +00002478 newfile(evalstr(t->op_words[0], DOALL));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002479
Denis Vlasenko68404f12008-03-17 09:00:54 +00002480 t->left = dowholefile(TLIST /*, 0*/);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002481 t->right = NULL;
2482
2483 outtree = outtree_save;
2484
2485 if (t->left)
Denis Vlasenko7e497522008-02-12 09:51:03 +00002486 rv = execute(t->left, pin, pout, /* no_fork: */ 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002487 if (t->right)
Denis Vlasenko7e497522008-02-12 09:51:03 +00002488 rv = execute(t->right, pin, pout, /* no_fork: */ 0);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002489 break;
2490
Eric Andersenff9eee42001-06-29 04:57:14 +00002491 case TPAREN:
Denis Vlasenko7e497522008-02-12 09:51:03 +00002492 rv = execute(t->left, pin, pout, /* no_fork: */ 0);
Eric Andersen737f5fb2003-03-14 16:05:59 +00002493 break;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002494
Eric Andersenff9eee42001-06-29 04:57:14 +00002495 case TCOM:
Denis Vlasenko7e497522008-02-12 09:51:03 +00002496 rv = forkexec(t, pin, pout, no_fork, wp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002497 break;
2498
2499 case TPIPE:
2500 {
Eric Andersen8401eea2004-08-04 19:16:54 +00002501 int pv[2];
2502
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002503 rv = openpipe(pv);
2504 if (rv < 0)
Eric Andersen8401eea2004-08-04 19:16:54 +00002505 break;
2506 pv[0] = remap(pv[0]);
2507 pv[1] = remap(pv[1]);
Denis Vlasenko7e497522008-02-12 09:51:03 +00002508 (void) execute(t->left, pin, pv, /* no_fork: */ 0);
2509 rv = execute(t->right, pv, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002510 }
2511 break;
2512
2513 case TLIST:
Denis Vlasenko7e497522008-02-12 09:51:03 +00002514 (void) execute(t->left, pin, pout, /* no_fork: */ 0);
2515 rv = execute(t->right, pin, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002516 break;
2517
2518 case TASYNC:
Eric Andersen8401eea2004-08-04 19:16:54 +00002519 {
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002520 smallint hinteractive = interactive;
Eric Andersenff9eee42001-06-29 04:57:14 +00002521
Eric Andersen12de6cf2004-08-04 19:19:10 +00002522 DBGPRINTF7(("EXECUTE: TASYNC clause, calling vfork()...\n"));
2523
Eric Andersen8401eea2004-08-04 19:16:54 +00002524 i = vfork();
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002525 if (i == 0) { /* child */
Eric Andersen8401eea2004-08-04 19:16:54 +00002526 signal(SIGINT, SIG_IGN);
2527 signal(SIGQUIT, SIG_IGN);
2528 if (interactive)
2529 signal(SIGTERM, SIG_DFL);
2530 interactive = 0;
2531 if (pin == NULL) {
2532 close(0);
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002533 xopen(bb_dev_null, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00002534 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002535 _exit(execute(t->left, pin, pout, /* no_fork: */ 1));
Eric Andersenff9eee42001-06-29 04:57:14 +00002536 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002537 interactive = hinteractive;
2538 if (i != -1) {
2539 setval(lookup("!"), putn(i));
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002540 closepipe(pin);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002541 if (interactive) {
2542 prs(putn(i));
2543 prs("\n");
2544 }
2545 } else
2546 rv = -1;
2547 setstatus(rv);
Eric Andersenff9eee42001-06-29 04:57:14 +00002548 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002549 break;
2550
2551 case TOR:
2552 case TAND:
Denis Vlasenko7e497522008-02-12 09:51:03 +00002553 rv = execute(t->left, pin, pout, /* no_fork: */ 0);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002554 t1 = t->right;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002555 if (t1 != NULL && (rv == 0) == (t->op_type == TAND))
Denis Vlasenko7e497522008-02-12 09:51:03 +00002556 rv = execute(t1, pin, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002557 break;
2558
2559 case TFOR:
2560 if (wp == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00002561 wp = dolv + 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002562 i = dolc;
2563 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00002564 i = 0;
2565 } else {
2566 i = -1;
Denis Vlasenko509697f2008-03-02 12:49:39 +00002567 while (*wp++ != NULL)
2568 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00002569 }
2570 vp = lookup(t->str);
2571 while (setjmp(bc.brkpt))
2572 if (isbreak)
2573 goto broken;
Denis Vlasenko7ae1cc12008-07-20 23:03:23 +00002574 /* Restore areanum value. It may be incremented by execute()
2575 * below, and then "continue" may jump back to setjmp above */
2576 areanum = a + 1;
2577 freearea(areanum + 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002578 brkset(&bc);
2579 for (t1 = t->left; i-- && *wp != NULL;) {
2580 setval(vp, *wp++);
Denis Vlasenko7e497522008-02-12 09:51:03 +00002581 rv = execute(t1, pin, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002582 }
2583 brklist = brklist->nextlev;
2584 break;
2585
2586 case TWHILE:
2587 case TUNTIL:
2588 while (setjmp(bc.brkpt))
2589 if (isbreak)
2590 goto broken;
Denis Vlasenko7ae1cc12008-07-20 23:03:23 +00002591 /* Restore areanum value. It may be incremented by execute()
2592 * below, and then "continue" may jump back to setjmp above */
2593 areanum = a + 1;
2594 freearea(areanum + 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002595 brkset(&bc);
2596 t1 = t->left;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002597 while ((execute(t1, pin, pout, /* no_fork: */ 0) == 0) == (t->op_type == TWHILE))
Denis Vlasenko7e497522008-02-12 09:51:03 +00002598 rv = execute(t->right, pin, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002599 brklist = brklist->nextlev;
2600 break;
2601
2602 case TIF:
2603 case TELIF:
Eric Andersen8401eea2004-08-04 19:16:54 +00002604 if (t->right != NULL) {
Denis Vlasenko7e497522008-02-12 09:51:03 +00002605 rv = !execute(t->left, pin, pout, /* no_fork: */ 0) ?
2606 execute(t->right->left, pin, pout, /* no_fork: */ 0) :
2607 execute(t->right->right, pin, pout, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002608 }
2609 break;
2610
2611 case TCASE:
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002612 cp = evalstr(t->str, DOSUB | DOTRIM);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002613 if (cp == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00002614 cp = "";
Eric Andersen12de6cf2004-08-04 19:19:10 +00002615
2616 DBGPRINTF7(("EXECUTE: TCASE, t->str is %s, cp is %s\n",
2617 ((t->str == NULL) ? "NULL" : t->str),
2618 ((cp == NULL) ? "NULL" : cp)));
2619
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002620 t1 = findcase(t->left, cp);
2621 if (t1 != NULL) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002622 DBGPRINTF7(("EXECUTE: TCASE, calling execute(t=%p, t1=%p)...\n", t, t1));
Denis Vlasenko7e497522008-02-12 09:51:03 +00002623 rv = execute(t1, pin, pout, /* no_fork: */ 0);
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002624 DBGPRINTF7(("EXECUTE: TCASE, back from execute(t=%p, t1=%p)...\n", t, t1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002625 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002626 break;
2627
2628 case TBRACE:
2629/*
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002630 iopp = t->ioact;
2631 if (i)
Eric Andersenff9eee42001-06-29 04:57:14 +00002632 while (*iopp)
2633 if (iosetup(*iopp++, pin!=NULL, pout!=NULL)) {
2634 rv = -1;
2635 break;
2636 }
2637*/
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002638 if (rv >= 0) {
2639 t1 = t->left;
2640 if (t1) {
Denis Vlasenko7e497522008-02-12 09:51:03 +00002641 rv = execute(t1, pin, pout, /* no_fork: */ 0);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002642 }
2643 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002644 break;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002645
2646 };
Eric Andersenff9eee42001-06-29 04:57:14 +00002647
Denis Vlasenkoe4712752007-04-14 15:08:41 +00002648 broken:
Denis Vlasenko509697f2008-03-02 12:49:39 +00002649// Restoring op_words is most likely not needed now: see comment in forkexec()
2650// (also take a look at exec builtin (doexec) - it touches t->op_words)
2651 t->op_words = wp2;
Eric Andersenff9eee42001-06-29 04:57:14 +00002652 isbreak = 0;
2653 freehere(areanum);
2654 freearea(areanum);
2655 areanum = a;
2656 if (interactive && intr) {
2657 closeall();
2658 fail();
2659 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002660
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002661 i = trapset;
2662 if (i != 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002663 trapset = 0;
2664 runtrap(i);
2665 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002666
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002667 DBGPRINTF(("EXECUTE: returning from t=%p, rv=%d\n", t, rv));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002668 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002669}
2670
Denis Vlasenkoe4712752007-04-14 15:08:41 +00002671static builtin_func_ptr inbuilt(const char *s)
2672{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002673 const struct builtincmd *bp;
2674
Denis Vlasenko95cb3262007-04-09 03:06:34 +00002675 for (bp = builtincmds; bp->name; bp++)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002676 if (strcmp(bp->name, s) == 0)
2677 return bp->builtinfunc;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002678 return NULL;
2679}
2680
Denis Vlasenko7e497522008-02-12 09:51:03 +00002681static int forkexec(struct op *t, int *pin, int *pout, int no_fork, char **wp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002682{
Eric Andersen12de6cf2004-08-04 19:19:10 +00002683 pid_t newpid;
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002684 int i;
2685 builtin_func_ptr bltin = NULL;
Denis Vlasenko7e497522008-02-12 09:51:03 +00002686 const char *bltin_name = NULL;
2687 const char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00002688 struct ioword **iopp;
2689 int resetsig;
2690 char **owp;
Denis Vlasenko7e497522008-02-12 09:51:03 +00002691 int forked;
Eric Andersenff9eee42001-06-29 04:57:14 +00002692
2693 int *hpin = pin;
2694 int *hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002695 char *hwp;
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002696 smallint hinteractive;
2697 smallint hintr;
2698 smallint hexecflg;
Eric Andersen8401eea2004-08-04 19:16:54 +00002699 struct brkcon *hbrklist;
Eric Andersenff9eee42001-06-29 04:57:14 +00002700
2701#if __GNUC__
2702 /* Avoid longjmp clobbering */
2703 (void) &pin;
2704 (void) &pout;
2705 (void) &wp;
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002706 (void) &bltin;
Eric Andersenff9eee42001-06-29 04:57:14 +00002707 (void) &cp;
2708 (void) &resetsig;
2709 (void) &owp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002710#endif
Eric Andersenff9eee42001-06-29 04:57:14 +00002711
Denis Vlasenko7e497522008-02-12 09:51:03 +00002712 DBGPRINTF(("FORKEXEC: t=%p, pin %p, pout %p, no_fork %d\n", t, pin,
2713 pout, no_fork));
Denis Vlasenko509697f2008-03-02 12:49:39 +00002714 DBGPRINTF7(("FORKEXEC: t->op_words is %s\n",
2715 ((t->op_words == NULL) ? "NULL" : t->op_words[0])));
Eric Andersenff9eee42001-06-29 04:57:14 +00002716 owp = wp;
2717 resetsig = 0;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002718 if (t->op_type == TCOM) {
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002719 while (*wp++ != NULL)
2720 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00002721 cp = *wp;
2722
2723 /* strip all initial assignments */
Denis Vlasenko7e497522008-02-12 09:51:03 +00002724 /* FIXME: not correct wrt PATH=yyy command etc */
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00002725 if (FLAG['x']) {
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002726 DBGPRINTF9(("FORKEXEC: echo'ing, cp=%p, wp=%p, owp=%p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00002727 cp, wp, owp));
Eric Andersen8401eea2004-08-04 19:16:54 +00002728 echo(cp ? wp : owp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002729 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002730
Denis Vlasenko7e497522008-02-12 09:51:03 +00002731 if (cp == NULL) {
2732 if (t->ioact == NULL) {
2733 while ((cp = *owp++) != NULL && assign(cp, COPYV))
2734 continue;
2735 DBGPRINTF(("FORKEXEC: returning setstatus(0)\n"));
2736 return setstatus(0);
2737 }
2738 } else { /* cp != NULL */
2739 bltin_name = cp;
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002740 bltin = inbuilt(cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002741 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002742 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002743
Denis Vlasenko7e497522008-02-12 09:51:03 +00002744 forked = 0;
Denis Vlasenko509697f2008-03-02 12:49:39 +00002745 // We were pointing t->op_words to temporary (expanded) arg list:
2746 // t->op_words = wp;
Denis Vlasenkofe218832008-03-01 09:35:39 +00002747 // and restored it later (in execute()), but "break"
Denis Vlasenko509697f2008-03-02 12:49:39 +00002748 // longjmps away (at "Run builtin" below), leaving t->op_words clobbered!
Denis Vlasenkofe218832008-03-01 09:35:39 +00002749 // See http://bugs.busybox.net/view.php?id=846.
Denis Vlasenko509697f2008-03-02 12:49:39 +00002750 // Now we do not touch t->op_words, but separately pass wp as param list
Denis Vlasenko42cc3042008-03-24 02:05:58 +00002751 // to builtins
Denis Vlasenko7e497522008-02-12 09:51:03 +00002752 DBGPRINTF(("FORKEXEC: bltin %p, no_fork %d, owp %p\n", bltin,
2753 no_fork, owp));
2754 /* Don't fork if it is a lone builtin (not in pipe)
2755 * OR we are told to _not_ fork */
2756 if ((!bltin || pin || pout) /* not lone bltin AND */
2757 && !no_fork /* not told to avoid fork */
2758 ) {
2759 /* Save values in case child alters them after vfork */
Eric Andersenff9eee42001-06-29 04:57:14 +00002760 hpin = pin;
2761 hpout = pout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002762 hwp = *wp;
2763 hinteractive = interactive;
2764 hintr = intr;
2765 hbrklist = brklist;
2766 hexecflg = execflg;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002767
Eric Andersen12de6cf2004-08-04 19:19:10 +00002768 DBGPRINTF3(("FORKEXEC: calling vfork()...\n"));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002769 newpid = vfork();
Eric Andersen12de6cf2004-08-04 19:19:10 +00002770 if (newpid == -1) {
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00002771 DBGPRINTF(("FORKEXEC: ERROR, can't vfork()!\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002772 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002773 }
2774
Denis Vlasenko489f93e2007-02-01 01:43:16 +00002775 if (newpid > 0) { /* Parent */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002776 /* Restore values */
Eric Andersenff9eee42001-06-29 04:57:14 +00002777 pin = hpin;
2778 pout = hpout;
Eric Andersenff9eee42001-06-29 04:57:14 +00002779 *wp = hwp;
2780 interactive = hinteractive;
2781 intr = hintr;
2782 brklist = hbrklist;
2783 execflg = hexecflg;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002784
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002785 closepipe(pin);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002786 return (pout == NULL ? setstatus(waitfor(newpid, 0)) : 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002787 }
2788
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002789 /* Child */
Denis Vlasenko7e497522008-02-12 09:51:03 +00002790 DBGPRINTF(("FORKEXEC: child process, bltin=%p (%s)\n", bltin, bltin_name));
Eric Andersenff9eee42001-06-29 04:57:14 +00002791 if (interactive) {
2792 signal(SIGINT, SIG_IGN);
2793 signal(SIGQUIT, SIG_IGN);
2794 resetsig = 1;
2795 }
2796 interactive = 0;
2797 intr = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002798 forked = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002799 brklist = 0;
2800 execflg = 0;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00002801 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002802
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002803 if (owp)
Eric Andersenff9eee42001-06-29 04:57:14 +00002804 while ((cp = *owp++) != NULL && assign(cp, COPYV))
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002805 if (!bltin)
Eric Andersenff9eee42001-06-29 04:57:14 +00002806 export(lookup(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002807
Denis Vlasenko284d0fa2008-02-16 13:18:17 +00002808 if (pin) { /* NB: close _first_, then move fds! */
2809 close(pin[1]);
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002810 xmove_fd(pin[0], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00002811 }
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002812 if (pout) {
Denis Vlasenko284d0fa2008-02-16 13:18:17 +00002813 close(pout[0]);
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00002814 xmove_fd(pout[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00002815 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002816
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002817 iopp = t->ioact;
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002818 if (iopp) {
2819 if (bltin && bltin != doexec) {
Denis Vlasenko7e497522008-02-12 09:51:03 +00002820 prs(bltin_name);
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00002821 err(": can't redirect shell command");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002822 if (forked)
2823 _exit(-1);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002824 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002825 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002826 while (*iopp) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00002827 if (iosetup(*iopp++, pin != NULL, pout != NULL)) {
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002828 /* system-detected error */
Eric Andersen12de6cf2004-08-04 19:19:10 +00002829 if (forked)
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002830 _exit(-1);
2831 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002832 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002833 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002834 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002835
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002836 if (bltin) {
Denis Vlasenko7e497522008-02-12 09:51:03 +00002837 if (forked || pin || pout) {
2838 /* Builtin in pipe: disallowed */
2839 /* TODO: allow "exec"? */
2840 prs(bltin_name);
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00002841 err(": can't run builtin as part of pipe");
Denis Vlasenko7e497522008-02-12 09:51:03 +00002842 if (forked)
2843 _exit(-1);
2844 return -1;
2845 }
Denis Vlasenkofe218832008-03-01 09:35:39 +00002846 /* Run builtin */
2847 i = setstatus(bltin(t, wp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002848 if (forked)
2849 _exit(i);
2850 DBGPRINTF(("FORKEXEC: returning i=%d\n", i));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00002851 return i;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002852 }
2853
Eric Andersenff9eee42001-06-29 04:57:14 +00002854 /* should use FIOCEXCL */
Eric Andersen8401eea2004-08-04 19:16:54 +00002855 for (i = FDBASE; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00002856 close(i);
2857 if (resetsig) {
2858 signal(SIGINT, SIG_DFL);
2859 signal(SIGQUIT, SIG_DFL);
2860 }
Eric Andersenff9eee42001-06-29 04:57:14 +00002861
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002862 if (t->op_type == TPAREN)
Denis Vlasenko7e497522008-02-12 09:51:03 +00002863 _exit(execute(t->left, NOPIPE, NOPIPE, /* no_fork: */ 1));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002864 if (wp[0] == NULL)
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00002865 _exit(EXIT_SUCCESS);
Eric Andersen12de6cf2004-08-04 19:19:10 +00002866
Eric Andersenfd7a4c82004-09-02 23:13:10 +00002867 cp = rexecve(wp[0], wp, makenv(0, NULL));
Eric Andersen8401eea2004-08-04 19:16:54 +00002868 prs(wp[0]);
2869 prs(": ");
Eric Andersen12de6cf2004-08-04 19:19:10 +00002870 err(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00002871 if (!execflg)
2872 trap[0] = NULL;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002873
Denis Vlasenko7e497522008-02-12 09:51:03 +00002874 DBGPRINTF(("FORKEXEC: calling leave(), pid=%d\n", getpid()));
Eric Andersen12de6cf2004-08-04 19:19:10 +00002875
Eric Andersenff9eee42001-06-29 04:57:14 +00002876 leave();
2877 /* NOTREACHED */
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00002878 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002879}
2880
2881/*
2882 * 0< 1> are ignored as required
2883 * within pipelines.
2884 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002885static int iosetup(struct ioword *iop, int pipein, int pipeout)
Eric Andersenff9eee42001-06-29 04:57:14 +00002886{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002887 int u = -1;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002888 char *cp = NULL;
2889 const char *msg;
Eric Andersenff9eee42001-06-29 04:57:14 +00002890
Mike Frysinger02d8fa42006-05-05 20:32:31 +00002891 DBGPRINTF(("IOSETUP: iop %p, pipein %i, pipeout %i\n", iop,
Eric Andersen12de6cf2004-08-04 19:19:10 +00002892 pipein, pipeout));
2893
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002894 if (iop->io_fd == IODEFAULT) /* take default */
2895 iop->io_fd = iop->io_flag & (IOREAD | IOHERE) ? 0 : 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002896
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002897 if (pipein && iop->io_fd == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002898 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002899
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002900 if (pipeout && iop->io_fd == 1)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002901 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00002902
Eric Andersen8401eea2004-08-04 19:16:54 +00002903 msg = iop->io_flag & (IOREAD | IOHERE) ? "open" : "create";
Eric Andersenff9eee42001-06-29 04:57:14 +00002904 if ((iop->io_flag & IOHERE) == 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002905 cp = iop->io_name; /* huh?? */
2906 cp = evalstr(cp, DOSUB | DOTRIM);
2907 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002908 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002909 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00002910
Eric Andersenff9eee42001-06-29 04:57:14 +00002911 if (iop->io_flag & IODUP) {
2912 if (cp[1] || (!isdigit(*cp) && *cp != '-')) {
2913 prs(cp);
2914 err(": illegal >& argument");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002915 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00002916 }
2917 if (*cp == '-')
2918 iop->io_flag = IOCLOSE;
Eric Andersen8401eea2004-08-04 19:16:54 +00002919 iop->io_flag &= ~(IOREAD | IOWRITE);
Eric Andersenff9eee42001-06-29 04:57:14 +00002920 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002921
Eric Andersenff9eee42001-06-29 04:57:14 +00002922 switch (iop->io_flag) {
2923 case IOREAD:
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002924 u = open(cp, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00002925 break;
2926
2927 case IOHERE:
Eric Andersen8401eea2004-08-04 19:16:54 +00002928 case IOHERE | IOXHERE:
2929 u = herein(iop->io_name, iop->io_flag & IOXHERE);
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00002930 cp = (char*)"here file";
Eric Andersenff9eee42001-06-29 04:57:14 +00002931 break;
2932
Eric Andersen8401eea2004-08-04 19:16:54 +00002933 case IOWRITE | IOCAT:
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00002934 u = open(cp, O_WRONLY);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002935 if (u >= 0) {
Denis Vlasenkoea620772006-10-14 02:23:43 +00002936 lseek(u, (long) 0, SEEK_END);
Eric Andersenff9eee42001-06-29 04:57:14 +00002937 break;
2938 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002939 /* fall through to creation if >>file doesn't exist */
2940
Eric Andersenff9eee42001-06-29 04:57:14 +00002941 case IOWRITE:
2942 u = creat(cp, 0666);
2943 break;
2944
2945 case IODUP:
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002946 u = dup2(*cp - '0', iop->io_fd);
Eric Andersenff9eee42001-06-29 04:57:14 +00002947 break;
2948
2949 case IOCLOSE:
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002950 close(iop->io_fd);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002951 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002952 }
Denis Vlasenko7e497522008-02-12 09:51:03 +00002953
Eric Andersenff9eee42001-06-29 04:57:14 +00002954 if (u < 0) {
2955 prs(cp);
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00002956 prs(": can't ");
Eric Andersenff9eee42001-06-29 04:57:14 +00002957 warn(msg);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002958 return 1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00002959 }
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00002960 xmove_fd(u, iop->io_fd);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00002961 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00002962}
2963
Eric Andersenff9eee42001-06-29 04:57:14 +00002964/*
2965 * Enter a new loop level (marked for break/continue).
2966 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00002967static void brkset(struct brkcon *bc)
Eric Andersenff9eee42001-06-29 04:57:14 +00002968{
2969 bc->nextlev = brklist;
2970 brklist = bc;
2971}
2972
2973/*
2974 * Wait for the last process created.
2975 * Print a message for each process found
2976 * that was killed by a signal.
2977 * Ignore interrupt signals while waiting
2978 * unless `canintr' is true.
2979 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002980static int waitfor(int lastpid, int canintr)
Eric Andersenff9eee42001-06-29 04:57:14 +00002981{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00002982 int pid, rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00002983 int s;
Denis Vlasenko648b44f2008-02-12 06:04:06 +00002984 smallint oheedint = heedint;
Eric Andersenff9eee42001-06-29 04:57:14 +00002985
2986 heedint = 0;
2987 rv = 0;
2988 do {
2989 pid = wait(&s);
2990 if (pid == -1) {
2991 if (errno != EINTR || canintr)
2992 break;
2993 } else {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00002994 rv = WAITSIG(s);
2995 if (rv != 0) {
Denis Vlasenko80b8b392007-06-25 10:55:35 +00002996 if (rv < ARRAY_SIZE(signame)) {
Eric Andersenff9eee42001-06-29 04:57:14 +00002997 if (signame[rv] != NULL) {
2998 if (pid != lastpid) {
2999 prn(pid);
3000 prs(": ");
3001 }
3002 prs(signame[rv]);
3003 }
3004 } else {
3005 if (pid != lastpid) {
3006 prn(pid);
3007 prs(": ");
3008 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003009 prs("Signal ");
3010 prn(rv);
3011 prs(" ");
Eric Andersenff9eee42001-06-29 04:57:14 +00003012 }
3013 if (WAITCORE(s))
3014 prs(" - core dumped");
Denis Vlasenko80b8b392007-06-25 10:55:35 +00003015 if (rv >= ARRAY_SIZE(signame) || signame[rv])
Eric Andersenff9eee42001-06-29 04:57:14 +00003016 prs("\n");
Mike Frysingerb81f97b2008-05-14 11:51:04 +00003017 rv |= 0x80;
Eric Andersenff9eee42001-06-29 04:57:14 +00003018 } else
3019 rv = WAITVAL(s);
3020 }
3021 } while (pid != lastpid);
3022 heedint = oheedint;
3023 if (intr) {
3024 if (interactive) {
3025 if (canintr)
3026 intr = 0;
3027 } else {
Eric Andersen8401eea2004-08-04 19:16:54 +00003028 if (exstat == 0)
3029 exstat = rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003030 onintr(0);
3031 }
3032 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003033 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003034}
3035
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003036static int setstatus(int s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003037{
3038 exstat = s;
3039 setval(lookup("?"), putn(s));
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003040 return s;
Eric Andersenff9eee42001-06-29 04:57:14 +00003041}
3042
3043/*
3044 * PATH-searching interface to execve.
3045 * If getenv("PATH") were kept up-to-date,
3046 * execvp might be used.
3047 */
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003048static const char *rexecve(char *c, char **v, char **envp)
Eric Andersenff9eee42001-06-29 04:57:14 +00003049{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003050 const char *sp;
3051 char *tp;
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00003052 int asis = 0;
Eric Andersen1c039232001-07-07 00:05:55 +00003053 char *name = c;
Eric Andersen8401eea2004-08-04 19:16:54 +00003054
Denis Vlasenko80d14be2007-04-10 23:03:30 +00003055 if (ENABLE_FEATURE_SH_STANDALONE) {
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003056 if (find_applet_by_name(name) >= 0) {
Rob Landleya299efb2006-08-10 21:46:43 +00003057 /* We have to exec here since we vforked. Running
Denis Vlasenkoe4f2d062007-04-11 17:03:19 +00003058 * run_applet_and_exit() won't work and bad things
Rob Landleya299efb2006-08-10 21:46:43 +00003059 * will happen. */
Denis Vlasenkobdbbb7e2007-06-08 15:02:55 +00003060 execve(bb_busybox_exec_path, v, envp);
Rob Landleya299efb2006-08-10 21:46:43 +00003061 }
Eric Andersen1c039232001-07-07 00:05:55 +00003062 }
Eric Andersen1c039232001-07-07 00:05:55 +00003063
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003064 DBGPRINTF(("REXECVE: c=%p, v=%p, envp=%p\n", c, v, envp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003065
Eric Andersen8401eea2004-08-04 19:16:54 +00003066 sp = any('/', c) ? "" : path->value;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003067 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003068 while (asis || *sp != '\0') {
3069 asis = 0;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003070 tp = global_env.linep;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003071 for (; *sp != '\0'; tp++) {
3072 *tp = *sp++;
3073 if (*tp == ':') {
3074 asis = (*sp == '\0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003075 break;
3076 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003077 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003078 if (tp != global_env.linep)
Eric Andersenff9eee42001-06-29 04:57:14 +00003079 *tp++ = '/';
Denis Vlasenko509697f2008-03-02 12:49:39 +00003080 strcpy(tp, c);
Eric Andersen1c039232001-07-07 00:05:55 +00003081
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003082 DBGPRINTF3(("REXECVE: global_env.linep is %s\n", global_env.linep));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003083
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003084 execve(global_env.linep, v, envp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003085
Eric Andersenff9eee42001-06-29 04:57:14 +00003086 switch (errno) {
3087 case ENOEXEC:
Denis Vlasenko447bd662008-05-30 22:28:32 +00003088 /* File is executable but file format isnt recognized */
3089 /* Run it as a shell script */
3090 /* (execve above didnt do it itself, unlike execvp) */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003091 *v = global_env.linep;
Denis Vlasenko509697f2008-03-02 12:49:39 +00003092 v--;
3093 tp = *v;
Denis Vlasenko447bd662008-05-30 22:28:32 +00003094 *v = (char*)DEFAULT_SHELL;
Glenn L McGrathdc4e75e2003-09-02 02:36:18 +00003095 execve(DEFAULT_SHELL, v, envp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003096 *v = tp;
Denis Vlasenko509697f2008-03-02 12:49:39 +00003097 return "no shell";
Eric Andersenff9eee42001-06-29 04:57:14 +00003098
3099 case ENOMEM:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003100 return (char *) bb_msg_memory_exhausted;
Eric Andersenff9eee42001-06-29 04:57:14 +00003101
3102 case E2BIG:
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003103 return "argument list too long";
Eric Andersenff9eee42001-06-29 04:57:14 +00003104 }
3105 }
Denis Vlasenko447bd662008-05-30 22:28:32 +00003106 if (errno == ENOENT) {
3107 exstat = 127; /* standards require this */
3108 return "not found";
3109 }
3110 exstat = 126; /* mimic bash */
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00003111 return "can't execute";
Eric Andersenff9eee42001-06-29 04:57:14 +00003112}
3113
3114/*
3115 * Run the command produced by generator `f'
3116 * applied to stream `arg'.
3117 */
Eric Andersen8401eea2004-08-04 19:16:54 +00003118static int run(struct ioarg *argp, int (*f) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00003119{
3120 struct op *otree;
3121 struct wdblock *swdlist;
3122 struct wdblock *siolist;
3123 jmp_buf ev, rt;
3124 xint *ofail;
3125 int rv;
3126
3127#if __GNUC__
3128 /* Avoid longjmp clobbering */
3129 (void) &rv;
3130#endif
3131
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003132 DBGPRINTF(("RUN: enter, areanum %d, outtree %p, failpt %p\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003133 areanum, outtree, failpt));
3134
Eric Andersenff9eee42001-06-29 04:57:14 +00003135 areanum++;
3136 swdlist = wdlist;
3137 siolist = iolist;
3138 otree = outtree;
3139 ofail = failpt;
3140 rv = -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003141
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003142 errpt = ev;
3143 if (newenv(setjmp(errpt)) == 0) {
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00003144 wdlist = NULL;
3145 iolist = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003146 pushio(argp, f);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003147 global_env.iobase = global_env.iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00003148 yynerrs = 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003149 failpt = rt;
3150 if (setjmp(failpt) == 0 && yyparse() == 0)
Denis Vlasenko7e497522008-02-12 09:51:03 +00003151 rv = execute(outtree, NOPIPE, NOPIPE, /* no_fork: */ 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003152 quitenv();
Eric Andersen12de6cf2004-08-04 19:19:10 +00003153 } else {
3154 DBGPRINTF(("RUN: error from newenv()!\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00003155 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00003156
Eric Andersenff9eee42001-06-29 04:57:14 +00003157 wdlist = swdlist;
3158 iolist = siolist;
3159 failpt = ofail;
3160 outtree = otree;
3161 freearea(areanum--);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003162
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003163 return rv;
Eric Andersenff9eee42001-06-29 04:57:14 +00003164}
3165
3166/* -------- do.c -------- */
3167
3168/*
3169 * built-in commands: doX
3170 */
3171
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003172static int dohelp(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM)
Eric Andersen1c039232001-07-07 00:05:55 +00003173{
3174 int col;
3175 const struct builtincmd *x;
3176
Denis Vlasenko34d4d892009-04-04 20:24:37 +00003177 printf("\n"
3178 "Built-in commands:\n"
3179 "------------------\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003180
Denis Vlasenko95cb3262007-04-09 03:06:34 +00003181 col = 0;
3182 x = builtincmds;
3183 while (x->name) {
3184 col += printf("%c%s", ((col == 0) ? '\t' : ' '), x->name);
Eric Andersen1c039232001-07-07 00:05:55 +00003185 if (col > 60) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00003186 bb_putchar('\n');
Eric Andersen1c039232001-07-07 00:05:55 +00003187 col = 0;
3188 }
Denis Vlasenko95cb3262007-04-09 03:06:34 +00003189 x++;
Eric Andersen1c039232001-07-07 00:05:55 +00003190 }
Denis Vlasenko80d14be2007-04-10 23:03:30 +00003191#if ENABLE_FEATURE_SH_STANDALONE
Eric Andersen1c039232001-07-07 00:05:55 +00003192 {
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003193 const char *applet = applet_names;
Eric Andersen1c039232001-07-07 00:05:55 +00003194
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003195 while (*applet) {
3196 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applet);
Eric Andersen1c039232001-07-07 00:05:55 +00003197 if (col > 60) {
Denis Vlasenko4daad902007-09-27 10:20:47 +00003198 bb_putchar('\n');
Eric Andersen1c039232001-07-07 00:05:55 +00003199 col = 0;
3200 }
Denis Vlasenko1aa7e472007-11-28 06:49:03 +00003201 applet += strlen(applet) + 1;
Eric Andersen1c039232001-07-07 00:05:55 +00003202 }
3203 }
3204#endif
Denis Vlasenko0ee39992006-12-24 15:23:28 +00003205 puts("\n");
Eric Andersen1c039232001-07-07 00:05:55 +00003206 return EXIT_SUCCESS;
3207}
3208
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003209static int dolabel(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM)
Eric Andersenff9eee42001-06-29 04:57:14 +00003210{
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003211 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003212}
3213
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003214static int dochdir(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003215{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003216 const char *cp, *er;
Eric Andersenff9eee42001-06-29 04:57:14 +00003217
Denis Vlasenkofe218832008-03-01 09:35:39 +00003218 cp = args[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003219 if (cp == NULL) {
3220 cp = homedir->value;
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003221 if (cp != NULL)
3222 goto do_cd;
3223 er = ": no home directory";
3224 } else {
3225 do_cd:
3226 if (chdir(cp) >= 0)
3227 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003228 er = ": bad directory";
Denis Vlasenkod244c5e2007-02-09 17:30:14 +00003229 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003230 prs(cp != NULL ? cp : "cd");
Eric Andersenff9eee42001-06-29 04:57:14 +00003231 err(er);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003232 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003233}
3234
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003235static int doshift(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003236{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003237 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003238
Denis Vlasenkofe218832008-03-01 09:35:39 +00003239 n = args[1] ? getn(args[1]) : 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003240 if (dolc < n) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003241 err("nothing to shift");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003242 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003243 }
3244 dolv[n] = dolv[0];
3245 dolv += n;
3246 dolc -= n;
3247 setval(lookup("#"), putn(dolc));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003248 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003249}
3250
3251/*
3252 * execute login and newgrp directly
3253 */
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003254static int dologin(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003255{
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003256 const char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003257
3258 if (interactive) {
3259 signal(SIGINT, SIG_DFL);
3260 signal(SIGQUIT, SIG_DFL);
3261 }
Denis Vlasenkofe218832008-03-01 09:35:39 +00003262 cp = rexecve(args[0], args, makenv(0, NULL));
3263 prs(args[0]);
Eric Andersen8401eea2004-08-04 19:16:54 +00003264 prs(": ");
3265 err(cp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003266 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003267}
3268
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003269static int doumask(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003270{
Denis Vlasenko7e497522008-02-12 09:51:03 +00003271 int i;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003272 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003273
Denis Vlasenkofe218832008-03-01 09:35:39 +00003274 cp = args[1];
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003275 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003276 i = umask(0);
3277 umask(i);
Denis Vlasenko7e497522008-02-12 09:51:03 +00003278 printf("%04o\n", i);
Eric Andersenff9eee42001-06-29 04:57:14 +00003279 } else {
Denis Vlasenko7e497522008-02-12 09:51:03 +00003280 i = bb_strtou(cp, NULL, 8);
3281 if (errno) {
3282 err("umask: bad octal number");
3283 return 1;
3284 }
3285 umask(i);
Eric Andersenff9eee42001-06-29 04:57:14 +00003286 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003287 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003288}
3289
Denis Vlasenkofe218832008-03-01 09:35:39 +00003290static int doexec(struct op *t, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003291{
Eric Andersenff9eee42001-06-29 04:57:14 +00003292 jmp_buf ex;
3293 xint *ofail;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003294 char **sv_words;
Eric Andersenff9eee42001-06-29 04:57:14 +00003295
3296 t->ioact = NULL;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003297 if (!args[1])
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003298 return 1;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003299
Eric Andersenff9eee42001-06-29 04:57:14 +00003300 execflg = 1;
3301 ofail = failpt;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003302 failpt = ex;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003303
Denis Vlasenko509697f2008-03-02 12:49:39 +00003304 sv_words = t->op_words;
3305 t->op_words = args + 1;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003306// TODO: test what will happen with "exec break" -
Denis Vlasenko509697f2008-03-02 12:49:39 +00003307// will it leave t->op_words pointing to garbage?
Denis Vlasenkofe218832008-03-01 09:35:39 +00003308// (see http://bugs.busybox.net/view.php?id=846)
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003309 if (setjmp(failpt) == 0)
Denis Vlasenko7e497522008-02-12 09:51:03 +00003310 execute(t, NOPIPE, NOPIPE, /* no_fork: */ 1);
Denis Vlasenko509697f2008-03-02 12:49:39 +00003311 t->op_words = sv_words;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003312
Eric Andersenff9eee42001-06-29 04:57:14 +00003313 failpt = ofail;
3314 execflg = 0;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003315
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003316 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003317}
3318
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003319static int dodot(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003320{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003321 int i;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003322 const char *sp;
3323 char *tp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003324 char *cp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003325 int maltmp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003326
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003327 DBGPRINTF(("DODOT: enter, t=%p, tleft %p, tright %p, global_env.linep is %s\n",
3328 t, t->left, t->right, ((global_env.linep == NULL) ? "NULL" : global_env.linep)));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003329
Denis Vlasenkofe218832008-03-01 09:35:39 +00003330 cp = args[1];
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003331 if (cp == NULL) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00003332 DBGPRINTF(("DODOT: bad args, ret 0\n"));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003333 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003334 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003335 DBGPRINTF(("DODOT: cp is %s\n", cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003336
Eric Andersen8401eea2004-08-04 19:16:54 +00003337 sp = any('/', cp) ? ":" : path->value;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003338
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003339 DBGPRINTF(("DODOT: sp is %s, global_env.linep is %s\n",
Eric Andersen12de6cf2004-08-04 19:19:10 +00003340 ((sp == NULL) ? "NULL" : sp),
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003341 ((global_env.linep == NULL) ? "NULL" : global_env.linep)));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003342
Eric Andersenff9eee42001-06-29 04:57:14 +00003343 while (*sp) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003344 tp = global_env.linep;
Eric Andersenff9eee42001-06-29 04:57:14 +00003345 while (*sp && (*tp = *sp++) != ':')
3346 tp++;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003347 if (tp != global_env.linep)
Eric Andersenff9eee42001-06-29 04:57:14 +00003348 *tp++ = '/';
Denis Vlasenko509697f2008-03-02 12:49:39 +00003349 strcpy(tp, cp);
Eric Andersen12de6cf2004-08-04 19:19:10 +00003350
3351 /* Original code */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003352 i = open(global_env.linep, O_RDONLY);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003353 if (i >= 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003354 exstat = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003355 maltmp = remap(i);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003356 DBGPRINTF(("DODOT: remap=%d, exstat=%d, global_env.iofd %d, i %d, global_env.linep is %s\n",
3357 maltmp, exstat, global_env.iofd, i, global_env.linep));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003358
3359 next(maltmp); /* Basically a PUSHIO */
3360
3361 DBGPRINTF(("DODOT: returning exstat=%d\n", exstat));
3362
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003363 return exstat;
Eric Andersenff9eee42001-06-29 04:57:14 +00003364 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003365 } /* while */
Eric Andersen12de6cf2004-08-04 19:19:10 +00003366
Eric Andersenff9eee42001-06-29 04:57:14 +00003367 prs(cp);
3368 err(": not found");
Eric Andersen12de6cf2004-08-04 19:19:10 +00003369
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003370 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003371}
3372
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003373static int dowait(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003374{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003375 int i;
3376 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003377
Denis Vlasenkofe218832008-03-01 09:35:39 +00003378 cp = args[1];
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003379 if (cp != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003380 i = getn(cp);
3381 if (i == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003382 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003383 } else
3384 i = -1;
3385 setstatus(waitfor(i, 1));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003386 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003387}
3388
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003389static int doread(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003390{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003391 char *cp, **wp;
3392 int nb = 0;
3393 int nl = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003394
Denis Vlasenkofe218832008-03-01 09:35:39 +00003395 if (args[1] == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003396 err("Usage: read name ...");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003397 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003398 }
Denis Vlasenkofe218832008-03-01 09:35:39 +00003399 for (wp = args + 1; *wp; wp++) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003400 for (cp = global_env.linep; !nl && cp < elinep - 1; cp++) {
Bernhard Reutner-Fischer5e25ddb2008-05-19 09:48:17 +00003401 nb = nonblock_safe_read(STDIN_FILENO, cp, sizeof(*cp));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003402 if (nb != sizeof(*cp))
Eric Andersenff9eee42001-06-29 04:57:14 +00003403 break;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003404 nl = (*cp == '\n');
3405 if (nl || (wp[1] && any(*cp, ifs->value)))
3406 break;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003407 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003408 *cp = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003409 if (nb <= 0)
3410 break;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003411 setval(lookup(*wp), global_env.linep);
Eric Andersenff9eee42001-06-29 04:57:14 +00003412 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003413 return nb <= 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003414}
3415
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003416static int doeval(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003417{
Denis Vlasenkofe218832008-03-01 09:35:39 +00003418 return RUN(awordlist, args + 1, wdchar);
Eric Andersenff9eee42001-06-29 04:57:14 +00003419}
3420
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003421static int dotrap(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003422{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003423 int n, i;
3424 int resetsig;
Eric Andersenff9eee42001-06-29 04:57:14 +00003425
Denis Vlasenkofe218832008-03-01 09:35:39 +00003426 if (args[1] == NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00003427 for (i = 0; i <= _NSIG; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003428 if (trap[i]) {
3429 prn(i);
3430 prs(": ");
3431 prs(trap[i]);
3432 prs("\n");
3433 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003434 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003435 }
Denis Vlasenkofe218832008-03-01 09:35:39 +00003436 resetsig = isdigit(args[1][0]);
3437 for (i = resetsig ? 1 : 2; args[i] != NULL; ++i) {
3438 n = getsig(args[i]);
Eric Andersenff9eee42001-06-29 04:57:14 +00003439 freecell(trap[n]);
3440 trap[n] = 0;
3441 if (!resetsig) {
Denis Vlasenkofe218832008-03-01 09:35:39 +00003442 if (args[1][0] != '\0') {
3443 trap[n] = strsave(args[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003444 setsig(n, sig);
3445 } else
3446 setsig(n, SIG_IGN);
3447 } else {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003448 if (interactive) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003449 if (n == SIGINT)
3450 setsig(n, onintr);
3451 else
Eric Andersen8401eea2004-08-04 19:16:54 +00003452 setsig(n, n == SIGQUIT ? SIG_IGN : SIG_DFL);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00003453 } else
Eric Andersenff9eee42001-06-29 04:57:14 +00003454 setsig(n, SIG_DFL);
3455 }
3456 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003457 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003458}
3459
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003460static int getsig(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003461{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003462 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003463
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003464 n = getn(s);
3465 if (n < 0 || n > _NSIG) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003466 err("trap: bad signal number");
3467 n = 0;
3468 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003469 return n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003470}
3471
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003472static void setsig(int n, sighandler_t f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003473{
3474 if (n == 0)
3475 return;
3476 if (signal(n, SIG_IGN) != SIG_IGN || ourtrap[n]) {
3477 ourtrap[n] = 1;
3478 signal(n, f);
3479 }
3480}
3481
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003482static int getn(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00003483{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003484 char *s;
3485 int n, m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003486
3487 s = as;
3488 m = 1;
3489 if (*s == '-') {
3490 m = -1;
3491 s++;
3492 }
3493 for (n = 0; isdigit(*s); s++)
Eric Andersen8401eea2004-08-04 19:16:54 +00003494 n = (n * 10) + (*s - '0');
Eric Andersenff9eee42001-06-29 04:57:14 +00003495 if (*s) {
3496 prs(as);
3497 err(": bad number");
3498 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003499 return n * m;
Eric Andersenff9eee42001-06-29 04:57:14 +00003500}
3501
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003502static int dobreak(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003503{
Denis Vlasenkofe218832008-03-01 09:35:39 +00003504 return brkcontin(args[1], 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003505}
3506
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003507static int docontinue(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003508{
Denis Vlasenkofe218832008-03-01 09:35:39 +00003509 return brkcontin(args[1], 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003510}
3511
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003512static int brkcontin(char *cp, int val)
Eric Andersenff9eee42001-06-29 04:57:14 +00003513{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003514 struct brkcon *bc;
3515 int nl;
Eric Andersenff9eee42001-06-29 04:57:14 +00003516
Eric Andersen8401eea2004-08-04 19:16:54 +00003517 nl = cp == NULL ? 1 : getn(cp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003518 if (nl <= 0)
3519 nl = 999;
3520 do {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003521 bc = brklist;
3522 if (bc == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003523 break;
3524 brklist = bc->nextlev;
3525 } while (--nl);
3526 if (nl) {
3527 err("bad break/continue level");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003528 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003529 }
Denis Vlasenko648b44f2008-02-12 06:04:06 +00003530 isbreak = (val != 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003531 longjmp(bc->brkpt, 1);
3532 /* NOTREACHED */
3533}
3534
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003535static int doexit(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003536{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003537 char *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003538
3539 execflg = 0;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003540 cp = args[1];
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003541 if (cp != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00003542 setstatus(getn(cp));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003543
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003544 DBGPRINTF(("DOEXIT: calling leave(), t=%p\n", t));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003545
Eric Andersenff9eee42001-06-29 04:57:14 +00003546 leave();
3547 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003548 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003549}
3550
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003551static int doexport(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003552{
Denis Vlasenkofe218832008-03-01 09:35:39 +00003553 rdexp(args + 1, export, EXPORT);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003554 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003555}
3556
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003557static int doreadonly(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003558{
Denis Vlasenkofe218832008-03-01 09:35:39 +00003559 rdexp(args + 1, ronly, RONLY);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003560 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003561}
3562
Eric Andersen8401eea2004-08-04 19:16:54 +00003563static void rdexp(char **wp, void (*f) (struct var *), int key)
Eric Andersenff9eee42001-06-29 04:57:14 +00003564{
Mike Frysinger02d8fa42006-05-05 20:32:31 +00003565 DBGPRINTF6(("RDEXP: enter, wp=%p, func=%p, key=%d\n", wp, f, key));
Eric Andersen12de6cf2004-08-04 19:19:10 +00003566 DBGPRINTF6(("RDEXP: *wp=%s\n", *wp));
3567
Eric Andersenff9eee42001-06-29 04:57:14 +00003568 if (*wp != NULL) {
Matt Kraaif69bfc72001-07-12 19:39:59 +00003569 for (; *wp != NULL; wp++) {
3570 if (isassign(*wp)) {
3571 char *cp;
Eric Andersen8401eea2004-08-04 19:16:54 +00003572
Matt Kraaif69bfc72001-07-12 19:39:59 +00003573 assign(*wp, COPYV);
Denis Vlasenko509697f2008-03-02 12:49:39 +00003574 for (cp = *wp; *cp != '='; cp++)
3575 continue;
Matt Kraaif69bfc72001-07-12 19:39:59 +00003576 *cp = '\0';
3577 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003578 if (checkname(*wp))
Eric Andersen8401eea2004-08-04 19:16:54 +00003579 (*f) (lookup(*wp));
Eric Andersenff9eee42001-06-29 04:57:14 +00003580 else
3581 badid(*wp);
Matt Kraaif69bfc72001-07-12 19:39:59 +00003582 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003583 } else
3584 putvlist(key, 1);
3585}
3586
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003587static void badid(char *s)
Eric Andersenff9eee42001-06-29 04:57:14 +00003588{
3589 prs(s);
3590 err(": bad identifier");
3591}
3592
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003593static int doset(struct op *t UNUSED_PARAM, char **args)
Eric Andersenff9eee42001-06-29 04:57:14 +00003594{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003595 struct var *vp;
3596 char *cp;
3597 int n;
Eric Andersenff9eee42001-06-29 04:57:14 +00003598
Denis Vlasenkofe218832008-03-01 09:35:39 +00003599 cp = args[1];
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003600 if (cp == NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003601 for (vp = vlist; vp; vp = vp->next)
Denis Vlasenko73c571a2009-03-09 00:12:37 +00003602 varput(vp->name, STDOUT_FILENO);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003603 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003604 }
3605 if (*cp == '-') {
Denis Vlasenkofe218832008-03-01 09:35:39 +00003606 args++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003607 if (*++cp == 0)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003608 FLAG['x'] = FLAG['v'] = 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003609 else {
3610 for (; *cp; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003611 switch (*cp) {
3612 case 'e':
3613 if (!interactive)
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003614 FLAG['e']++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003615 break;
3616
3617 default:
Eric Andersen8401eea2004-08-04 19:16:54 +00003618 if (*cp >= 'a' && *cp <= 'z')
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003619 FLAG[(int) *cp]++;
Eric Andersenff9eee42001-06-29 04:57:14 +00003620 break;
3621 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003622 }
3623 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003624 setdash();
3625 }
Denis Vlasenkofe218832008-03-01 09:35:39 +00003626 if (args[1]) {
3627 args[0] = dolv[0];
3628 for (n = 1; args[n]; n++)
3629 setarea((char *) args[n], 0);
Eric Andersen8401eea2004-08-04 19:16:54 +00003630 dolc = n - 1;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003631 dolv = args;
Eric Andersenff9eee42001-06-29 04:57:14 +00003632 setval(lookup("#"), putn(dolc));
Eric Andersen8401eea2004-08-04 19:16:54 +00003633 setarea((char *) (dolv - 1), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00003634 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003635 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003636}
3637
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003638static void varput(char *s, int out)
Eric Andersenff9eee42001-06-29 04:57:14 +00003639{
Matt Kraai69edfec2001-08-06 14:14:18 +00003640 if (isalnum(*s) || *s == '_') {
Denis Vlasenko73c571a2009-03-09 00:12:37 +00003641 xwrite_str(out, s);
3642 xwrite(out, "\n", 1);
Eric Andersenff9eee42001-06-29 04:57:14 +00003643 }
3644}
3645
3646
3647/*
3648 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
3649 * This file contains code for the times builtin.
Eric Andersenff9eee42001-06-29 04:57:14 +00003650 */
Denis Vlasenkofe218832008-03-01 09:35:39 +00003651static void times_fmt(char *buf, clock_t val, unsigned clk_tck)
3652{
3653 unsigned min, sec;
3654 if (sizeof(val) > sizeof(int))
3655 sec = ((unsigned long)val) / clk_tck;
3656 else
3657 sec = ((unsigned)val) / clk_tck;
3658 min = sec / 60;
3659#if ENABLE_DESKTOP
3660 sprintf(buf, "%um%u.%03us", min, (sec - min * 60),
3661 /* msec: */ ((unsigned)(val - (clock_t)sec * clk_tck)) * 1000 / clk_tck
3662 );
3663#else
3664 sprintf(buf, "%um%us", min, (sec - min * 60));
3665#endif
3666}
3667
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +00003668static int dotimes(struct op *t UNUSED_PARAM, char **args UNUSED_PARAM)
Eric Andersenff9eee42001-06-29 04:57:14 +00003669{
3670 struct tms buf;
Denis Vlasenkofe218832008-03-01 09:35:39 +00003671 unsigned clk_tck = sysconf(_SC_CLK_TCK);
3672 /* How much do we need for "NmN.NNNs" ? */
3673 enum { TIMEBUF_SIZE = sizeof(int)*3 + sizeof(int)*3 + 6 };
3674 char u[TIMEBUF_SIZE], s[TIMEBUF_SIZE];
3675 char cu[TIMEBUF_SIZE], cs[TIMEBUF_SIZE];
Eric Andersenff9eee42001-06-29 04:57:14 +00003676
3677 times(&buf);
Denis Vlasenkofe218832008-03-01 09:35:39 +00003678
3679 times_fmt(u, buf.tms_utime, clk_tck);
3680 times_fmt(s, buf.tms_stime, clk_tck);
3681 times_fmt(cu, buf.tms_cutime, clk_tck);
3682 times_fmt(cs, buf.tms_cstime, clk_tck);
3683
3684 printf("%s %s\n%s %s\n", u, s, cu, cs);
Eric Andersenff9eee42001-06-29 04:57:14 +00003685 return 0;
3686}
3687
3688
Eric Andersenff9eee42001-06-29 04:57:14 +00003689/* -------- eval.c -------- */
3690
3691/*
3692 * ${}
3693 * `command`
3694 * blank interpretation
3695 * quoting
3696 * glob
3697 */
3698
Eric Andersen8401eea2004-08-04 19:16:54 +00003699static char **eval(char **ap, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003700{
3701 struct wdblock *wb;
3702 char **wp;
3703 char **wf;
3704 jmp_buf ev;
3705
3706#if __GNUC__
3707 /* Avoid longjmp clobbering */
3708 (void) &wp;
3709 (void) &ap;
3710#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003711
3712 DBGPRINTF4(("EVAL: enter, f=%d\n", f));
3713
Eric Andersenff9eee42001-06-29 04:57:14 +00003714 wp = NULL;
3715 wb = NULL;
3716 wf = NULL;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003717 errpt = ev;
3718 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003719 while (*ap && isassign(*ap))
3720 expand(*ap++, &wb, f & ~DOGLOB);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003721 if (FLAG['k']) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003722 for (wf = ap; *wf; wf++) {
3723 if (isassign(*wf))
3724 expand(*wf, &wb, f & ~DOGLOB);
3725 }
3726 }
Denis Vlasenko648b44f2008-02-12 06:04:06 +00003727 for (wb = addword((char *) NULL, wb); *ap; ap++) {
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00003728 if (!FLAG['k'] || !isassign(*ap))
Eric Andersenff9eee42001-06-29 04:57:14 +00003729 expand(*ap, &wb, f & ~DOKEY);
3730 }
Eric Andersen8401eea2004-08-04 19:16:54 +00003731 wb = addword((char *) 0, wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003732 wp = getwords(wb);
3733 quitenv();
3734 } else
3735 gflg = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003736
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003737 return gflg ? (char **) NULL : wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003738}
3739
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003740
Eric Andersenff9eee42001-06-29 04:57:14 +00003741/*
3742 * Make the exported environment from the exported
3743 * names in the dictionary. Keyword assignments
3744 * will already have been done.
3745 */
Eric Andersenfd7a4c82004-09-02 23:13:10 +00003746static char **makenv(int all, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00003747{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003748 struct var *vp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003749
3750 DBGPRINTF5(("MAKENV: enter, all=%d\n", all));
Eric Andersenff9eee42001-06-29 04:57:14 +00003751
Eric Andersenff9eee42001-06-29 04:57:14 +00003752 for (vp = vlist; vp; vp = vp->next)
Eric Andersen12de6cf2004-08-04 19:19:10 +00003753 if (all || vp->status & EXPORT)
Eric Andersenff9eee42001-06-29 04:57:14 +00003754 wb = addword(vp->name, wb);
Eric Andersen8401eea2004-08-04 19:16:54 +00003755 wb = addword((char *) 0, wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003756 return getwords(wb);
Eric Andersenff9eee42001-06-29 04:57:14 +00003757}
3758
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003759static int expand(const char *cp, struct wdblock **wbp, int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003760{
3761 jmp_buf ev;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003762 char *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003763
3764#if __GNUC__
3765 /* Avoid longjmp clobbering */
3766 (void) &cp;
3767#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00003768
3769 DBGPRINTF3(("EXPAND: enter, f=%d\n", f));
3770
Eric Andersenff9eee42001-06-29 04:57:14 +00003771 gflg = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003772
Eric Andersenff9eee42001-06-29 04:57:14 +00003773 if (cp == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003774 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003775
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003776 if (!anys("$`'\"", cp) && !anys(ifs->value, cp)
3777 && ((f & DOGLOB) == 0 || !anys("[*?", cp))
3778 ) {
3779 xp = strsave(cp, areanum);
Eric Andersenff9eee42001-06-29 04:57:14 +00003780 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003781 unquote(xp);
3782 *wbp = addword(xp, *wbp);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003783 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00003784 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003785 errpt = ev;
3786 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003787 PUSHIO(aword, cp, strchar);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003788 global_env.iobase = global_env.iop;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003789 while ((xp = blank(f)) && gflg == 0) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003790 global_env.linep = xp;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003791 xp = strsave(xp, areanum);
Eric Andersen8401eea2004-08-04 19:16:54 +00003792 if ((f & DOGLOB) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003793 if (f & DOTRIM)
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003794 unquote(xp);
3795 *wbp = addword(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003796 } else
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003797 *wbp = glob(xp, *wbp);
Eric Andersenff9eee42001-06-29 04:57:14 +00003798 }
3799 quitenv();
3800 } else
3801 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003802 return gflg == 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003803}
3804
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003805static char *evalstr(char *cp, int f)
3806{
3807 struct wdblock *wb;
3808
3809 DBGPRINTF6(("EVALSTR: enter, cp=%p, f=%d\n", cp, f));
3810
3811 wb = NULL;
3812 if (expand(cp, &wb, f)) {
3813 if (wb == NULL || wb->w_nword == 0
3814 || (cp = wb->w_words[0]) == NULL
3815 ) {
Denis Vlasenko8e858e22007-03-07 09:35:43 +00003816// TODO: I suspect that
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00003817// char *evalstr(char *cp, int f) is actually
3818// const char *evalstr(const char *cp, int f)!
3819 cp = (char*)"";
3820 }
3821 DELETE(wb);
3822 } else
3823 cp = NULL;
3824 return cp;
3825}
3826
3827
Eric Andersenff9eee42001-06-29 04:57:14 +00003828/*
3829 * Blank interpretation and quoting
3830 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003831static char *blank(int f)
Eric Andersenff9eee42001-06-29 04:57:14 +00003832{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003833 int c, c1;
3834 char *sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003835 int scanequals, foundequals;
3836
Eric Andersen12de6cf2004-08-04 19:19:10 +00003837 DBGPRINTF3(("BLANK: enter, f=%d\n", f));
3838
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003839 sp = global_env.linep;
Eric Andersenff9eee42001-06-29 04:57:14 +00003840 scanequals = f & DOKEY;
3841 foundequals = 0;
3842
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003843 loop:
3844 c = subgetc('"', foundequals);
3845 switch (c) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003846 case 0:
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003847 if (sp == global_env.linep)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003848 return 0;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003849 *global_env.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003850 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003851
3852 default:
3853 if (f & DOBLANK && any(c, ifs->value))
3854 goto loop;
3855 break;
3856
3857 case '"':
3858 case '\'':
3859 scanequals = 0;
3860 if (INSUB())
3861 break;
3862 for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
3863 if (c == 0)
3864 break;
3865 if (c == '\'' || !any(c, "$`\""))
3866 c |= QUOTE;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003867 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003868 }
3869 c = 0;
3870 }
3871 unget(c);
Matt Kraai69edfec2001-08-06 14:14:18 +00003872 if (!isalpha(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003873 scanequals = 0;
3874 for (;;) {
3875 c = subgetc('"', foundequals);
3876 if (c == 0 ||
Eric Andersen8401eea2004-08-04 19:16:54 +00003877 f & (DOBLANK && any(c, ifs->value)) ||
3878 (!INSUB() && any(c, "\"'"))) {
3879 scanequals = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003880 unget(c);
3881 if (any(c, "\"'"))
3882 goto loop;
3883 break;
3884 }
3885 if (scanequals) {
3886 if (c == '=') {
3887 foundequals = 1;
Eric Andersen8401eea2004-08-04 19:16:54 +00003888 scanequals = 0;
3889 } else if (!isalnum(c) && c != '_')
Eric Andersenff9eee42001-06-29 04:57:14 +00003890 scanequals = 0;
3891 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003892 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003893 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003894 *global_env.linep++ = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003895 return sp;
Eric Andersenff9eee42001-06-29 04:57:14 +00003896}
3897
3898/*
3899 * Get characters, substituting for ` and $
3900 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003901static int subgetc(char ec, int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003902{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003903 char c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003904
3905 DBGPRINTF3(("SUBGETC: enter, quoted=%d\n", quoted));
Eric Andersenff9eee42001-06-29 04:57:14 +00003906
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00003907 again:
Eric Andersenff9eee42001-06-29 04:57:14 +00003908 c = my_getc(ec);
3909 if (!INSUB() && ec != '\'') {
3910 if (c == '`') {
3911 if (grave(quoted) == 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003912 return 0;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003913 global_env.iop->task = XGRAVE;
Eric Andersenff9eee42001-06-29 04:57:14 +00003914 goto again;
3915 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003916 if (c == '$') {
3917 c = dollar(quoted);
3918 if (c == 0) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003919 global_env.iop->task = XDOLL;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003920 goto again;
3921 }
Eric Andersenff9eee42001-06-29 04:57:14 +00003922 }
3923 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003924 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003925}
3926
3927/*
3928 * Prepare to generate the string returned by ${} substitution.
3929 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00003930static int dollar(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00003931{
3932 int otask;
3933 struct io *oiop;
3934 char *dolp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00003935 char *s, c, *cp = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00003936 struct var *vp;
3937
Eric Andersen12de6cf2004-08-04 19:19:10 +00003938 DBGPRINTF3(("DOLLAR: enter, quoted=%d\n", quoted));
3939
Eric Andersenff9eee42001-06-29 04:57:14 +00003940 c = readc();
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003941 s = global_env.linep;
Eric Andersenff9eee42001-06-29 04:57:14 +00003942 if (c != '{') {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003943 *global_env.linep++ = c;
Matt Kraai69edfec2001-08-06 14:14:18 +00003944 if (isalpha(c) || c == '_') {
Eric Andersen8401eea2004-08-04 19:16:54 +00003945 while ((c = readc()) != 0 && (isalnum(c) || c == '_'))
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003946 if (global_env.linep < elinep)
3947 *global_env.linep++ = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003948 unget(c);
3949 }
3950 c = 0;
3951 } else {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003952 oiop = global_env.iop;
3953 otask = global_env.iop->task;
Eric Andersen12de6cf2004-08-04 19:19:10 +00003954
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003955 global_env.iop->task = XOTHER;
Eric Andersen8401eea2004-08-04 19:16:54 +00003956 while ((c = subgetc('"', 0)) != 0 && c != '}' && c != '\n')
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003957 if (global_env.linep < elinep)
3958 *global_env.linep++ = c;
3959 if (oiop == global_env.iop)
3960 global_env.iop->task = otask;
Eric Andersenff9eee42001-06-29 04:57:14 +00003961 if (c != '}') {
3962 err("unclosed ${");
Denis Vlasenko648b44f2008-02-12 06:04:06 +00003963 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00003964 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00003965 }
3966 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003967 if (global_env.linep >= elinep) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003968 err("string in ${} too long");
Denis Vlasenko648b44f2008-02-12 06:04:06 +00003969 gflg = 1;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003970 global_env.linep -= 10;
Eric Andersenff9eee42001-06-29 04:57:14 +00003971 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003972 *global_env.linep = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00003973 if (*s)
Eric Andersen8401eea2004-08-04 19:16:54 +00003974 for (cp = s + 1; *cp; cp++)
Eric Andersenff9eee42001-06-29 04:57:14 +00003975 if (any(*cp, "=-+?")) {
3976 c = *cp;
3977 *cp++ = 0;
3978 break;
3979 }
3980 if (s[1] == 0 && (*s == '*' || *s == '@')) {
3981 if (dolc > 1) {
3982 /* currently this does not distinguish $* and $@ */
3983 /* should check dollar */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00003984 global_env.linep = s;
Eric Andersen8401eea2004-08-04 19:16:54 +00003985 PUSHIO(awordlist, dolv + 1, dolchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00003986 return 0;
Eric Andersen8401eea2004-08-04 19:16:54 +00003987 } else { /* trap the nasty ${=} */
Eric Andersenff9eee42001-06-29 04:57:14 +00003988 s[0] = '1';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003989 s[1] = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00003990 }
3991 }
3992 vp = lookup(s);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00003993 dolp = vp->value;
3994 if (dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00003995 switch (c) {
3996 case '=':
3997 if (isdigit(*s)) {
Bernhard Reutner-Fischera53de7f2008-07-21 13:46:54 +00003998 err("can't use ${...=...} with $n");
Denis Vlasenko648b44f2008-02-12 06:04:06 +00003999 gflg = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004000 break;
4001 }
4002 setval(vp, cp);
4003 dolp = vp->value;
4004 break;
4005
4006 case '-':
4007 dolp = strsave(cp, areanum);
4008 break;
4009
4010 case '?':
4011 if (*cp == 0) {
4012 prs("missing value for ");
4013 err(s);
4014 } else
4015 err(cp);
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004016 gflg = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004017 break;
4018 }
4019 } else if (c == '+')
4020 dolp = strsave(cp, areanum);
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00004021 if (FLAG['u'] && dolp == null) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004022 prs("unset variable: ");
4023 err(s);
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004024 gflg = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004025 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004026 global_env.linep = s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004027 PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004028 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004029}
4030
4031/*
4032 * Run the command in `...` and read its output.
4033 */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004034
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004035static int grave(int quoted)
Eric Andersenff9eee42001-06-29 04:57:14 +00004036{
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004037 /* moved to G: static char child_cmd[LINELIM]; */
4038
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004039 const char *cp;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004040 int i;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004041 int j;
Eric Andersenff9eee42001-06-29 04:57:14 +00004042 int pf[2];
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004043 const char *src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004044 char *dest;
4045 int count;
4046 int ignore;
4047 int ignore_once;
4048 char *argument_list[4];
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004049 struct wdblock *wb = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004050
4051#if __GNUC__
4052 /* Avoid longjmp clobbering */
4053 (void) &cp;
4054#endif
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004055
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004056 for (cp = global_env.iop->argp->aword; *cp != '`'; cp++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004057 if (*cp == 0) {
4058 err("no closing `");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004059 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004060 }
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004061 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004062
4063 /* string copy with dollar expansion */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004064 src = global_env.iop->argp->aword;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004065 dest = child_cmd;
4066 count = 0;
4067 ignore = 0;
4068 ignore_once = 0;
4069 while ((*src != '`') && (count < LINELIM)) {
4070 if (*src == '\'')
4071 ignore = !ignore;
4072 if (*src == '\\')
4073 ignore_once = 1;
4074 if (*src == '$' && !ignore && !ignore_once) {
4075 struct var *vp;
Denis Vlasenkoab801872007-12-02 08:35:37 +00004076 /* moved to G to reduce stack usage
Eric Andersen737f5fb2003-03-14 16:05:59 +00004077 char var_name[LINELIM];
4078 char alt_value[LINELIM];
Denis Vlasenkoab801872007-12-02 08:35:37 +00004079 */
4080#define var_name (G.grave__var_name)
4081#define alt_value (G.grave__alt_value)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004082 int var_index = 0;
4083 int alt_index = 0;
4084 char operator = 0;
4085 int braces = 0;
4086 char *value;
4087
4088 src++;
4089 if (*src == '{') {
4090 braces = 1;
4091 src++;
4092 }
4093
4094 var_name[var_index++] = *src++;
Paul Fox54690dc2005-07-20 18:33:12 +00004095 while (isalnum(*src) || *src=='_')
Eric Andersen737f5fb2003-03-14 16:05:59 +00004096 var_name[var_index++] = *src++;
4097 var_name[var_index] = 0;
4098
4099 if (braces) {
4100 switch (*src) {
4101 case '}':
4102 break;
4103 case '-':
4104 case '=':
4105 case '+':
4106 case '?':
Eric Andersen8401eea2004-08-04 19:16:54 +00004107 operator = * src;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004108 break;
4109 default:
4110 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004111 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004112 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004113 if (operator) {
Eric Andersen737f5fb2003-03-14 16:05:59 +00004114 src++;
4115 while (*src && (*src != '}')) {
4116 alt_value[alt_index++] = *src++;
4117 }
4118 alt_value[alt_index] = 0;
4119 if (*src != '}') {
4120 err("unclosed ${\n");
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004121 return 0;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004122 }
4123 }
4124 src++;
4125 }
4126
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004127 if (isalpha(*var_name)) {
4128 /* let subshell handle it instead */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004129
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004130 char *namep = var_name;
4131
4132 *dest++ = '$';
4133 if (braces)
4134 *dest++ = '{';
4135 while (*namep)
4136 *dest++ = *namep++;
4137 if (operator) {
4138 char *altp = alt_value;
4139 *dest++ = operator;
4140 while (*altp)
4141 *dest++ = *altp++;
4142 }
4143 if (braces)
4144 *dest++ = '}';
4145
4146 wb = addword(lookup(var_name)->name, wb);
4147 } else {
4148 /* expand */
4149
4150 vp = lookup(var_name);
4151 if (vp->value != null)
4152 value = (operator == '+') ?
4153 alt_value : vp->value;
4154 else if (operator == '?') {
4155 err(alt_value);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004156 return 0;
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004157 } else if (alt_index && (operator != '+')) {
4158 value = alt_value;
4159 if (operator == '=')
4160 setval(vp, value);
4161 } else
4162 continue;
4163
4164 while (*value && (count < LINELIM)) {
4165 *dest++ = *value++;
4166 count++;
4167 }
Eric Andersen737f5fb2003-03-14 16:05:59 +00004168 }
Denis Vlasenkoab801872007-12-02 08:35:37 +00004169#undef var_name
4170#undef alt_value
Eric Andersen737f5fb2003-03-14 16:05:59 +00004171 } else {
4172 *dest++ = *src++;
4173 count++;
4174 ignore_once = 0;
4175 }
4176 }
4177 *dest = '\0';
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004178
Eric Andersenff9eee42001-06-29 04:57:14 +00004179 if (openpipe(pf) < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004180 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004181
Denis Vlasenko509697f2008-03-02 12:49:39 +00004182 while ((i = vfork()) == -1 && errno == EAGAIN)
4183 continue;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004184
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004185 DBGPRINTF3(("GRAVE: i is %p\n", io));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004186
Eric Andersen737f5fb2003-03-14 16:05:59 +00004187 if (i < 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004188 closepipe(pf);
Eric Andersen8401eea2004-08-04 19:16:54 +00004189 err((char *) bb_msg_memory_exhausted);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004190 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004191 }
4192 if (i != 0) {
Denis Vlasenkofb0eba72008-01-02 19:55:04 +00004193 waitpid(i, NULL, 0); // safe_waitpid?
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004194 global_env.iop->argp->aword = ++cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004195 close(pf[1]);
Eric Andersen8401eea2004-08-04 19:16:54 +00004196 PUSHIO(afile, remap(pf[0]),
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004197 (int (*)(struct ioarg *)) ((quoted) ? qgravechar : gravechar));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004198 return 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004199 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004200 /* allow trapped signals */
Eric Andersen737f5fb2003-03-14 16:05:59 +00004201 /* XXX - Maybe this signal stuff should go as well? */
Eric Andersen8401eea2004-08-04 19:16:54 +00004202 for (j = 0; j <= _NSIG; j++)
Eric Andersen737f5fb2003-03-14 16:05:59 +00004203 if (ourtrap[j] && signal(j, SIG_IGN) != SIG_IGN)
4204 signal(j, SIG_DFL);
Eric Andersenc7bda1c2004-03-15 08:29:22 +00004205
Denis Vlasenko2b54aaa2007-05-09 22:16:08 +00004206 /* Testcase where below checks are needed:
4207 * close stdout & run this script:
4208 * files=`ls`
4209 * echo "$files" >zz
4210 */
4211 xmove_fd(pf[1], 1);
Denis Vlasenko847fa772008-01-28 22:45:43 +00004212 if (pf[0] != 1)
4213 close(pf[0]);
Eric Andersen737f5fb2003-03-14 16:05:59 +00004214
Eric Andersen8401eea2004-08-04 19:16:54 +00004215 argument_list[0] = (char *) DEFAULT_SHELL;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004216 argument_list[1] = (char *) "-c";
Eric Andersen737f5fb2003-03-14 16:05:59 +00004217 argument_list[2] = child_cmd;
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004218 argument_list[3] = NULL;
Eric Andersen737f5fb2003-03-14 16:05:59 +00004219
Eric Andersenfd7a4c82004-09-02 23:13:10 +00004220 cp = rexecve(argument_list[0], argument_list, makenv(1, wb));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004221 prs(argument_list[0]);
4222 prs(": ");
4223 err(cp);
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00004224 _exit(EXIT_FAILURE);
Eric Andersenff9eee42001-06-29 04:57:14 +00004225}
4226
Eric Andersen737f5fb2003-03-14 16:05:59 +00004227
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004228static char *unquote(char *as)
Eric Andersenff9eee42001-06-29 04:57:14 +00004229{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004230 char *s;
Eric Andersenff9eee42001-06-29 04:57:14 +00004231
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004232 s = as;
4233 if (s != NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004234 while (*s)
4235 *s++ &= ~QUOTE;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004236 return as;
Eric Andersenff9eee42001-06-29 04:57:14 +00004237}
4238
4239/* -------- glob.c -------- */
4240
4241/*
4242 * glob
4243 */
4244
4245#define scopy(x) strsave((x), areanum)
4246#define BLKSIZ 512
4247#define NDENT ((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
4248
Eric Andersen8401eea2004-08-04 19:16:54 +00004249static struct wdblock *cl, *nl;
Denis Vlasenko6ca409e2007-08-12 20:58:27 +00004250static const char spcl[] ALIGN1= "[?*";
Eric Andersenff9eee42001-06-29 04:57:14 +00004251
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004252static struct wdblock *glob(char *cp, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004253{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004254 int i;
4255 char *pp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004256
4257 if (cp == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004258 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004259 i = 0;
4260 for (pp = cp; *pp; pp++)
4261 if (any(*pp, spcl))
4262 i++;
4263 else if (!any(*pp & ~QUOTE, spcl))
4264 *pp &= ~QUOTE;
4265 if (i != 0) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004266 for (cl = addword(scopy(cp), NULL); anyspcl(cl); cl = nl) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004267 nl = newword(cl->w_nword * 2);
4268 for (i = 0; i < cl->w_nword; i++) { /* for each argument */
Eric Andersenff9eee42001-06-29 04:57:14 +00004269 for (pp = cl->w_words[i]; *pp; pp++)
4270 if (any(*pp, spcl)) {
4271 globname(cl->w_words[i], pp);
4272 break;
4273 }
4274 if (*pp == '\0')
4275 nl = addword(scopy(cl->w_words[i]), nl);
4276 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004277 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004278 DELETE(cl->w_words[i]);
4279 DELETE(cl);
4280 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004281 if (cl->w_nword) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004282 for (i = 0; i < cl->w_nword; i++)
Denis Vlasenkofb290382008-03-02 12:51:26 +00004283 unquote(cl->w_words[i]);
4284 qsort_string_vector(cl->w_words, cl->w_nword);
4285 for (i = 0; i < cl->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004286 wb = addword(cl->w_words[i], wb);
4287 DELETE(cl);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004288 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004289 }
4290 }
4291 wb = addword(unquote(cp), wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004292 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004293}
4294
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004295static void globname(char *we, char *pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004296{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004297 char *np, *cp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004298 char *name, *gp, *dp;
4299 int k;
4300 DIR *dirp;
4301 struct dirent *de;
Eric Andersen8401eea2004-08-04 19:16:54 +00004302 char dname[NAME_MAX + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004303 struct stat dbuf;
4304
4305 for (np = we; np != pp; pp--)
4306 if (pp[-1] == '/')
4307 break;
Denis Vlasenkofb290382008-03-02 12:51:26 +00004308 dp = cp = get_space((int) (pp - np) + 3);
4309 while (np < pp)
Eric Andersenff9eee42001-06-29 04:57:14 +00004310 *cp++ = *np++;
4311 *cp++ = '.';
4312 *cp = '\0';
Denis Vlasenkofb290382008-03-02 12:51:26 +00004313 gp = cp = get_space(strlen(pp) + 1);
4314 while (*np && *np != '/')
Eric Andersenff9eee42001-06-29 04:57:14 +00004315 *cp++ = *np++;
4316 *cp = '\0';
4317 dirp = opendir(dp);
4318 if (dirp == 0) {
4319 DELETE(dp);
4320 DELETE(gp);
4321 return;
4322 }
4323 dname[NAME_MAX] = '\0';
Eric Andersen8401eea2004-08-04 19:16:54 +00004324 while ((de = readdir(dirp)) != NULL) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004325 /* XXX Hmmm... What this could be? (abial) */
Denis Vlasenkoed9d6212008-06-09 07:44:19 +00004326 /* if (ent[j].d_ino == 0) continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004327 */
Eric Andersenff9eee42001-06-29 04:57:14 +00004328 strncpy(dname, de->d_name, NAME_MAX);
Eric Andersen8401eea2004-08-04 19:16:54 +00004329 if (dname[0] == '.')
4330 if (*gp != '.')
4331 continue;
4332 for (k = 0; k < NAME_MAX; k++)
4333 if (any(dname[k], spcl))
4334 dname[k] |= QUOTE;
4335 if (gmatch(dname, gp)) {
4336 name = generate(we, pp, dname, np);
4337 if (*np && !anys(np, spcl)) {
4338 if (stat(name, &dbuf)) {
4339 DELETE(name);
Eric Andersenff9eee42001-06-29 04:57:14 +00004340 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004341 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004342 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004343 nl = addword(name, nl);
4344 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004345 }
4346 closedir(dirp);
4347 DELETE(dp);
4348 DELETE(gp);
4349}
4350
4351/*
4352 * generate a pathname as below.
4353 * start..end1 / middle end
4354 * the slashes come for free
4355 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004356static char *generate(char *start1, char *end1, char *middle, char *end)
Eric Andersenff9eee42001-06-29 04:57:14 +00004357{
4358 char *p;
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004359 char *op, *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004360
Denis Vlasenko509697f2008-03-02 12:49:39 +00004361 p = op = get_space((int)(end1 - start1) + strlen(middle) + strlen(end) + 2);
4362 xp = start1;
4363 while (xp != end1)
Eric Andersenff9eee42001-06-29 04:57:14 +00004364 *op++ = *xp++;
Denis Vlasenko509697f2008-03-02 12:49:39 +00004365 xp = middle;
4366 while (*xp != '\0')
4367 *op++ = *xp++;
4368 strcpy(op, end);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004369 return p;
Eric Andersenff9eee42001-06-29 04:57:14 +00004370}
4371
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004372static int anyspcl(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004373{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004374 int i;
4375 char **wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004376
4377 wd = wb->w_words;
Eric Andersen8401eea2004-08-04 19:16:54 +00004378 for (i = 0; i < wb->w_nword; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004379 if (anys(spcl, *wd++))
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004380 return 1;
4381 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004382}
4383
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004384
Eric Andersenff9eee42001-06-29 04:57:14 +00004385/* -------- word.c -------- */
4386
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004387static struct wdblock *newword(int nw)
Eric Andersenff9eee42001-06-29 04:57:14 +00004388{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004389 struct wdblock *wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004390
Denis Vlasenko509697f2008-03-02 12:49:39 +00004391 wb = get_space(sizeof(*wb) + nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004392 wb->w_bsize = nw;
4393 wb->w_nword = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004394 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004395}
4396
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004397static struct wdblock *addword(char *wd, struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004398{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004399 struct wdblock *wb2;
4400 int nw;
Eric Andersenff9eee42001-06-29 04:57:14 +00004401
4402 if (wb == NULL)
4403 wb = newword(NSTART);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004404 nw = wb->w_nword;
4405 if (nw >= wb->w_bsize) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004406 wb2 = newword(nw * 2);
Eric Andersen8401eea2004-08-04 19:16:54 +00004407 memcpy((char *) wb2->w_words, (char *) wb->w_words,
4408 nw * sizeof(char *));
Eric Andersenff9eee42001-06-29 04:57:14 +00004409 wb2->w_nword = nw;
4410 DELETE(wb);
4411 wb = wb2;
4412 }
4413 wb->w_words[wb->w_nword++] = wd;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004414 return wb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004415}
Eric Andersen8401eea2004-08-04 19:16:54 +00004416
Denis Vlasenkoe4712752007-04-14 15:08:41 +00004417static char **getwords(struct wdblock *wb)
Eric Andersenff9eee42001-06-29 04:57:14 +00004418{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004419 char **wd;
4420 int nb;
Eric Andersenff9eee42001-06-29 04:57:14 +00004421
4422 if (wb == NULL)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004423 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004424 if (wb->w_nword == 0) {
4425 DELETE(wb);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004426 return NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004427 }
Denis Vlasenko509697f2008-03-02 12:49:39 +00004428 nb = sizeof(*wd) * wb->w_nword;
4429 wd = get_space(nb);
Denis Vlasenkofb290382008-03-02 12:51:26 +00004430 memcpy(wd, wb->w_words, nb);
4431 DELETE(wb); /* perhaps should done by caller */
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004432 return wd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004433}
4434
Eric Andersenff9eee42001-06-29 04:57:14 +00004435
4436/* -------- io.c -------- */
4437
4438/*
4439 * shell IO
4440 */
4441
Eric Andersen8401eea2004-08-04 19:16:54 +00004442static int my_getc(int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004443{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004444 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004445
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004446 if (global_env.linep > elinep) {
Denis Vlasenko509697f2008-03-02 12:49:39 +00004447 while ((c = readc()) != '\n' && c)
4448 continue;
Eric Andersenff9eee42001-06-29 04:57:14 +00004449 err("input line too long");
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004450 gflg = 1;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004451 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004452 }
4453 c = readc();
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004454 if ((ec != '\'') && (ec != '`') && (global_env.iop->task != XGRAVE)) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004455 if (c == '\\') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004456 c = readc();
4457 if (c == '\n' && ec != '\"')
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004458 return my_getc(ec);
Eric Andersenff9eee42001-06-29 04:57:14 +00004459 c |= QUOTE;
4460 }
4461 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004462 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004463}
4464
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004465static void unget(int c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004466{
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004467 if (global_env.iop >= global_env.iobase)
4468 global_env.iop->peekc = c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004469}
4470
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004471static int eofc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004472{
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004473 return global_env.iop < global_env.iobase || (global_env.iop->peekc == 0 && global_env.iop->prev == 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004474}
4475
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004476static int readc(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004477{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004478 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004479
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004480 RCPRINTF(("READC: global_env.iop %p, global_env.iobase %p\n", global_env.iop, global_env.iobase));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004481
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004482 for (; global_env.iop >= global_env.iobase; global_env.iop--) {
4483 RCPRINTF(("READC: global_env.iop %p, peekc 0x%x\n", global_env.iop, global_env.iop->peekc));
4484 c = global_env.iop->peekc;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004485 if (c != '\0') {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004486 global_env.iop->peekc = 0;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004487 return c;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004488 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004489 if (global_env.iop->prev != 0) {
4490 c = (*global_env.iop->iofn)(global_env.iop->argp, global_env.iop);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004491 if (c != '\0') {
4492 if (c == -1) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004493 global_env.iop++;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004494 continue;
Eric Andersen8401eea2004-08-04 19:16:54 +00004495 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004496 if (global_env.iop == iostack)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004497 ioecho(c);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004498 global_env.iop->prev = c;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004499 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004500 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004501 if (global_env.iop->task == XIO && global_env.iop->prev != '\n') {
4502 global_env.iop->prev = 0;
4503 if (global_env.iop == iostack)
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004504 ioecho('\n');
4505 return '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004506 }
Eric Andersenff9eee42001-06-29 04:57:14 +00004507 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004508 if (global_env.iop->task == XIO) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004509 if (multiline) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004510 global_env.iop->prev = 0;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004511 return 0;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004512 }
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004513 if (interactive && global_env.iop == iostack + 1) {
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004514#if ENABLE_FEATURE_EDITING
4515 current_prompt = prompt->value;
4516#else
4517 prs(prompt->value);
4518#endif
4519 }
4520 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004521 } /* FOR */
4522
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004523 if (global_env.iop >= iostack) {
4524 RCPRINTF(("READC: return 0, global_env.iop %p\n", global_env.iop));
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004525 return 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004526 }
4527
4528 DBGPRINTF(("READC: leave()...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004529 leave();
4530 /* NOTREACHED */
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004531 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004532}
4533
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004534static void ioecho(char c)
Eric Andersenff9eee42001-06-29 04:57:14 +00004535{
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00004536 if (FLAG['v'])
Bernhard Reutner-Fischer5e25ddb2008-05-19 09:48:17 +00004537 write(STDERR_FILENO, &c, sizeof c);
Eric Andersenff9eee42001-06-29 04:57:14 +00004538}
4539
Eric Andersen8401eea2004-08-04 19:16:54 +00004540static void pushio(struct ioarg *argp, int (*fn) (struct ioarg *))
Eric Andersenff9eee42001-06-29 04:57:14 +00004541{
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004542 DBGPRINTF(("PUSHIO: argp %p, argp->afid 0x%x, global_env.iop %p\n", argp,
4543 argp->afid, global_env.iop));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004544
4545 /* Set env ptr for io source to next array spot and check for array overflow */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004546 if (++global_env.iop >= &iostack[NPUSH]) {
4547 global_env.iop--;
Eric Andersenff9eee42001-06-29 04:57:14 +00004548 err("Shell input nested too deeply");
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004549 gflg = 1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004550 return;
4551 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004552
4553 /* We did not overflow the NPUSH array spots so setup data structs */
4554
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004555 global_env.iop->iofn = (int (*)(struct ioarg *, struct io *)) fn; /* Store data source func ptr */
Eric Andersenff9eee42001-06-29 04:57:14 +00004556
4557 if (argp->afid != AFID_NOBUF)
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004558 global_env.iop->argp = argp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004559 else {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004560
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004561 global_env.iop->argp = ioargstack + (global_env.iop - iostack); /* MAL - index into stack */
4562 *global_env.iop->argp = *argp; /* copy data from temp area into stack spot */
Eric Andersen12de6cf2004-08-04 19:19:10 +00004563
4564 /* MAL - mainbuf is for 1st data source (command line?) and all nested use a single shared buffer? */
4565
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004566 if (global_env.iop == &iostack[0])
4567 global_env.iop->argp->afbuf = &mainbuf;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004568 else
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004569 global_env.iop->argp->afbuf = &sharedbuf;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004570
4571 /* MAL - if not a termimal AND (commandline OR readable file) then give it a buffer id? */
4572 /* This line appears to be active when running scripts from command line */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004573 if ((isatty(global_env.iop->argp->afile) == 0)
4574 && (global_env.iop == &iostack[0]
4575 || lseek(global_env.iop->argp->afile, 0L, SEEK_CUR) != -1)) {
Eric Andersen12de6cf2004-08-04 19:19:10 +00004576 if (++bufid == AFID_NOBUF) /* counter rollover check, AFID_NOBUF = 11111111 */
4577 bufid = AFID_ID; /* AFID_ID = 0 */
4578
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004579 global_env.iop->argp->afid = bufid; /* assign buffer id */
Eric Andersen8401eea2004-08-04 19:16:54 +00004580 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004581
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004582 DBGPRINTF(("PUSHIO: iostack %p, global_env.iop %p, afbuf %p\n",
4583 iostack, global_env.iop, global_env.iop->argp->afbuf));
4584 DBGPRINTF(("PUSHIO: mbuf %p, sbuf %p, bid %d, global_env.iop %p\n",
4585 &mainbuf, &sharedbuf, bufid, global_env.iop));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004586
Eric Andersenff9eee42001-06-29 04:57:14 +00004587 }
4588
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004589 global_env.iop->prev = ~'\n';
4590 global_env.iop->peekc = 0;
4591 global_env.iop->xchar = 0;
4592 global_env.iop->nlcount = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004593
Eric Andersenff9eee42001-06-29 04:57:14 +00004594 if (fn == filechar || fn == linechar)
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004595 global_env.iop->task = XIO;
Eric Andersen8401eea2004-08-04 19:16:54 +00004596 else if (fn == (int (*)(struct ioarg *)) gravechar
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004597 || fn == (int (*)(struct ioarg *)) qgravechar)
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004598 global_env.iop->task = XGRAVE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004599 else
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004600 global_env.iop->task = XOTHER;
Eric Andersenff9eee42001-06-29 04:57:14 +00004601}
4602
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004603static struct io *setbase(struct io *ip)
Eric Andersenff9eee42001-06-29 04:57:14 +00004604{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004605 struct io *xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004606
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004607 xp = global_env.iobase;
4608 global_env.iobase = ip;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004609 return xp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004610}
4611
4612/*
4613 * Input generating functions
4614 */
4615
4616/*
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004617 * Produce the characters of a string, then a newline, then NUL.
Eric Andersenff9eee42001-06-29 04:57:14 +00004618 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004619static int nlchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004620{
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004621 char c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004622
4623 if (ap->aword == NULL)
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004624 return '\0';
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004625 c = *ap->aword++;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00004626 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004627 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004628 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004629 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004630 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004631}
4632
4633/*
4634 * Given a list of words, produce the characters
4635 * in them, with a space after each word.
4636 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004637static int wdchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004638{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004639 char c;
4640 char **wl;
Eric Andersenff9eee42001-06-29 04:57:14 +00004641
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004642 wl = ap->awordlist;
4643 if (wl == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004644 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004645 if (*wl != NULL) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004646 c = *(*wl)++;
4647 if (c != 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004648 return c & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004649 ap->awordlist++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004650 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004651 }
4652 ap->awordlist = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004653 return '\n';
Eric Andersenff9eee42001-06-29 04:57:14 +00004654}
4655
4656/*
4657 * Return the characters of a list of words,
4658 * producing a space between them.
4659 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004660static int dolchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004661{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004662 char *wp;
Eric Andersenff9eee42001-06-29 04:57:14 +00004663
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004664 wp = *ap->awordlist++;
4665 if (wp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004666 PUSHIO(aword, wp, *ap->awordlist == NULL ? strchar : xxchar);
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004667 return -1;
Eric Andersenff9eee42001-06-29 04:57:14 +00004668 }
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004669 return 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004670}
4671
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004672static int xxchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004673{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004674 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004675
4676 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004677 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004678 c = *ap->aword++;
4679 if (c == '\0') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004680 ap->aword = NULL;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004681 return ' ';
Eric Andersenff9eee42001-06-29 04:57:14 +00004682 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004683 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004684}
4685
4686/*
4687 * Produce the characters from a single word (string).
4688 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004689static int strchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004690{
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004691 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004692 return 0;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004693 return *ap->aword++;
Eric Andersenff9eee42001-06-29 04:57:14 +00004694}
4695
4696/*
4697 * Produce quoted characters from a single word (string).
4698 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004699static int qstrchar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004700{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004701 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004702
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004703 if (ap->aword == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00004704 return 0;
Denis Vlasenkob2abef32007-01-01 18:18:04 +00004705 c = *ap->aword++;
4706 if (c)
4707 c |= QUOTE;
4708 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004709}
4710
4711/*
4712 * Return the characters from a file.
4713 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004714static int filechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004715{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004716 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004717 char c;
4718 struct iobuf *bp = ap->afbuf;
4719
4720 if (ap->afid != AFID_NOBUF) {
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004721 i = (ap->afid != bp->id);
4722 if (i || bp->bufp == bp->ebufp) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004723 if (i)
Denis Vlasenkoea620772006-10-14 02:23:43 +00004724 lseek(ap->afile, ap->afpos, SEEK_SET);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004725
Denis Vlasenkoe376d452008-02-20 22:23:24 +00004726 i = nonblock_safe_read(ap->afile, bp->buf, sizeof(bp->buf));
Eric Andersen8401eea2004-08-04 19:16:54 +00004727 if (i <= 0) {
4728 closef(ap->afile);
4729 return 0;
4730 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004731
Eric Andersen8401eea2004-08-04 19:16:54 +00004732 bp->id = ap->afid;
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004733 bp->bufp = bp->buf;
4734 bp->ebufp = bp->bufp + i;
Eric Andersen8401eea2004-08-04 19:16:54 +00004735 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004736
Eric Andersen8401eea2004-08-04 19:16:54 +00004737 ap->afpos++;
4738 return *bp->bufp++ & 0177;
Eric Andersenff9eee42001-06-29 04:57:14 +00004739 }
Denis Vlasenko38f63192007-01-22 09:03:07 +00004740#if ENABLE_FEATURE_EDITING
Eric Andersen737f5fb2003-03-14 16:05:59 +00004741 if (interactive && isatty(ap->afile)) {
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004742 /* moved to G: static char filechar_cmdbuf[BUFSIZ]; */
Eric Andersen8401eea2004-08-04 19:16:54 +00004743 static int position = 0, size = 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004744
Eric Andersen8401eea2004-08-04 19:16:54 +00004745 while (size == 0 || position >= size) {
Denis Vlasenko6e602c42008-02-02 18:50:50 +00004746 size = read_line_input(current_prompt, filechar_cmdbuf, BUFSIZ, line_input_state);
4747 if (size < 0) /* Error/EOF */
Bernhard Reutner-Fischer636a1f82008-05-19 09:29:47 +00004748 exit(EXIT_SUCCESS);
Eric Andersen8401eea2004-08-04 19:16:54 +00004749 position = 0;
Denis Vlasenko6e602c42008-02-02 18:50:50 +00004750 /* if Ctrl-C, size == 0 and loop will repeat */
Eric Andersen8401eea2004-08-04 19:16:54 +00004751 }
Denis Vlasenko55f30b02007-03-24 22:42:29 +00004752 c = filechar_cmdbuf[position];
Eric Andersen8401eea2004-08-04 19:16:54 +00004753 position++;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004754 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004755 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004756#endif
Denis Vlasenkoe376d452008-02-20 22:23:24 +00004757 i = nonblock_safe_read(ap->afile, &c, sizeof(c));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004758 return i == sizeof(c) ? (c & 0x7f) : (closef(ap->afile), 0);
Eric Andersenff9eee42001-06-29 04:57:14 +00004759}
4760
4761/*
4762 * Return the characters from a here temp file.
4763 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004764static int herechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004765{
4766 char c;
4767
Denis Vlasenkoe376d452008-02-20 22:23:24 +00004768 if (nonblock_safe_read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004769 close(ap->afile);
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004770 c = '\0';
Eric Andersenff9eee42001-06-29 04:57:14 +00004771 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004772 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004773}
4774
4775/*
4776 * Return the characters produced by a process (`...`).
4777 * Quote them if required, and remove any trailing newline characters.
4778 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004779static int gravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004780{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004781 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004782
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004783 c = qgravechar(ap, iop) & ~QUOTE;
4784 if (c == '\n')
Eric Andersenff9eee42001-06-29 04:57:14 +00004785 c = ' ';
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004786 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004787}
4788
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004789static int qgravechar(struct ioarg *ap, struct io *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004790{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004791 int c;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004792
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004793 DBGPRINTF3(("QGRAVECHAR: enter, ap=%p, iop=%p\n", ap, iop));
Eric Andersenff9eee42001-06-29 04:57:14 +00004794
4795 if (iop->xchar) {
4796 if (iop->nlcount) {
4797 iop->nlcount--;
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004798 return '\n' | QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004799 }
4800 c = iop->xchar;
4801 iop->xchar = 0;
4802 } else if ((c = filechar(ap)) == '\n') {
4803 iop->nlcount = 1;
4804 while ((c = filechar(ap)) == '\n')
4805 iop->nlcount++;
4806 iop->xchar = c;
4807 if (c == 0)
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004808 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004809 iop->nlcount--;
4810 c = '\n';
4811 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004812 return c != 0 ? c | QUOTE : 0;
Eric Andersenff9eee42001-06-29 04:57:14 +00004813}
4814
4815/*
4816 * Return a single command (usually the first line) from a file.
4817 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004818static int linechar(struct ioarg *ap)
Eric Andersenff9eee42001-06-29 04:57:14 +00004819{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004820 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004821
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004822 c = filechar(ap);
4823 if (c == '\n') {
Eric Andersenff9eee42001-06-29 04:57:14 +00004824 if (!multiline) {
4825 closef(ap->afile);
Eric Andersen8401eea2004-08-04 19:16:54 +00004826 ap->afile = -1; /* illegal value */
Eric Andersenff9eee42001-06-29 04:57:14 +00004827 }
4828 }
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004829 return c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004830}
4831
Eric Andersenff9eee42001-06-29 04:57:14 +00004832/*
Denis Vlasenkoed9d6212008-06-09 07:44:19 +00004833 * Remap fd into shell's fd space
Eric Andersenff9eee42001-06-29 04:57:14 +00004834 */
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004835static int remap(int fd)
Eric Andersenff9eee42001-06-29 04:57:14 +00004836{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004837 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004838 int map[NOFILE];
Eric Andersen12de6cf2004-08-04 19:19:10 +00004839 int newfd;
4840
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004841 DBGPRINTF(("REMAP: fd=%d, global_env.iofd=%d\n", fd, global_env.iofd));
Eric Andersenff9eee42001-06-29 04:57:14 +00004842
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004843 if (fd < global_env.iofd) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004844 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004845 map[i] = 0;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004846
Eric Andersenff9eee42001-06-29 04:57:14 +00004847 do {
4848 map[fd] = 1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004849 newfd = dup(fd);
4850 fd = newfd;
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004851 } while (fd >= 0 && fd < global_env.iofd);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004852
Eric Andersen8401eea2004-08-04 19:16:54 +00004853 for (i = 0; i < NOFILE; i++)
Eric Andersenff9eee42001-06-29 04:57:14 +00004854 if (map[i])
4855 close(i);
Eric Andersen12de6cf2004-08-04 19:19:10 +00004856
Eric Andersenff9eee42001-06-29 04:57:14 +00004857 if (fd < 0)
4858 err("too many files open in shell");
4859 }
Eric Andersen12de6cf2004-08-04 19:19:10 +00004860
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004861 return fd;
Eric Andersenff9eee42001-06-29 04:57:14 +00004862}
4863
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004864static int openpipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004865{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004866 int i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004867
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004868 i = pipe(pv);
4869 if (i < 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004870 err("can't create pipe - try again");
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00004871 return i;
Eric Andersenff9eee42001-06-29 04:57:14 +00004872}
4873
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004874static void closepipe(int *pv)
Eric Andersenff9eee42001-06-29 04:57:14 +00004875{
4876 if (pv != NULL) {
Denis Vlasenkoa5f2cd32008-02-11 18:10:06 +00004877 close(pv[0]);
4878 close(pv[1]);
Eric Andersenff9eee42001-06-29 04:57:14 +00004879 }
4880}
4881
Denis Vlasenko1e3b0682007-02-01 01:43:54 +00004882
Eric Andersenff9eee42001-06-29 04:57:14 +00004883/* -------- here.c -------- */
4884
4885/*
4886 * here documents
4887 */
4888
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004889static void markhere(char *s, struct ioword *iop)
Eric Andersenff9eee42001-06-29 04:57:14 +00004890{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004891 struct here *h, *lh;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004892
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004893 DBGPRINTF7(("MARKHERE: enter, s=%p\n", s));
Eric Andersenff9eee42001-06-29 04:57:14 +00004894
Denis Vlasenko509697f2008-03-02 12:49:39 +00004895 h = get_space(sizeof(struct here));
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004896 if (h == NULL)
Eric Andersenff9eee42001-06-29 04:57:14 +00004897 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004898
Eric Andersenff9eee42001-06-29 04:57:14 +00004899 h->h_tag = evalstr(s, DOSUB);
4900 if (h->h_tag == 0)
4901 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004902
Eric Andersenff9eee42001-06-29 04:57:14 +00004903 h->h_iop = iop;
4904 iop->io_name = 0;
4905 h->h_next = NULL;
4906 if (inhere == 0)
4907 inhere = h;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004908 else {
4909 for (lh = inhere; lh != NULL; lh = lh->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004910 if (lh->h_next == 0) {
4911 lh->h_next = h;
4912 break;
4913 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004914 }
4915 }
Eric Andersen8401eea2004-08-04 19:16:54 +00004916 iop->io_flag |= IOHERE | IOXHERE;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004917 for (s = h->h_tag; *s; s++) {
Eric Andersenff9eee42001-06-29 04:57:14 +00004918 if (*s & QUOTE) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004919 iop->io_flag &= ~IOXHERE;
4920 *s &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004921 }
Denis Vlasenko00ccf952007-02-01 01:39:24 +00004922 }
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004923 h->h_dosub = ((iop->io_flag & IOXHERE) ? '\0' : '\'');
Eric Andersenff9eee42001-06-29 04:57:14 +00004924}
4925
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00004926static void gethere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00004927{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004928 struct here *h, *hp;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004929
4930 DBGPRINTF7(("GETHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00004931
4932 /* Scan here files first leaving inhere list in place */
4933 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
Denis Vlasenko648b44f2008-02-12 06:04:06 +00004934 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub /* NUL or ' */);
Eric Andersenff9eee42001-06-29 04:57:14 +00004935
4936 /* Make inhere list active - keep list intact for scraphere */
4937 if (hp != NULL) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004938 hp->h_next = acthere;
4939 acthere = inhere;
4940 inhere = NULL;
Eric Andersenff9eee42001-06-29 04:57:14 +00004941 }
4942}
4943
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004944static void readhere(char **name, char *s, int ec)
Eric Andersenff9eee42001-06-29 04:57:14 +00004945{
4946 int tf;
4947 char tname[30] = ".msh_XXXXXX";
"Robert P. J. Day"68229832006-07-01 13:08:46 +00004948 int c;
Eric Andersenff9eee42001-06-29 04:57:14 +00004949 jmp_buf ev;
Eric Andersen8401eea2004-08-04 19:16:54 +00004950 char myline[LINELIM + 1];
Eric Andersenff9eee42001-06-29 04:57:14 +00004951 char *thenext;
4952
Mike Frysinger02d8fa42006-05-05 20:32:31 +00004953 DBGPRINTF7(("READHERE: enter, name=%p, s=%p\n", name, s));
Eric Andersen12de6cf2004-08-04 19:19:10 +00004954
Eric Andersenff9eee42001-06-29 04:57:14 +00004955 tf = mkstemp(tname);
4956 if (tf < 0)
4957 return;
Eric Andersen12de6cf2004-08-04 19:19:10 +00004958
Eric Andersenff9eee42001-06-29 04:57:14 +00004959 *name = strsave(tname, areanum);
Denis Vlasenkoe27f1562007-01-01 06:00:38 +00004960 errpt = ev;
4961 if (newenv(setjmp(errpt)) != 0)
Eric Andersenff9eee42001-06-29 04:57:14 +00004962 unlink(tname);
4963 else {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004964 pushio(global_env.iop->argp, (int (*)(struct ioarg *)) global_env.iop->iofn);
4965 global_env.iobase = global_env.iop;
Eric Andersenff9eee42001-06-29 04:57:14 +00004966 for (;;) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00004967 if (interactive && global_env.iop <= iostack) {
Denis Vlasenko38f63192007-01-22 09:03:07 +00004968#if ENABLE_FEATURE_EDITING
Eric Andersen8401eea2004-08-04 19:16:54 +00004969 current_prompt = cprompt->value;
Eric Andersenff9eee42001-06-29 04:57:14 +00004970#else
Eric Andersen8401eea2004-08-04 19:16:54 +00004971 prs(cprompt->value);
Eric Andersenff9eee42001-06-29 04:57:14 +00004972#endif
4973 }
4974 thenext = myline;
4975 while ((c = my_getc(ec)) != '\n' && c) {
4976 if (ec == '\'')
Eric Andersen8401eea2004-08-04 19:16:54 +00004977 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00004978 if (thenext >= &myline[LINELIM]) {
4979 c = 0;
4980 break;
4981 }
4982 *thenext++ = c;
4983 }
4984 *thenext = 0;
4985 if (strcmp(s, myline) == 0 || c == 0)
4986 break;
4987 *thenext++ = '\n';
Eric Andersen8401eea2004-08-04 19:16:54 +00004988 write(tf, myline, (int) (thenext - myline));
Eric Andersenff9eee42001-06-29 04:57:14 +00004989 }
4990 if (c == 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00004991 prs("here document `");
4992 prs(s);
4993 err("' unclosed");
Eric Andersenff9eee42001-06-29 04:57:14 +00004994 }
4995 quitenv();
4996 }
4997 close(tf);
4998}
4999
5000/*
5001 * open here temp file.
5002 * if unquoted here, expand here temp file into second temp file.
5003 */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005004static int herein(char *hname, int xdoll)
Eric Andersenff9eee42001-06-29 04:57:14 +00005005{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005006 int hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005007 int tf;
5008
5009#if __GNUC__
5010 /* Avoid longjmp clobbering */
5011 (void) &tf;
5012#endif
Eric Andersen12de6cf2004-08-04 19:19:10 +00005013 if (hname == NULL)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005014 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005015
5016 DBGPRINTF7(("HEREIN: hname is %s, xdoll=%d\n", hname, xdoll));
5017
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005018 hf = open(hname, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00005019 if (hf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005020 return -1;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005021
Eric Andersenff9eee42001-06-29 04:57:14 +00005022 if (xdoll) {
5023 char c;
5024 char tname[30] = ".msh_XXXXXX";
5025 jmp_buf ev;
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005026
Eric Andersenff9eee42001-06-29 04:57:14 +00005027 tf = mkstemp(tname);
5028 if (tf < 0)
Denis Vlasenko079f8af2006-11-27 16:49:31 +00005029 return -1;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005030 errpt = ev;
5031 if (newenv(setjmp(errpt)) == 0) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005032 PUSHIO(afile, hf, herechar);
Denis Vlasenkoc794c512007-12-16 17:21:29 +00005033 setbase(global_env.iop);
Eric Andersenff9eee42001-06-29 04:57:14 +00005034 while ((c = subgetc(0, 0)) != 0) {
Eric Andersen8401eea2004-08-04 19:16:54 +00005035 c &= ~QUOTE;
Eric Andersenff9eee42001-06-29 04:57:14 +00005036 write(tf, &c, sizeof c);
5037 }
5038 quitenv();
5039 } else
5040 unlink(tname);
5041 close(tf);
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005042 tf = open(tname, O_RDONLY);
Eric Andersenff9eee42001-06-29 04:57:14 +00005043 unlink(tname);
Denis Vlasenkod9e15f22006-11-27 16:49:55 +00005044 return tf;
Denis Vlasenko00ccf952007-02-01 01:39:24 +00005045 }
5046 return hf;
Eric Andersenff9eee42001-06-29 04:57:14 +00005047}
5048
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005049static void scraphere(void)
Eric Andersenff9eee42001-06-29 04:57:14 +00005050{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005051 struct here *h;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005052
5053 DBGPRINTF7(("SCRAPHERE: enter...\n"));
Eric Andersenff9eee42001-06-29 04:57:14 +00005054
5055 for (h = inhere; h != NULL; h = h->h_next) {
5056 if (h->h_iop && h->h_iop->io_name)
Eric Andersen8401eea2004-08-04 19:16:54 +00005057 unlink(h->h_iop->io_name);
Eric Andersenff9eee42001-06-29 04:57:14 +00005058 }
5059 inhere = NULL;
5060}
5061
5062/* unlink here temp files before a freearea(area) */
Bernhard Reutner-Fischerf0877982006-06-25 22:08:53 +00005063static void freehere(int area)
Eric Andersenff9eee42001-06-29 04:57:14 +00005064{
"Robert P. J. Day"68229832006-07-01 13:08:46 +00005065 struct here *h, *hl;
Eric Andersen12de6cf2004-08-04 19:19:10 +00005066
5067 DBGPRINTF6(("FREEHERE: enter, area=%d\n", area));
Eric Andersenff9eee42001-06-29 04:57:14 +00005068
5069 hl = NULL;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00005070 for (h = acthere; h != NULL; h = h->h_next) {
Eric Andersenff9eee42001-06-29 04:57:14 +00005071 if (getarea((char *) h) >= area) {
5072 if (h->h_iop->io_name != NULL)
5073 unlink(h->h_iop->io_name);
5074 if (hl == NULL)
5075 acthere = h->h_next;
5076 else
5077 hl->h_next = h->h_next;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00005078 } else {
Eric Andersenff9eee42001-06-29 04:57:14 +00005079 hl = h;
Denis Vlasenko4aafd5f2008-03-02 14:33:26 +00005080 }
5081 }
Eric Andersenff9eee42001-06-29 04:57:14 +00005082}
5083
5084
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005085/* -------- sh.c -------- */
5086/*
5087 * shell
5088 */
5089
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +00005090int msh_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005091int msh_main(int argc, char **argv)
5092{
5093 int f;
5094 char *s;
5095 int cflag;
5096 char *name, **ap;
5097 int (*iof) (struct ioarg *);
5098
Denis Vlasenkoab801872007-12-02 08:35:37 +00005099 INIT_G();
5100
Denis Vlasenko55f30b02007-03-24 22:42:29 +00005101 sharedbuf.id = AFID_NOBUF;
5102 mainbuf.id = AFID_NOBUF;
Denis Vlasenko55f30b02007-03-24 22:42:29 +00005103 elinep = line + sizeof(line) - 5;
5104
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005105#if ENABLE_FEATURE_EDITING
5106 line_input_state = new_line_input_t(FOR_SHELL);
5107#endif
5108
5109 DBGPRINTF(("MSH_MAIN: argc %d, environ %p\n", argc, environ));
5110
5111 initarea();
5112 ap = environ;
5113 if (ap != NULL) {
5114 while (*ap)
5115 assign(*ap++, !COPYV);
5116 for (ap = environ; *ap;)
5117 export(lookup(*ap++));
5118 }
5119 closeall();
5120 areanum = 1;
5121
5122 shell = lookup("SHELL");
5123 if (shell->value == null)
5124 setval(shell, (char *)DEFAULT_SHELL);
5125 export(shell);
5126
5127 homedir = lookup("HOME");
5128 if (homedir->value == null)
5129 setval(homedir, "/");
5130 export(homedir);
5131
5132 setval(lookup("$"), putn(getpid()));
5133
5134 path = lookup("PATH");
5135 if (path->value == null) {
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005136 /* Can be merged with same string elsewhere in bbox */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005137 if (geteuid() == 0)
Denis Vlasenkof5f75c52007-06-12 22:35:19 +00005138 setval(path, bb_default_root_path);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005139 else
Denis Vlasenkof5f75c52007-06-12 22:35:19 +00005140 setval(path, bb_default_path);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005141 }
5142 export(path);
5143
5144 ifs = lookup("IFS");
5145 if (ifs->value == null)
5146 setval(ifs, " \t\n");
5147
5148#ifdef MSHDEBUG
5149 mshdbg_var = lookup("MSHDEBUG");
5150 if (mshdbg_var->value == null)
5151 setval(mshdbg_var, "0");
5152#endif
5153
5154 prompt = lookup("PS1");
5155#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5156 if (prompt->value == null)
5157#endif
5158 setval(prompt, DEFAULT_USER_PROMPT);
5159 if (geteuid() == 0) {
5160 setval(prompt, DEFAULT_ROOT_PROMPT);
5161 prompt->status &= ~EXPORT;
5162 }
5163 cprompt = lookup("PS2");
5164#if ENABLE_FEATURE_EDITING_FANCY_PROMPT
5165 if (cprompt->value == null)
5166#endif
5167 setval(cprompt, "> ");
5168
5169 iof = filechar;
5170 cflag = 0;
5171 name = *argv++;
5172 if (--argc >= 1) {
5173 if (argv[0][0] == '-' && argv[0][1] != '\0') {
5174 for (s = argv[0] + 1; *s; s++)
5175 switch (*s) {
5176 case 'c':
5177 prompt->status &= ~EXPORT;
5178 cprompt->status &= ~EXPORT;
5179 setval(prompt, "");
5180 setval(cprompt, "");
5181 cflag = 1;
5182 if (--argc > 0)
5183 PUSHIO(aword, *++argv, iof = nlchar);
5184 break;
5185
5186 case 'q':
5187 qflag = SIG_DFL;
5188 break;
5189
5190 case 's':
5191 /* standard input */
5192 break;
5193
5194 case 't':
5195 prompt->status &= ~EXPORT;
5196 setval(prompt, "");
5197 iof = linechar;
5198 break;
5199
5200 case 'i':
Denis Vlasenko648b44f2008-02-12 06:04:06 +00005201 interactive = 1;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005202 default:
5203 if (*s >= 'a' && *s <= 'z')
Denis Vlasenko7d4c44e2007-04-16 22:34:39 +00005204 FLAG[(int) *s]++;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005205 }
5206 } else {
5207 argv--;
5208 argc++;
5209 }
5210
5211 if (iof == filechar && --argc > 0) {
5212 setval(prompt, "");
5213 setval(cprompt, "");
5214 prompt->status &= ~EXPORT;
5215 cprompt->status &= ~EXPORT;
5216
5217/* Shell is non-interactive, activate printf-based debug */
5218#ifdef MSHDEBUG
Denis Vlasenkoed9d6212008-06-09 07:44:19 +00005219 mshdbg = mshdbg_var->value[0] - '0';
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005220 if (mshdbg < 0)
5221 mshdbg = 0;
5222#endif
5223 DBGPRINTF(("MSH_MAIN: calling newfile()\n"));
5224
5225 name = *++argv;
5226 if (newfile(name))
Denis Vlasenkoed9d6212008-06-09 07:44:19 +00005227 exit(EXIT_FAILURE); /* Exit on error */
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005228 }
5229 }
5230
5231 setdash();
5232
5233 /* This won't be true if PUSHIO has been called, say from newfile() above */
Denis Vlasenkoc794c512007-12-16 17:21:29 +00005234 if (global_env.iop < iostack) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005235 PUSHIO(afile, 0, iof);
5236 if (isatty(0) && isatty(1) && !cflag) {
Denis Vlasenko648b44f2008-02-12 06:04:06 +00005237 interactive = 1;
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005238#if !ENABLE_FEATURE_SH_EXTRA_QUIET
5239#ifdef MSHDEBUG
Denis Vlasenkoca525b42007-06-13 12:27:17 +00005240 printf("\n\n%s built-in shell (msh with debug)\n", bb_banner);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005241#else
Denis Vlasenkoca525b42007-06-13 12:27:17 +00005242 printf("\n\n%s built-in shell (msh)\n", bb_banner);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005243#endif
5244 printf("Enter 'help' for a list of built-in commands.\n\n");
5245#endif
5246 }
5247 }
5248
5249 signal(SIGQUIT, qflag);
5250 if (name && name[0] == '-') {
Denis Vlasenko648b44f2008-02-12 06:04:06 +00005251 interactive = 1;
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005252 f = open(".profile", O_RDONLY);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005253 if (f >= 0)
5254 next(remap(f));
Denis Vlasenko5f9468e2007-04-14 13:22:09 +00005255 f = open("/etc/profile", O_RDONLY);
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005256 if (f >= 0)
5257 next(remap(f));
5258 }
5259 if (interactive)
5260 signal(SIGTERM, sig);
5261
5262 if (signal(SIGINT, SIG_IGN) != SIG_IGN)
5263 signal(SIGINT, onintr);
Denis Vlasenkofee2d0c2008-02-12 10:12:18 +00005264
5265/* Handle "msh SCRIPT VAR=val params..." */
5266/* Disabled: bash does not do it! */
5267#if 0
5268 argv++;
5269 /* skip leading args of the form VAR=val */
5270 while (*argv && assign(*argv, !COPYV)) {
5271 argc--;
5272 argv++;
5273 }
5274 argv--;
5275#endif
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005276 dolv = argv;
5277 dolc = argc;
5278 dolv[0] = name;
Denis Vlasenkofee2d0c2008-02-12 10:12:18 +00005279
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005280 setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
5281
Denis Vlasenkoc794c512007-12-16 17:21:29 +00005282 DBGPRINTF(("MSH_MAIN: begin FOR loop, interactive %d, global_env.iop %p, iostack %p\n", interactive, global_env.iop, iostack));
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005283
5284 for (;;) {
Denis Vlasenkoc794c512007-12-16 17:21:29 +00005285 if (interactive && global_env.iop <= iostack) {
Denis Vlasenko489f93e2007-02-01 01:43:16 +00005286#if ENABLE_FEATURE_EDITING
5287 current_prompt = prompt->value;
5288#else
5289 prs(prompt->value);
5290#endif
5291 }
5292 onecommand();
5293 /* Ensure that getenv("PATH") stays current */
5294 setenv("PATH", path->value, 1);
5295 }
5296
5297 DBGPRINTF(("MSH_MAIN: returning.\n"));
5298}
5299
5300
Eric Andersenff9eee42001-06-29 04:57:14 +00005301/*
5302 * Copyright (c) 1987,1997, Prentice Hall
5303 * All rights reserved.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005304 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005305 * Redistribution and use of the MINIX operating system in source and
5306 * binary forms, with or without modification, are permitted provided
5307 * that the following conditions are met:
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005308 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005309 * Redistributions of source code must retain the above copyright
5310 * notice, this list of conditions and the following disclaimer.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005311 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005312 * Redistributions in binary form must reproduce the above
5313 * copyright notice, this list of conditions and the following
5314 * disclaimer in the documentation and/or other materials provided
5315 * with the distribution.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005316 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005317 * Neither the name of Prentice Hall nor the names of the software
5318 * authors or contributors may be used to endorse or promote
5319 * products derived from this software without specific prior
5320 * written permission.
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005321 *
Eric Andersenff9eee42001-06-29 04:57:14 +00005322 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS, AUTHORS, AND
5323 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
5324 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
5325 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
5326 * IN NO EVENT SHALL PRENTICE HALL OR ANY AUTHORS OR CONTRIBUTORS BE
5327 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
5328 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
5329 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
5330 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
5331 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
5332 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
5333 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5334 *
5335 */