Coverage Report

Created: 2026-10-17 06:38

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/barebox/common/hush.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/* vi: set sw=8 ts=8: */
3
/*
4
 * hush.c -- a prototype Bourne shell grammar parser
5
 *      Intended to follow the original Thompson and Ritchie
6
 *      "small and simple is beautiful" philosophy, which
7
 *      incidentally is a good match to today's BusyBox.
8
 *
9
 * Copyright (C) 2000,2001  Larry Doolittle  <larry@doolittle.boa.org>
10
 *
11
 * Credits:
12
 *      The parser routines proper are all original material, first
13
 *      written Dec 2000 and Jan 2001 by Larry Doolittle.
14
 *      The execution engine, the builtins, and much of the underlying
15
 *      support has been adapted from busybox-0.49pre's lash,
16
 *      which is Copyright (C) 2000 by Lineo, Inc., and
17
 *      written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>.
18
 *      That, in turn, is based in part on ladsh.c, by Michael K. Johnson and
19
 *      Erik W. Troan, which they placed in the public domain.  I don't know
20
 *      how much of the Johnson/Troan code has survived the repeated rewrites.
21
 * Other credits:
22
 *      simple_itoa() was lifted from boa-0.93.15
23
 *      b_addchr() derived from similar w_addchar function in glibc-2.2
24
 *      setup_redirect(), redirect_opt_num(), and big chunks of main()
25
 *        and many builtins derived from contributions by Erik Andersen
26
 *      miscellaneous bugfixes from Matt Kraai
27
 */
28
29
/** @page shell_notes Simple Shell Environment: Hush
30
 *
31
 * @par Notes from the source:
32
 *
33
 * Intended to follow the original Thompson and Ritchie "small and simple
34
 * is beautiful" philosophy, which incidentally is a good match to
35
 * today's BusyBox.
36
 *
37
 * There are two big (and related) architecture differences between
38
 * this parser and the lash parser.  One is that this version is
39
 * actually designed from the ground up to understand nearly all
40
 * of the Bourne grammar.  The second, consequential change is that
41
 * the parser and input reader have been turned inside out.  Now,
42
 * the parser is in control, and asks for input as needed.  The old
43
 * way had the input reader in control, and it asked for parsing to
44
 * take place as needed.  The new way makes it much easier to properly
45
 * handle the recursion implicit in the various substitutions, especially
46
 * across continuation lines.
47
 *
48
 * Bash grammar not implemented: (how many of these were in original sh?)
49
 * -     $@ (those sure look like weird quoting rules)
50
 * -     $_
51
 * -     ! negation operator for pipes
52
 * -     &> and >& redirection of stdout+stderr
53
 * -     Brace Expansion
54
 * -     Tilde Expansion
55
 * -     fancy forms of Parameter Expansion
56
 * -     aliases
57
 * -     Arithmetic Expansion
58
 * -     <(list) and >(list) Process Substitution
59
 * -     reserved words: case, esac, select, function
60
 * -     Here Documents ( << word )
61
 * -     Functions
62
 *
63
 * Major bugs:
64
 * -     job handling woefully incomplete and buggy
65
 * -     reserved word execution woefully incomplete and buggy
66
 *
67
 * to-do:
68
 * -     port selected bugfixes from post-0.49 busybox lash - done?
69
 * -     finish implementing reserved words: for, while, until, do, done
70
 * -     change { and } from special chars to reserved words
71
 * -     builtins: break, continue, eval, return, set, trap, ulimit
72
 * -     test magic exec
73
 * -     handle children going into background
74
 * -     clean up recognition of null pipes
75
 * -     check setting of global_argc and global_argv
76
 * -     control-C handling, probably with longjmp
77
 * -     follow IFS rules more precisely, including update semantics
78
 * -     figure out what to do with backslash-newline
79
 * -     explain why we use signal instead of sigaction
80
 * -     propagate syntax errors, die on resource errors?
81
 * -     continuation lines, both explicit and implicit - done?
82
 * -     memory leak finding and plugging - done?
83
 * -     more testing, especially quoting rules and redirection
84
 * -     document how quoting rules not precisely followed for variable assignments
85
 * -     maybe change map[] to use 2-bit entries
86
 * -     (eventually) remove all the printf's
87
 *
88
 * Things that do _not_ work in this environment:
89
 *
90
 * - redirecting (stdout to a file for example)
91
 * - recursion
92
 *
93
 * Enable the "Hush parser" in "General Settings", "Select your shell" to
94
 * get the new console feeling.
95
 *
96
 */
97
98
#define pr_fmt(fmt) "hush: " fmt
99
100
#include <talloc.h>
101
#include <malloc.h>         /* malloc, free, realloc*/
102
#include <xfuncs.h>
103
#include <linux/ctype.h>    /* isalpha, isdigit */
104
#include <common.h>        /* readline */
105
#include <environment.h>
106
#include <command.h>        /* find_cmd */
107
#include <driver.h>
108
#include <errno.h>
109
#include <fs.h>
110
#include <libbb.h>
111
#include <password.h>
112
#include <glob.h>
113
#include <slice.h>
114
#include <getopt.h>
115
#include <libfile.h>
116
#include <magicvar.h>
117
#include <structio.h>
118
#include <linux/list.h>
119
#include <binfmt.h>
120
#include <init.h>
121
#include <shell.h>
122
#include <security/config.h>
123
124
/*cmd_boot.c*/
125
extern int do_bootd(int flag, int argc, char *argv[]);      /* do_bootd */
126
0
#define SPECIAL_VAR_SYMBOL 03
127
128
129
0
#define EXIT_SUCCESS 0
130
0
#define EOF -1
131
0
#define xstrdup strdup
132
0
#define error_msg printf
133
134
typedef enum {
135
  PIPE_SEQ = 1,
136
  PIPE_AND = 2,
137
  PIPE_OR  = 3,
138
  PIPE_BG  = 4,
139
} pipe_style;
140
141
/* might eventually control execution */
142
typedef enum {
143
  RES_NONE  = 0,
144
  RES_IF    = 1,
145
  RES_THEN  = 2,
146
  RES_ELIF  = 3,
147
  RES_ELSE  = 4,
148
  RES_FI    = 5,
149
  RES_FOR   = 6,
150
  RES_WHILE = 7,
151
  RES_UNTIL = 8,
152
  RES_DO    = 9,
153
  RES_DONE  = 10,
154
  RES_XXXX  = 11,
155
  RES_IN    = 12,
156
  RES_SNTX  = 13
157
} reserved_style;
158
0
#define FLAG_END   (1<<RES_NONE)
159
#define FLAG_IF    (1<<RES_IF)
160
#define FLAG_THEN  (1<<RES_THEN)
161
#define FLAG_ELIF  (1<<RES_ELIF)
162
#define FLAG_ELSE  (1<<RES_ELSE)
163
#define FLAG_FI    (1<<RES_FI)
164
#define FLAG_FOR   (1<<RES_FOR)
165
#define FLAG_WHILE (1<<RES_WHILE)
166
#define FLAG_UNTIL (1<<RES_UNTIL)
167
#define FLAG_DO    (1<<RES_DO)
168
#define FLAG_DONE  (1<<RES_DONE)
169
#define FLAG_IN    (1<<RES_IN)
170
0
#define FLAG_START (1<<RES_XXXX)
171
172
0
#define FLAG_EXIT_FROM_LOOP 1
173
0
#define FLAG_PARSE_SEMICOLON (1 << 1)    /* symbol ';' is special for parser */
174
0
#define FLAG_REPARSING       (1 << 2)    /* >=2nd pass */
175
176
struct option {
177
  struct list_head  list;
178
  char  opt;
179
  char  *optarg;
180
};
181
182
/* This holds pointers to the various results of parsing */
183
struct p_context {
184
  const void *scope;
185
  struct child_prog *child;
186
  struct pipe *list_head;
187
  struct pipe *pipe;
188
  reserved_style w;
189
  int old_flag;       /* for figuring out valid reserved words */
190
  struct p_context *stack;
191
  int type;     /* define type of parser : ";$" common or special symbol */
192
  /* How about quoting status? */
193
194
  char **global_argv;
195
  unsigned int global_argc;
196
197
  int options_parsed;
198
  struct list_head options;
199
};
200
201
202
struct child_prog {
203
  char **argv;        /* program name and arguments */
204
  int    argc;                            /* number of program arguments */
205
  struct pipe *group;     /* if non-NULL, first in group or subshell */
206
  int sp;       /* number of SPECIAL_VAR_SYMBOL */
207
  int type;
208
  glob_t glob_result;     /* result of parameter globbing */
209
};
210
211
struct pipe {
212
  int num_progs;        /* total number of programs in job */
213
  struct child_prog *progs; /* array of commands in pipe */
214
  struct pipe *next;      /* to track background commands */
215
  pipe_style followup;    /* PIPE_BG, PIPE_SEQ, PIPE_OR, PIPE_AND */
216
  reserved_style r_mode;    /* supports if, for, while, until */
217
};
218
219
220
static char console_buffer[CONFIG_CBSIZE];    /* console I/O buffer */
221
222
/* globals, connect us to the outside world
223
 * the first three support $?, $#, and $1 */
224
static unsigned int last_return_code;
225
226
int shell_get_last_return_code(void)
227
0
{
228
0
  return last_return_code;
229
0
}
230
231
/* "globals" within this file */
232
static uchar *ifs;
233
static char map[256];
234
235
#define B_CHUNK (100)
236
0
#define B_NOSPAC 1
237
238
typedef struct {
239
  char *data;
240
  int length;
241
  int maxlen;
242
  int quote;
243
  int nonnull;
244
} o_string;
245
0
#define NULL_O_STRING {NULL,0,0,0,0}
246
/* used for initialization:
247
  o_string foo = NULL_O_STRING; */
248
249
/* I can almost use ordinary FILE *.  Is open_memstream() universally
250
 * available?  Where is it documented? */
251
struct in_str {
252
  const char *p;
253
  int interrupt;
254
  int promptmode;
255
  int (*get) (struct in_str *);
256
  int (*peek) (struct in_str *);
257
};
258
0
#define b_getch(input) ((input)->get(input))
259
0
#define b_peek(input) ((input)->peek(input))
260
261
#ifdef HUSH_DEBUG
262
#define hush_debug(fmt, arg...) debug(fmt, ##arg)
263
#else
264
#define hush_debug(fmt, arg...)
265
#endif
266
267
#define final_printf hush_debug
268
269
static void syntax(void)
270
0
{
271
0
  printf("syntax error\n");
272
0
}
273
274
static void syntaxf(const char *fmt, ...)
275
0
{
276
0
  va_list args;
277
278
0
  printf("syntax error: ");
279
280
0
  va_start(args, fmt);
281
282
0
  vprintf(fmt, args);
283
284
0
  va_end(args);
285
0
}
286
287
static void syntax_unexpected_token(const char *token)
288
0
{
289
0
  syntaxf("unexpected token `%s'\n", token);
290
0
}
291
292
/*   o_string manipulation: */
293
static int b_check_space(o_string *o, int len);
294
static int b_addchr(o_string *o, int ch);
295
static void b_reset(o_string *o);
296
/*  in_str manipulations: */
297
static int static_get(struct in_str *i);
298
static int static_peek(struct in_str *i);
299
static int file_get(struct in_str *i);
300
static int file_peek(struct in_str *i);
301
static void setup_file_in_str(struct in_str *i);
302
static void setup_string_in_str(struct in_str *i, const char *s);
303
/*  "run" the final data structures: */
304
static int free_pipe_list(struct pipe *head, int indent);
305
static int free_pipe(struct pipe *pi, int indent);
306
/*  really run the final data structures: */
307
static int run_list_real(struct p_context *ctx, struct pipe *pi);
308
static int run_pipe_real(struct p_context *ctx, struct pipe *pi);
309
/*   extended glob support: */
310
/*   variable assignment: */
311
static int is_assignment(const char *s);
312
/*   data structure manipulation: */
313
static void initialize_context(struct p_context *ctx, bool newscope);
314
static void release_context(struct p_context *ctx);
315
static int done_word(o_string *dest, struct p_context *ctx);
316
static int done_command(struct p_context *ctx);
317
static int done_pipe(struct p_context *ctx, pipe_style type);
318
/*   primary string parsing: */
319
static const char *lookup_param(char *src);
320
static char *make_string(char **inp);
321
static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input);
322
static int parse_stream(o_string *dest, struct p_context *ctx, struct in_str *input0, int end_trigger);
323
/*   setup: */
324
static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int flag);
325
326
static int parse_string_outer(struct p_context *ctx, const char *s, int flag);
327
/*     local variable support */
328
static char **make_list_in(char **inp, char *name);
329
static char *insert_var_value(char *inp);
330
static int set_local_var(const char *s, int flg_export);
331
static int execute_script(const char *path, int argc, char *argv[]);
332
static int source_script(const char *path, int argc, char *argv[]);
333
334
static int b_check_space(o_string *o, int len)
335
0
{
336
  /* It would be easy to drop a more restrictive policy
337
   * in here, such as setting a maximum string length */
338
0
  if (o->length + len > o->maxlen) {
339
0
    char *old_data = o->data;
340
    /* assert (data == NULL || o->maxlen != 0); */
341
0
    o->maxlen += max(2*len, B_CHUNK);
342
0
    o->data = realloc(o->data, 1 + o->maxlen);
343
0
    if (o->data == NULL) {
344
0
      free(old_data);
345
0
    }
346
0
  }
347
0
  return o->data == NULL;
348
0
}
349
350
static int b_addchr(o_string *o, int ch)
351
0
{
352
0
  hush_debug("%s: %c %d %p\n", __func__, ch, o->length, o);
353
354
0
  if (b_check_space(o, 1))
355
0
    return B_NOSPAC;
356
357
0
  o->data[o->length] = ch;
358
0
  o->length++;
359
0
  o->data[o->length] = '\0';
360
361
0
  return 0;
362
0
}
363
364
static int b_addstr(o_string *o, const char *str)
365
0
{
366
0
  int ret;
367
368
0
  while (*str) {
369
0
    ret = b_addchr(o, *str++);
370
0
    if (ret)
371
0
      return ret;
372
0
  }
373
374
0
  return 0;
375
0
}
376
377
static void b_reset(o_string *o)
378
0
{
379
0
  o->length = 0;
380
0
  o->nonnull = 0;
381
382
0
  if (o->data != NULL)
383
0
    *o->data = '\0';
384
0
}
385
386
static void b_free(o_string *o)
387
0
{
388
0
  b_reset(o);
389
0
  free(o->data);
390
0
  o->data = NULL;
391
0
  o->maxlen = 0;
392
0
}
393
394
static int b_adduint(o_string *o, unsigned int i)
395
0
{
396
0
  int r;
397
  /* 21 digits plus null terminator, good for 64-bit or smaller
398
   * ints */
399
0
  char number[22];
400
0
  char *p = number;
401
402
0
  snprintf(number, sizeof(number), "%u", i);
403
404
  /* no escape checking necessary */
405
0
  do {
406
0
    r = b_addchr(o, *p++);
407
0
  } while (r == 0 && *p);
408
409
0
  return r;
410
0
}
411
412
static int static_get(struct in_str *i)
413
0
{
414
0
  int ch = *i->p++;
415
416
0
  if (ch == '\0')
417
0
    return EOF;
418
419
0
  return ch;
420
0
}
421
422
423
static int static_peek(struct in_str *i)
424
0
{
425
0
  return *i->p;
426
0
}
427
428
static char *getprompt(void)
429
0
{
430
0
  static char prompt[PATH_MAX + 32];
431
432
0
#ifdef CONFIG_HUSH_FANCY_PROMPT
433
0
  const char *ps1, *prompt_command;
434
0
  struct p_context ctx = {};
435
436
0
  prompt_command = getenv("PROMPT_COMMAND");
437
0
  if (prompt_command) {
438
0
    unsigned int lr = last_return_code;
439
440
0
    initialize_context(&ctx, false);
441
0
    parse_string_outer(&ctx, prompt_command, FLAG_PARSE_SEMICOLON);
442
0
    release_context(&ctx);
443
444
0
    last_return_code = lr;
445
0
  }
446
447
0
  ps1 = getenv("PS1");
448
0
  if (ps1)
449
0
    process_escape_sequence(ps1, prompt, PATH_MAX + 32);
450
0
  else
451
0
#endif
452
0
  sprintf(prompt, "%s%s ", CONFIG_PROMPT, getcwd());
453
454
0
  return prompt;
455
0
}
456
457
static void get_user_input(struct in_str *i)
458
0
{
459
0
  int n;
460
0
  static char the_command[CONFIG_CBSIZE];
461
0
  char *prompt;
462
463
0
  if (i->promptmode == 1)
464
0
    prompt = getprompt();
465
0
  else
466
0
    prompt = CONFIG_PROMPT_HUSH_PS2;
467
468
0
  command_slice_release();
469
470
0
  n = readline(prompt, console_buffer, CONFIG_CBSIZE - 1);
471
472
0
  command_slice_acquire();
473
474
0
  if (n == -1 ) {
475
0
    i->interrupt = 1;
476
0
    n = 0;
477
0
  }
478
479
0
  console_buffer[n] = '\n';
480
0
  console_buffer[n + 1]= '\0';
481
482
0
  if (i->promptmode == 1) {
483
0
    strcpy(the_command,console_buffer);
484
0
    i->p = the_command;
485
0
    return;
486
0
  }
487
488
0
  if (console_buffer[0] != '\n') {
489
0
    if (strlen(the_command) + strlen(console_buffer)
490
0
        < CONFIG_CBSIZE) {
491
0
      n = strlen(the_command);
492
0
      the_command[n - 1] = ' ';
493
0
      strcpy(&the_command[n], console_buffer);
494
0
    } else {
495
0
      the_command[0] = '\n';
496
0
      the_command[1] = '\0';
497
0
    }
498
0
  }
499
500
0
  if (i->interrupt) {
501
0
    the_command[0] = '\n';
502
0
    the_command[1] = '\0';
503
0
  }
504
505
0
  i->p = console_buffer;
506
0
}
507
508
/* This is the magic location that prints prompts
509
 * and gets data back from the user */
510
static int file_get(struct in_str *i)
511
0
{
512
0
  int ch;
513
514
0
  ch = 0;
515
516
  /* If there is data waiting, eat it up */
517
0
  if (i->p && *i->p)
518
0
    return *i->p++;
519
520
  /* need to double check i->file because we might be doing something
521
   * more complicated by now, like sourcing or substituting. */
522
0
  while (!i->p  || strlen(i->p) == 0 )
523
0
    get_user_input(i);
524
525
0
  i->promptmode = 2;
526
527
0
  if (i->p && *i->p)
528
0
    ch = *i->p++;
529
530
0
  hush_debug("%s: got a %d\n", __func__, ch);
531
532
0
  return ch;
533
0
}
534
535
/* All the callers guarantee this routine will never be
536
 * used right after a newline, so prompting is not needed.
537
 */
538
static int file_peek(struct in_str *i)
539
0
{
540
0
    return *i->p;
541
0
}
542
543
static void setup_file_in_str(struct in_str *i)
544
0
{
545
0
  i->peek = file_peek;
546
0
  i->get = file_get;
547
0
  i->interrupt = 0;
548
0
  i->promptmode = 1;
549
0
  i->p = NULL;
550
0
}
551
552
static void setup_string_in_str(struct in_str *i, const char *s)
553
0
{
554
0
  i->peek = static_peek;
555
0
  i->get = static_get;
556
0
  i->interrupt = 0;
557
0
  i->promptmode = 1;
558
0
  i->p = s;
559
0
}
560
561
#ifdef CONFIG_CMD_GETOPT
562
static int builtin_getopt(struct p_context *ctx, struct child_prog *child,
563
    int argc, char *argv[])
564
0
{
565
0
  char *optstring, *var;
566
0
  int opt, ret = 0;
567
0
  char opta[2];
568
0
  struct option *o;
569
0
  struct getopt_context gc;
570
571
0
  if (argc != 3)
572
0
    return -2 - 1;
573
574
0
  optstring = argv[1];
575
0
  var = argv[2];
576
577
0
  getopt_context_store(&gc);
578
579
0
  if (!ctx->options_parsed) {
580
0
    while ((opt = getopt(ctx->global_argc, ctx->global_argv, optstring)) > 0) {
581
0
      o = xzalloc(sizeof(*o));
582
0
      o->opt = opt;
583
0
      o->optarg = xstrdup(optarg);
584
0
      list_add_tail(&o->list, &ctx->options);
585
0
    }
586
0
    ctx->global_argv += optind - 1;
587
0
    ctx->global_argc -= optind - 1;
588
0
  }
589
590
0
  ctx->options_parsed = 1;
591
592
0
  if (list_empty(&ctx->options)) {
593
0
    ret = -1;
594
0
    goto out;
595
0
  }
596
597
0
  o = list_first_entry(&ctx->options, struct option, list);
598
599
0
  opta[0] = o->opt;
600
0
  opta[1] = 0;
601
0
  setenv(var, opta);
602
0
  setenv("OPTARG", o->optarg);
603
604
0
  free(o->optarg);
605
0
  list_del(&o->list);
606
0
  free(o);
607
0
out:
608
0
  getopt_context_restore(&gc);
609
610
0
  return ret;
611
0
}
612
613
BAREBOX_MAGICVAR(OPTARG, "optarg for hush builtin getopt");
614
#else
615
static int builtin_getopt(struct p_context *ctx, struct child_prog *child,
616
    int argc, char *argv[])
617
{
618
  return -1;
619
}
620
#endif
621
622
static int builtin_exit(struct p_context *ctx, struct child_prog *child,
623
    int argc, char *argv[])
624
0
{
625
0
  int r;
626
627
0
  r = last_return_code;
628
0
  if (argc > 1)
629
0
    r = simple_strtoul(argv[1], NULL, 0);
630
631
0
  return -r - 2;
632
0
}
633
634
static void remove_quotes_in_str(char *src)
635
0
{
636
0
  char *trg = src;
637
0
  bool in_double_quotes = false;
638
639
0
  while (*src) {
640
0
    if (*src == '\'') {
641
0
      src++;
642
0
      while (*src != '\'')
643
0
        *trg++ = *src++;
644
0
      src++;
645
0
      continue;
646
0
    }
647
648
    /* drop quotes */
649
0
    if (*src == '"') {
650
0
      in_double_quotes = !in_double_quotes;
651
0
      src++;
652
0
      continue;
653
0
    }
654
655
    /* replace \" with " */
656
0
    if (*src == '\\' && *(src + 1) == '"') {
657
0
      *trg++ = '"';
658
0
      src += 2;
659
0
      continue;
660
0
    }
661
662
    /* replace \' with ' */
663
0
    if (*src == '\\' && *(src + 1) == '\'') {
664
0
      *trg++ = '\'';
665
0
      src += 2;
666
0
      continue;
667
0
    }
668
669
    /* replace \\ with \ */
670
0
    if (*src == '\\' && *(src + 1) == '\\') {
671
0
      *trg++ = '\\';
672
0
      src += 2;
673
0
      continue;
674
0
    }
675
676
    /* replace '\ ' with ' ' */
677
0
    if (!in_double_quotes && *src == '\\' && *(src + 1) == ' ') {
678
0
      *trg++ = ' ';
679
0
      src += 2;
680
0
      continue;
681
0
    }
682
683
0
    *trg++ = *src++;
684
0
  }
685
0
  *trg = 0;
686
0
}
687
688
static void remove_quotes(int argc, char *argv[])
689
0
{
690
0
  int i;
691
692
0
  for (i = 0; i < argc; i++)
693
0
    remove_quotes_in_str(argv[i]);
694
0
}
695
696
static int fake_glob(const char *src, int flags,
697
    int (*errfunc) (const char *epath, int eerrno),
698
    glob_t *pglob)
699
0
{
700
0
  int pathc;
701
702
0
  if (!(flags & GLOB_APPEND)) {
703
0
    globfree(pglob);
704
0
    pglob->gl_pathv = NULL;
705
0
    pglob->gl_pathc = 0;
706
0
    pglob->gl_offs = 0;
707
0
  }
708
0
  pathc = ++pglob->gl_pathc;
709
0
  pglob->gl_pathv = xrealloc(pglob->gl_pathv, (pathc + 1) * sizeof(*pglob->gl_pathv));
710
0
  pglob->gl_pathv[pathc - 1] = xstrdup(src);
711
0
  pglob->gl_pathv[pathc] = NULL;
712
713
0
  return 0;
714
0
}
715
716
#ifdef CONFIG_GLOB
717
static int do_glob(const char *src, int flags,
718
    int (*errfunc) (const char *epath, int eerrno),
719
    glob_t *pglob)
720
0
{
721
0
  return glob(src, flags, errfunc, pglob);
722
0
}
723
#else
724
static int do_glob(const char *src, int flags,
725
    int (*errfunc) (const char *epath, int eerrno),
726
    glob_t *pglob)
727
{
728
  return fake_glob(src, flags, errfunc, pglob);
729
}
730
#endif
731
732
static void do_glob_in_argv(glob_t *globbuf, int argc, char **argv)
733
0
{
734
0
  int i;
735
0
  int flags;
736
737
0
  globbuf->gl_offs = 0;
738
0
  flags = GLOB_DOOFFS | GLOB_NOCHECK;
739
740
0
  for (i = 0; i < argc; i++) {
741
0
    do_glob(argv[i], flags, NULL, globbuf);
742
0
    flags |= GLOB_APPEND;
743
0
  }
744
0
}
745
746
/* run_pipe_real() starts all the jobs, but doesn't wait for anything
747
 * to finish.  See checkjobs().
748
 *
749
 * return code is normally -1, when the caller has to wait for children
750
 * to finish to determine the exit status of the pipe.  If the pipe
751
 * is a simple builtin command, however, the action is done by the
752
 * time run_pipe_real returns, and the exit code is provided as the
753
 * return value.
754
 *
755
 * The input of the pipe is always stdin, the output is always
756
 * stdout.  The outpipe[] mechanism in BusyBox-0.48 lash is bogus,
757
 * because it tries to avoid running the command substitution in
758
 * subshell, when that is in fact necessary.  The subshell process
759
 * now has its stdout directed to the input of the appropriate pipe,
760
 * so this routine is noticeably simpler.
761
 */
762
static int run_pipe_real(struct p_context *ctx, struct pipe *pi)
763
0
{
764
0
  int i;
765
0
  int nextin;
766
0
  struct child_prog *child;
767
0
  char *p;
768
0
  glob_t globbuf = {};
769
0
  int ret;
770
0
  int rcode;
771
0
# if __GNUC__
772
  /* Avoid longjmp clobbering */
773
0
  (void) &i;
774
0
  (void) &nextin;
775
0
  (void) &child;
776
0
# endif
777
778
0
  nextin = 0;
779
780
  /*
781
   * We do not support pipes in barebox, so pi->num_progs can't
782
   * be bigger than 1. pi->num_progs == 0 is already caught in
783
   * the caller, so everything else than 1 is a bug.
784
   */
785
0
  BUG_ON(pi->num_progs != 1);
786
787
0
  child = &pi->progs[0];
788
789
0
  if (child->group) {
790
0
    hush_debug("non-subshell grouping\n");
791
0
    rcode = run_list_real(ctx, child->group);
792
793
0
    return rcode;
794
0
  }
795
796
0
  if (!pi->progs[0].argv)
797
0
    return -1;
798
799
0
  for (i = 0; is_assignment(child->argv[i]); i++)
800
0
    { /* nothing */ }
801
802
0
  if (i != 0 && child->argv[i] == NULL) {
803
    /* assignments, but no command: set the local environment */
804
0
    for (i = 0; child->argv[i] != NULL; i++) {
805
806
      /* Ok, this case is tricky.  We have to decide if this is a
807
       * local variable, or an already exported variable.  If it is
808
       * already exported, we have to export the new value.  If it is
809
       * not exported, we need only set this as a local variable.
810
       * This junk is all to decide whether or not to export this
811
       * variable. */
812
0
      int export_me = 0;
813
814
0
      hush_debug("Local environment set: %s\n", child->argv[i]);
815
816
0
      p = insert_var_value(child->argv[i]);
817
0
      rcode = set_local_var(p, export_me);
818
0
      if (rcode)
819
0
        return 1;
820
821
0
      if (p != child->argv[i])
822
0
        free(p);
823
0
    }
824
0
    return EXIT_SUCCESS;   /* don't worry about errors in set_local_var() yet */
825
0
  }
826
0
  for (i = 0; is_assignment(child->argv[i]); i++) {
827
0
    p = insert_var_value(child->argv[i]);
828
0
    rcode = set_local_var(p, 0);
829
0
    if (rcode)
830
0
      return 1;
831
832
0
    if (p != child->argv[i]) {
833
0
      child->sp--;
834
0
      free(p);
835
0
    }
836
0
  }
837
0
  if (child->sp) {
838
0
    char * str = NULL;
839
0
    struct p_context ctx1;
840
841
0
    initialize_context(&ctx1, true);
842
843
0
    str = make_string((child->argv + i));
844
0
    rcode = parse_string_outer(&ctx1, str, FLAG_EXIT_FROM_LOOP | FLAG_REPARSING);
845
0
    release_context(&ctx1);
846
0
    free(str);
847
848
0
    return rcode;
849
0
  }
850
851
0
  do_glob_in_argv(&globbuf, child->argc - i, &child->argv[i]);
852
853
0
  if (!globbuf.gl_pathv)
854
0
    return -1;
855
856
0
  remove_quotes(globbuf.gl_pathc, globbuf.gl_pathv);
857
858
0
  if (!strcmp(globbuf.gl_pathv[0], "getopt") &&
859
0
      IS_ENABLED(CONFIG_CMD_GETOPT)) {
860
0
    ret = builtin_getopt(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv);
861
0
  } else if (!strcmp(globbuf.gl_pathv[0], "exit")) {
862
0
    ret = builtin_exit(ctx, child, globbuf.gl_pathc, globbuf.gl_pathv);
863
0
  } else {
864
0
    ret = execute_binfmt(globbuf.gl_pathc, globbuf.gl_pathv);
865
0
    if (ret < 0) {
866
0
      stnoprintf("%s: %pe\n", globbuf.gl_pathv[0], ERR_PTR(ret));
867
0
      ret = 127;
868
0
    }
869
0
  }
870
871
0
  globfree(&globbuf);
872
873
0
  return ret;
874
0
}
875
876
static int run_list_real(struct p_context *ctx, struct pipe *pi)
877
0
{
878
0
  char *save_name = NULL;
879
0
  char **list = NULL;
880
0
  char **save_list = NULL;
881
0
  struct pipe *rpipe;
882
0
  int flag_rep = 0;
883
0
  int rcode=0, flag_skip=1;
884
0
  int flag_restore = 0, flag_conditional = 0;
885
0
  int if_code=0, next_if_code=0;  /* need double-buffer to handle elif */
886
0
  reserved_style rmode, skip_more_in_this_rmode = RES_XXXX;
887
888
  /* check syntax for "for" */
889
0
  for (rpipe = pi; rpipe; rpipe = rpipe->next) {
890
0
    if ((rpipe->r_mode == RES_IN ||
891
0
        rpipe->r_mode == RES_FOR) &&
892
0
        (rpipe->next == NULL)) {
893
0
      syntax();
894
0
      return 1;
895
0
    }
896
0
    if ((rpipe->r_mode == RES_IN &&
897
0
        (rpipe->next->r_mode == RES_IN &&
898
0
        rpipe->next->progs->argv != NULL))||
899
0
        (rpipe->r_mode == RES_FOR &&
900
0
        rpipe->next->r_mode != RES_IN)) {
901
0
      syntax();
902
0
      return 1;
903
0
    }
904
0
  }
905
0
  for (; pi; pi = (flag_restore != 0) ? rpipe : pi->next) {
906
0
    if (pi->r_mode == RES_WHILE || pi->r_mode == RES_UNTIL ||
907
0
        pi->r_mode == RES_FOR) {
908
      /* check Ctrl-C */
909
0
      if (ctrlc())
910
0
        return 1;
911
0
      flag_restore = 0;
912
0
      if (!rpipe) {
913
0
        flag_rep = 0;
914
0
        rpipe = pi;
915
0
      }
916
0
    }
917
0
    rmode = pi->r_mode;
918
0
    hush_debug("rmode=%d  if_code=%d  next_if_code=%d skip_more=%d\n",
919
0
        rmode, if_code, next_if_code, skip_more_in_this_rmode);
920
0
    if (rmode == skip_more_in_this_rmode && flag_skip) {
921
0
      if (pi->followup == PIPE_SEQ)
922
0
        flag_skip=0;
923
0
      continue;
924
0
    }
925
926
0
    flag_skip = 1;
927
0
    skip_more_in_this_rmode = RES_XXXX;
928
929
0
    if (rmode == RES_THEN || rmode == RES_ELSE)
930
0
      if_code = next_if_code;
931
932
0
    if (rmode == RES_THEN &&  if_code)
933
0
      continue;
934
935
0
    if (rmode == RES_ELSE && !if_code)
936
0
      continue;
937
938
0
    if (rmode == RES_ELIF && !if_code)
939
0
      break;
940
941
0
    if (rmode == RES_FOR && pi->num_progs) {
942
0
      if (!list) {
943
        /* if no variable values after "in" we skip "for" */
944
0
        if (!pi->next->progs->argv)
945
0
          continue;
946
947
        /* create list of variable values */
948
0
        list = make_list_in(pi->next->progs->argv,
949
0
          pi->progs->argv[0]);
950
0
        save_list = list;
951
0
        save_name = pi->progs->argv[0];
952
0
        pi->progs->argv[0] = NULL;
953
0
        flag_rep = 1;
954
0
      }
955
0
      if (!(*list)) {
956
0
        free(pi->progs->argv[0]);
957
0
        free(save_list);
958
0
        list = NULL;
959
0
        flag_rep = 0;
960
0
        pi->progs->argv[0] = save_name;
961
0
        continue;
962
0
      } else {
963
        /* insert new value from list for variable */
964
0
        if (pi->progs->argv[0])
965
0
          free(pi->progs->argv[0]);
966
0
        pi->progs->argv[0] = *list++;
967
0
      }
968
0
    }
969
0
    if (rmode == RES_IN)
970
0
      continue;
971
972
0
    if (rmode == RES_DO) {
973
0
      if (!flag_rep)
974
0
        continue;
975
0
    }
976
977
0
    if (rmode == RES_DONE) {
978
0
      if (flag_rep) {
979
0
        flag_restore = 1;
980
0
      } else {
981
0
        rpipe = NULL;
982
0
      }
983
0
    }
984
985
0
    if (pi->num_progs == 0)
986
0
      continue;
987
988
0
    rcode = run_pipe_real(ctx, pi);
989
0
    hush_debug("run_pipe_real returned %d\n",rcode);
990
991
0
    if (rcode < -1) {
992
0
      last_return_code = -rcode - 2;
993
0
      return rcode; /* exit */
994
0
    }
995
996
    /* Conditional statements like "if", "elif", "while" and "until"
997
     * return 1 if conditional is not met. This is standard behavior.
998
     * However this does not mean that this value (1) should be
999
     * returned as exit code, as it suggests generic error code.
1000
     * Catch this by raising a flag and check it later on.
1001
     */
1002
0
    if (rcode == 1) {
1003
0
      if (rmode == RES_IF || rmode == RES_ELIF ||
1004
0
        rmode == RES_WHILE || rmode == RES_UNTIL)
1005
0
        flag_conditional = 1;
1006
0
      else
1007
0
        flag_conditional = 0;
1008
0
    }
1009
1010
0
    last_return_code = rcode;
1011
1012
0
    if (rmode == RES_IF || rmode == RES_ELIF )
1013
0
      next_if_code = rcode;  /* can be overwritten a number of times */
1014
1015
0
    if (rmode == RES_WHILE)
1016
0
      flag_rep = !last_return_code;
1017
1018
0
    if (rmode == RES_UNTIL)
1019
0
      flag_rep = last_return_code;
1020
1021
0
    if ((rcode == EXIT_SUCCESS && pi->followup == PIPE_OR) ||
1022
0
         (rcode != EXIT_SUCCESS && pi->followup == PIPE_AND) )
1023
0
      skip_more_in_this_rmode = rmode;
1024
0
  }
1025
1026
  /* Substitute exit code in case flag_conditional is set. */
1027
0
  if (flag_conditional == 1 && last_return_code == 1) {
1028
0
    last_return_code = 0;
1029
0
    rcode = 0;
1030
0
  }
1031
1032
0
  return rcode;
1033
0
}
1034
1035
/* broken, of course, but OK for testing */
1036
static __maybe_unused char *indenter(int i)
1037
0
{
1038
0
  static char blanks[] = "                                    ";
1039
0
  return &blanks[sizeof(blanks) - i - 1];
1040
0
}
1041
1042
/* return code is the exit status of the pipe */
1043
static int free_pipe(struct pipe *pi, int indent)
1044
0
{
1045
0
  struct child_prog *child;
1046
0
  int i, ret_code = 0;
1047
1048
0
  for (i = 0; i < pi->num_progs; i++) {
1049
1050
0
    child = &pi->progs[i];
1051
0
    final_printf("%s  command %d:\n", indenter(indent), i);
1052
1053
0
    if (child->argv) {
1054
#ifdef HUSH_DEBUG
1055
      char **p;
1056
      int a;
1057
1058
      for (a = 0,p = child->argv; *p; a++,p++) {
1059
        final_printf("%s   argv[%d] = %s\n",
1060
            indenter(indent),a,*p);
1061
      }
1062
#endif
1063
0
      globfree(&child->glob_result);
1064
0
      child->argv = NULL;
1065
0
    } else if (child->group) {
1066
0
      ret_code = free_pipe_list(child->group,indent+3);
1067
0
      final_printf("%s   end group\n",indenter(indent));
1068
0
    } else {
1069
0
      final_printf("%s   (nil)\n",indenter(indent));
1070
0
    }
1071
0
  }
1072
1073
  /* children are an array, they get freed all at once */
1074
0
  talloc_free(pi->progs);
1075
0
  pi->progs = NULL;
1076
1077
0
  return ret_code;
1078
0
}
1079
1080
static int free_pipe_list(struct pipe *head, int indent)
1081
0
{
1082
0
  int rcode = 0;   /* if list has no members */
1083
0
  struct pipe *pi, *next;
1084
1085
0
  for (pi = head; pi; pi = next) {
1086
0
    final_printf("%s pipe reserved mode %d\n", indenter(indent), pi->r_mode);
1087
0
    rcode = free_pipe(pi, indent);
1088
0
    final_printf("%s pipe followup code %d\n", indenter(indent), pi->followup);
1089
0
    next = pi->next;
1090
0
    pi->next = NULL;
1091
0
    talloc_free(pi);
1092
0
  }
1093
0
  return rcode;
1094
0
}
1095
1096
static int xglob(o_string *dest, int flags, glob_t *pglob, int glob_needed)
1097
0
{
1098
0
  int gr;
1099
1100
  /* short-circuit for null word */
1101
  /* we can code this better when the debug's are gone */
1102
0
  if (dest->length == 0) {
1103
0
    if (dest->nonnull) {
1104
      /* bash man page calls this an "explicit" null */
1105
0
      gr = fake_glob(dest->data, flags, NULL, pglob);
1106
0
      hush_debug("globhack returned %d\n",gr);
1107
0
    } else {
1108
0
      return 0;
1109
0
    }
1110
0
  } else if (glob_needed) {
1111
0
    gr = do_glob(dest->data, flags, NULL, pglob);
1112
0
    hush_debug("glob returned %d\n",gr);
1113
0
  } else {
1114
0
    gr = fake_glob(dest->data, flags, NULL, pglob);
1115
0
    hush_debug("globhack returned %d\n",gr);
1116
0
  }
1117
0
  if (gr != 0) { /* GLOB_ABORTED ? */
1118
0
    error_msg("glob(3) error %d",gr);
1119
0
  }
1120
1121
  /* globprint(glob_target); */
1122
1123
0
  return gr;
1124
0
}
1125
1126
/* Select which version we will use */
1127
static int run_list(struct p_context *ctx, struct pipe *pi)
1128
0
{
1129
0
  int rcode = 0;
1130
1131
0
  rcode = run_list_real(ctx, pi);
1132
1133
  /* free_pipe_list has the side effect of clearing memory
1134
   * In the long run that function can be merged with run_list_real,
1135
   * but doing that now would hobble the debugging effort. */
1136
0
  free_pipe_list(pi, 0);
1137
1138
0
  return rcode;
1139
0
}
1140
1141
static char *get_dollar_var(char ch);
1142
1143
/* This is used to set local shell variables
1144
   flg_export==0 if only local (not exporting) variable
1145
   flg_export==1 if "new" exporting environ
1146
   flg_export>1  if current startup environ (not call putenv()) */
1147
static int set_local_var(const char *s, int flg_export)
1148
0
{
1149
0
  char *name, *value;
1150
0
  int ret;
1151
1152
  /* might be possible! */
1153
0
  if (!isalpha(*s))
1154
0
    return -1;
1155
1156
0
  name = strdup(s);
1157
1158
  /* Assume when we enter this function that we are already in
1159
   * NAME=VALUE format.  So the first order of business is to
1160
   * split 's' on the '=' into 'name' and 'value' */
1161
0
  value = parse_assignment(name);
1162
0
  if (!value) {
1163
0
    free(name);
1164
0
    return -1;
1165
0
  }
1166
1167
0
  remove_quotes_in_str(value);
1168
1169
0
  ret = setenv(name, value);
1170
0
  free(name);
1171
1172
0
  return ret;
1173
0
}
1174
1175
1176
1177
static int is_assignment(const char *s)
1178
0
{
1179
0
  if (s == NULL)
1180
0
    return 0;
1181
1182
0
  if (!isalpha(*s))
1183
0
    return 0;
1184
1185
0
  ++s;
1186
1187
0
  while(isalnum(*s) || *s=='_' || *s=='.')
1188
0
    ++s;
1189
1190
0
  return *s=='=';
1191
0
}
1192
1193
1194
static struct pipe *new_pipe(struct p_context *ctx)
1195
0
{
1196
0
  return xtalloc_zero_size(ctx->scope, sizeof(struct pipe));
1197
0
}
1198
1199
static void initialize_context(struct p_context *ctx, bool newscope)
1200
0
{
1201
0
  if (newscope)
1202
0
    ctx->scope = talloc_new(NULL);
1203
0
  ctx->pipe = NULL;
1204
0
  ctx->child = NULL;
1205
0
  ctx->list_head = new_pipe(ctx);
1206
0
  ctx->pipe = ctx->list_head;
1207
0
  ctx->w = RES_NONE;
1208
0
  ctx->stack = NULL;
1209
0
  ctx->old_flag = 0;
1210
0
  ctx->options_parsed = 0;
1211
0
  INIT_LIST_HEAD(&ctx->options);
1212
0
  done_command(ctx);   /* creates the memory for working child */
1213
0
}
1214
1215
static void release_context(struct p_context *ctx)
1216
0
{
1217
0
#ifdef CONFIG_CMD_GETOPT
1218
0
  struct option *opt, *tmp;
1219
1220
0
  list_for_each_entry_safe(opt, tmp, &ctx->options, list) {
1221
0
    free(opt->optarg);
1222
0
    free(opt);
1223
0
  }
1224
0
#endif
1225
0
  talloc_free((void *)ctx->scope);
1226
0
}
1227
1228
/* normal return is 0
1229
 * if a reserved word is found, and processed, return 1
1230
 * should handle if, then, elif, else, fi, for, while, until, do, done.
1231
 * case, function, and select are obnoxious, save those for later.
1232
 */
1233
struct reserved_combo {
1234
  char *literal;
1235
  int code;
1236
  long flag;
1237
};
1238
/* Mostly a list of accepted follow-up reserved words.
1239
 * FLAG_END means we are done with the sequence, and are ready
1240
 * to turn the compound list into a command.
1241
 * FLAG_START means the word must start a new compound list.
1242
 */
1243
static struct reserved_combo reserved_list[] = {
1244
  { "if",    RES_IF,    FLAG_THEN | FLAG_START },
1245
  { "then",  RES_THEN,  FLAG_ELIF | FLAG_ELSE | FLAG_FI },
1246
  { "elif",  RES_ELIF,  FLAG_THEN },
1247
  { "else",  RES_ELSE,  FLAG_FI   },
1248
  { "fi",    RES_FI,    FLAG_END  },
1249
  { "for",   RES_FOR,   FLAG_IN   | FLAG_START },
1250
  { "while", RES_WHILE, FLAG_DO   | FLAG_START },
1251
  { "until", RES_UNTIL, FLAG_DO   | FLAG_START },
1252
  { "in",    RES_IN,    FLAG_DO   },
1253
  { "do",    RES_DO,    FLAG_DONE },
1254
  { "done",  RES_DONE,  FLAG_END  }
1255
};
1256
1257
static int reserved_word(o_string *dest, struct p_context *ctx)
1258
0
{
1259
0
  struct reserved_combo *r;
1260
0
  int i;
1261
1262
0
  for (i = 0; i < ARRAY_SIZE(reserved_list); i++) {
1263
0
    r = &reserved_list[i];
1264
1265
0
    if (strcmp(dest->data, r->literal))
1266
0
      continue;
1267
1268
0
    hush_debug("found reserved word %s, code %d\n",r->literal,r->code);
1269
1270
0
    if (r->flag & FLAG_START) {
1271
0
      struct p_context *new = xmalloc(sizeof(struct p_context));
1272
1273
0
      hush_debug("push stack\n");
1274
1275
0
      if (ctx->w == RES_IN || ctx->w == RES_FOR) {
1276
0
        syntax();
1277
0
        free(new);
1278
0
        ctx->w = RES_SNTX;
1279
0
        b_reset(dest);
1280
1281
0
        return 1;
1282
0
      }
1283
0
      *new = *ctx;   /* physical copy */
1284
0
      initialize_context(ctx, false);
1285
0
      ctx->stack = new;
1286
0
    } else if (ctx->w == RES_NONE || !(ctx->old_flag & (1 << r->code))) {
1287
0
      syntax_unexpected_token(r->literal);
1288
0
      ctx->w = RES_SNTX;
1289
0
      b_reset(dest);
1290
0
      return 1;
1291
0
    }
1292
1293
0
    ctx->w = r->code;
1294
0
    ctx->old_flag = r->flag;
1295
1296
0
    if (ctx->old_flag & FLAG_END) {
1297
0
      struct p_context *old;
1298
1299
0
      hush_debug("pop stack\n");
1300
1301
0
      done_pipe(ctx,PIPE_SEQ);
1302
0
      old = ctx->stack;
1303
0
      old->child->group = ctx->list_head;
1304
0
      *ctx = *old;   /* physical copy */
1305
0
      free(old);
1306
0
    }
1307
1308
0
    b_reset(dest);
1309
1310
0
    return 1;
1311
0
  }
1312
1313
0
  return 0;
1314
0
}
1315
1316
/* normal return is 0.
1317
 * Syntax or xglob errors return 1. */
1318
static int done_word(o_string *dest, struct p_context *ctx)
1319
0
{
1320
0
  struct child_prog *child = ctx->child;
1321
0
  glob_t *glob_target;
1322
0
  int gr, flags = GLOB_NOCHECK;
1323
1324
0
  hush_debug("%s: %s %p\n", __func__, dest->data, child);
1325
0
  if (dest->length == 0 && !dest->nonnull) {
1326
0
    hush_debug("  true null, ignored\n");
1327
0
    return 0;
1328
0
  }
1329
0
  if (child->group) {
1330
0
    syntax();
1331
0
    return 1;  /* syntax error, groups and arglists don't mix */
1332
0
  }
1333
0
  if (!child->argv && (ctx->type & FLAG_PARSE_SEMICOLON)) {
1334
0
    hush_debug("checking %s for reserved-ness\n",dest->data);
1335
0
    if (reserved_word(dest,ctx))
1336
0
      return ctx->w == RES_SNTX;
1337
0
  }
1338
1339
0
  glob_target = &child->glob_result;
1340
0
  if (child->argv)
1341
0
    flags |= GLOB_APPEND;
1342
1343
0
  gr = xglob(dest, flags, glob_target, ctx->w == RES_IN ? 1 : 0);
1344
0
  if (gr)
1345
0
    return 1;
1346
1347
0
  b_reset(dest);
1348
1349
0
  child->argv = glob_target->gl_pathv;
1350
0
  child->argc = glob_target->gl_pathc;
1351
1352
0
  if (ctx->w == RES_FOR) {
1353
0
    done_word(dest,ctx);
1354
0
    done_pipe(ctx,PIPE_SEQ);
1355
0
  }
1356
1357
0
  return 0;
1358
0
}
1359
1360
/* The only possible error here is out of memory, in which case
1361
 * xmalloc exits. */
1362
static int done_command(struct p_context *ctx)
1363
0
{
1364
  /* The child is really already in the pipe structure, so
1365
   * advance the pipe counter and make a new, null child.
1366
   * Only real trickiness here is that the uncommitted
1367
   * child structure, to which ctx->child points, is not
1368
   * counted in pi->num_progs. */
1369
0
  struct pipe *pi = ctx->pipe;
1370
0
  struct child_prog *prog = ctx->child;
1371
1372
0
  if (prog && prog->group == NULL && prog->argv == NULL) {
1373
0
    hush_debug("%s: skipping null command\n", __func__);
1374
0
    return 0;
1375
0
  } else if (prog) {
1376
0
    pi->num_progs++;
1377
0
    hush_debug("%s: num_progs incremented to %d\n", __func__, pi->num_progs);
1378
0
  } else {
1379
0
    hush_debug("%s: initializing\n", __func__);
1380
0
  }
1381
0
  pi->progs = talloc_realloc_size(ctx->scope, pi->progs,
1382
0
          sizeof(*pi->progs) * (pi->num_progs + 1));
1383
0
  if (!pi->progs)
1384
0
    panic("enomem");
1385
1386
0
  prog = pi->progs + pi->num_progs;
1387
0
  prog->glob_result.gl_pathv = NULL;
1388
1389
0
  prog->argv = NULL;
1390
0
  prog->group = NULL;
1391
0
  prog->sp = 0;
1392
0
  ctx->child = prog;
1393
0
  prog->type = ctx->type;
1394
1395
  /* but ctx->pipe and ctx->list_head remain unchanged */
1396
0
  return 0;
1397
0
}
1398
1399
static int done_pipe(struct p_context *ctx, pipe_style type)
1400
0
{
1401
0
  struct pipe *new_p;
1402
1403
0
  done_command(ctx);  /* implicit closure of previous command */
1404
1405
0
  hush_debug("%s: type %d\n", __func__, type);
1406
1407
0
  ctx->pipe->followup = type;
1408
0
  ctx->pipe->r_mode = ctx->w;
1409
1410
0
  new_p = new_pipe(ctx);
1411
1412
0
  ctx->pipe->next = new_p;
1413
0
  ctx->pipe = new_p;
1414
0
  ctx->child = NULL;
1415
1416
0
  done_command(ctx);  /* set up new pipe to accept commands */
1417
1418
0
  return 0;
1419
0
}
1420
1421
1422
/* basically useful version until someone wants to get fancier,
1423
 * see the bash man page under "Parameter Expansion" */
1424
static const char *lookup_param(char *src)
1425
0
{
1426
0
  if (!src)
1427
0
    return NULL;
1428
1429
0
  if (*src == '$')
1430
0
    return get_dollar_var(src[1]);
1431
1432
0
  return getenv(src);
1433
0
}
1434
1435
static int parse_string(o_string *dest, struct p_context *ctx, const char *src)
1436
0
{
1437
0
  struct in_str foo;
1438
1439
0
  setup_string_in_str(&foo, src);
1440
1441
0
  return parse_stream(dest, ctx, &foo, '\0');
1442
0
}
1443
1444
static char *get_dollar_var(char ch)
1445
0
{
1446
0
  static char buf[40];
1447
1448
0
  buf[0] = '\0';
1449
1450
0
  switch (ch) {
1451
0
    case '?':
1452
0
      sprintf(buf, "%u", (unsigned int)last_return_code);
1453
0
      break;
1454
0
    default:
1455
0
      return NULL;
1456
0
  }
1457
0
  return buf;
1458
0
}
1459
1460
/* return code: 0 for OK, 1 for syntax error */
1461
static int handle_dollar(o_string *dest, struct p_context *ctx, struct in_str *input)
1462
0
{
1463
0
  int advance = 0, i;
1464
0
  int ch = input->peek(input);  /* first character after the $ */
1465
1466
0
  hush_debug("%s: ch=%c\n", __func__, ch);
1467
1468
0
  if (isalpha(ch)) {
1469
0
    b_addchr(dest, SPECIAL_VAR_SYMBOL);
1470
0
    ctx->child->sp++;
1471
1472
0
    while (ch = b_peek(input),isalnum(ch) || ch == '_' || ch == '.') {
1473
0
      b_getch(input);
1474
0
      b_addchr(dest,ch);
1475
0
    }
1476
1477
0
    b_addchr(dest, SPECIAL_VAR_SYMBOL);
1478
1479
0
  } else if (isdigit(ch)) {
1480
1481
0
    i = ch - '0'; /* XXX is $0 special? */
1482
0
    if (i < ctx->global_argc) {
1483
0
      parse_string(dest, ctx, ctx->global_argv[i]);        /* recursion */
1484
0
    }
1485
0
    advance = 1;
1486
0
  } else {
1487
0
    switch (ch) {
1488
0
    case '?':
1489
0
      ctx->child->sp++;
1490
0
      b_addchr(dest, SPECIAL_VAR_SYMBOL);
1491
0
      b_addchr(dest, '$');
1492
0
      b_addchr(dest, '?');
1493
0
      b_addchr(dest, SPECIAL_VAR_SYMBOL);
1494
0
      advance = 1;
1495
0
      break;
1496
0
    case '#':
1497
0
      b_adduint(dest,ctx->global_argc ? ctx->global_argc-1 : 0);
1498
0
      advance = 1;
1499
0
      break;
1500
0
    case '{':
1501
0
      b_addchr(dest, SPECIAL_VAR_SYMBOL);
1502
0
      ctx->child->sp++;
1503
0
      b_getch(input);
1504
1505
      /* XXX maybe someone will try to escape the '}' */
1506
1507
0
      while(ch = b_getch(input),ch != EOF && ch != '}') {
1508
0
        b_addchr(dest,ch);
1509
0
      }
1510
0
      if (ch != '}') {
1511
0
        syntax();
1512
0
        return 1;
1513
0
      }
1514
0
      b_addchr(dest, SPECIAL_VAR_SYMBOL);
1515
0
      break;
1516
0
    case '*':
1517
0
      for (i = 1; i < ctx->global_argc; i++) {
1518
0
        b_addstr(dest, ctx->global_argv[i]);
1519
0
        b_addchr(dest, ' ');
1520
0
      }
1521
1522
0
      advance = 1;
1523
0
      break;
1524
0
    default:
1525
0
      b_addchr(dest, '$');
1526
0
    }
1527
0
  }
1528
  /* Eat the character if the flag was set.  If the compiler
1529
   * is smart enough, we could substitute "b_getch(input);"
1530
   * for all the "advance = 1;" above, and also end up with
1531
   * a nice size-optimized program.  Hah!  That'll be the day.
1532
   */
1533
0
  if (advance)
1534
0
    b_getch(input);
1535
1536
0
  return 0;
1537
0
}
1538
1539
1540
/* return code is 0 for normal exit, 1 for syntax error */
1541
static int parse_stream(o_string *dest, struct p_context *ctx,
1542
  struct in_str *input, int end_trigger)
1543
0
{
1544
0
  unsigned int ch, m;
1545
0
  int next;
1546
1547
  /* Only double-quote state is handled in the state variable dest->quote.
1548
   * A single-quote triggers a bypass of the main loop until its mate is
1549
   * found.  When recursing, quote state is passed in via dest->quote. */
1550
1551
0
  hush_debug("%s: end_trigger=%d\n", __func__, end_trigger);
1552
1553
0
  while ((ch = b_getch(input)) != EOF) {
1554
0
    m = map[ch];
1555
0
    if (input->interrupt)
1556
0
      return 1;
1557
0
    next = (ch == '\n') ? 0 : b_peek(input);
1558
1559
0
    hush_debug("%s: ch=%c (%d) m=%d quote=%d - %c\n",
1560
0
        __func__,
1561
0
        ch >= ' ' ? ch : '.', ch, m,
1562
0
        dest->quote, ctx->stack == NULL ? '*' : '.');
1563
1564
0
    if (m == 0 || ((m == 1 || m == 2) && dest->quote)) {
1565
0
      b_addchr(dest, ch);
1566
0
      continue;
1567
0
    }
1568
1569
0
    if (m == 2) {  /* unquoted IFS */
1570
0
      if (done_word(dest, ctx)) {
1571
0
        return 1;
1572
0
      }
1573
      /* If we aren't performing a substitution, treat a newline as a
1574
       * command separator.  */
1575
0
      if (end_trigger != '\0' && ch == '\n')
1576
0
        done_pipe(ctx, PIPE_SEQ);
1577
0
    }
1578
1579
0
    if (ch == end_trigger && !dest->quote && ctx->w==RES_NONE) {
1580
0
      hush_debug("%s: leaving (triggered)\n", __func__);
1581
0
      return 0;
1582
0
    }
1583
1584
0
    if (m == 2)
1585
0
      continue;
1586
1587
0
    switch (ch) {
1588
0
    case '#':
1589
0
      if (dest->length == 0 && !dest->quote) {
1590
0
        while (ch = b_peek(input), ch != EOF && ch!='\n') {
1591
0
          b_getch(input);
1592
0
        }
1593
0
      } else {
1594
0
        b_addchr(dest, ch);
1595
0
      }
1596
0
      break;
1597
0
    case '\\':
1598
0
      if (next == EOF) {
1599
0
        syntax();
1600
0
        return 1;
1601
0
      }
1602
0
      b_addchr(dest, '\\');
1603
0
      b_addchr(dest, b_getch(input));
1604
0
      break;
1605
0
    case '$':
1606
0
      if (handle_dollar(dest, ctx, input)!=0)
1607
0
        return 1;
1608
0
      break;
1609
0
    case '\'':
1610
0
      dest->nonnull = 1;
1611
0
      b_addchr(dest, '\'');
1612
0
      while (ch = b_getch(input), ch != EOF && ch != '\'') {
1613
0
        if (input->interrupt)
1614
0
          return 1;
1615
0
        b_addchr(dest,ch);
1616
0
      }
1617
0
      b_addchr(dest, '\'');
1618
0
      if (ch == EOF) {
1619
0
        syntax();
1620
0
        return 1;
1621
0
      }
1622
0
      break;
1623
0
    case '"':
1624
0
      dest->nonnull = 1;
1625
0
      b_addchr(dest, '"');
1626
0
      dest->quote = !dest->quote;
1627
0
      break;
1628
0
    case ';':
1629
0
      done_word(dest, ctx);
1630
0
      done_pipe(ctx, PIPE_SEQ);
1631
0
      break;
1632
0
    case '&':
1633
0
      done_word(dest, ctx);
1634
0
      if (next == '&') {
1635
0
        b_getch(input);
1636
0
        done_pipe(ctx, PIPE_AND);
1637
0
      } else {
1638
0
        syntax();
1639
0
        return 1;
1640
0
      }
1641
0
      break;
1642
0
    case '|':
1643
0
      done_word(dest, ctx);
1644
0
      if (next == '|') {
1645
0
        b_getch(input);
1646
0
        done_pipe(ctx, PIPE_OR);
1647
0
      } else {
1648
        /* we could pick up a file descriptor choice here
1649
         * with redirect_opt_num(), but bash doesn't do it.
1650
         * "echo foo 2| cat" yields "foo 2". */
1651
0
        syntax();
1652
0
        return 1;
1653
0
      }
1654
0
      break;
1655
0
    default:
1656
0
      syntax();   /* this is really an internal logic error */
1657
0
      return 1;
1658
0
    }
1659
0
  }
1660
1661
  /* complain if quote?  No, maybe we just finished a command substitution
1662
   * that was quoted.  Example:
1663
   * $ echo "`cat foo` plus more"
1664
   * and we just got the EOF generated by the subshell that ran "cat foo"
1665
   * The only real complaint is if we got an EOF when end_trigger != '\0',
1666
   * that is, we were really supposed to get end_trigger, and never got
1667
   * one before the EOF.  Can't use the standard "syntax error" return code,
1668
   * so that parse_stream_outer can distinguish the EOF and exit smoothly. */
1669
0
  hush_debug("%s: leaving (EOF)\n", __func__);
1670
1671
0
  if (end_trigger != '\0')
1672
0
    return -1;
1673
0
  return 0;
1674
0
}
1675
1676
static void mapset(const unsigned char *set, int code)
1677
0
{
1678
0
  const unsigned char *s;
1679
1680
0
  for (s = set; *s; s++)
1681
0
    map[*s] = code;
1682
0
}
1683
1684
static void update_ifs_map(void)
1685
0
{
1686
  /* char *ifs and char map[256] are both globals. */
1687
0
  ifs = (uchar *)getenv("IFS");
1688
0
  ifs = NULL;
1689
0
  if (ifs == NULL)
1690
0
    ifs = (uchar *)" \t\n";
1691
1692
  /* Precompute a list of 'flow through' behavior so it can be treated
1693
   * quickly up front.  Computation is necessary because of IFS.
1694
   * Special case handling of IFS == " \t\n" is not implemented.
1695
   * The map[] array only really needs two bits each, and on most machines
1696
   * that would be faster because of the reduced L1 cache footprint.
1697
   */
1698
0
  memset(map, 0, sizeof(map));  /* most characters flow through always */
1699
0
  mapset((uchar *)"\\$'\"", 3); /* never flow through */
1700
0
  mapset((uchar *)";&|#", 1); /* flow through if quoted */
1701
0
  mapset(ifs, 2);     /* also flow through if quoted */
1702
0
}
1703
1704
/*
1705
 * shell_expand - Expand shell variables in a string.
1706
 * @str:  The input string containing shell variables like
1707
 *    $var or ${var}
1708
 * Return:  The expanded string. Must be freed with free().
1709
 */
1710
char *shell_expand(char *str)
1711
0
{
1712
0
  struct p_context ctx = {};
1713
0
  o_string o = {};
1714
0
  char *res, *parsed;
1715
1716
0
  if (!IS_ALLOWED(SCONFIG_SHELL))
1717
0
    return str;
1718
1719
0
  remove_quotes_in_str(str);
1720
1721
0
  o.quote = 1;
1722
1723
0
  initialize_context(&ctx, false);
1724
1725
0
  parse_string(&o, &ctx, str);
1726
1727
0
  parsed = xmemdup(o.data, o.length + 1);
1728
0
  parsed[o.length] = 0;
1729
1730
0
  res = insert_var_value(parsed);
1731
0
  if (res != parsed)
1732
0
    free(parsed);
1733
1734
0
  free_pipe_list(ctx.list_head, 0);
1735
0
  b_free(&o);
1736
1737
0
  return res;
1738
0
}
1739
1740
/* most recursion does not come through here, the exception is
1741
 * from builtin_source() */
1742
static int parse_stream_outer(struct p_context *ctx, struct in_str *inp, int flag)
1743
0
{
1744
0
  o_string temp = NULL_O_STRING;
1745
0
  int rcode;
1746
0
  int code = 0;
1747
1748
0
  do {
1749
0
    ctx->type = flag;
1750
0
    initialize_context(ctx, false);
1751
0
    update_ifs_map();
1752
1753
0
    if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING))
1754
0
      mapset((uchar *)";$&|", 0);
1755
1756
0
    inp->promptmode = 1;
1757
0
    rcode = parse_stream(&temp, ctx, inp, '\n');
1758
1759
0
    if (rcode != 1 && ctx->old_flag != 0) {
1760
0
      syntax();
1761
0
      return 1;
1762
0
    }
1763
0
    if (rcode != 1 && ctx->old_flag == 0) {
1764
0
      done_word(&temp, ctx);
1765
0
      done_pipe(ctx, PIPE_SEQ);
1766
0
      if (ctx->list_head->num_progs) {
1767
0
        code = run_list(ctx, ctx->list_head);
1768
0
      } else {
1769
0
        free_pipe_list(ctx->list_head, 0);
1770
0
        continue;
1771
0
      }
1772
0
      if (code < -1) { /* exit */
1773
0
        b_free(&temp);
1774
0
        return code;
1775
0
      }
1776
0
    } else {
1777
0
      if (ctx->old_flag != 0) {
1778
0
        free(ctx->stack);
1779
0
        b_reset(&temp);
1780
0
      }
1781
0
      if (inp->interrupt)
1782
0
        printf("<INTERRUPT>\n");
1783
0
      temp.nonnull = 0;
1784
0
      temp.quote = 0;
1785
0
      free_pipe_list(ctx->list_head,0);
1786
0
      b_free(&temp);
1787
0
      return 1;
1788
0
    }
1789
0
    b_free(&temp);
1790
0
  } while (!ctrlc() && rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP));   /* loop on syntax errors, return on EOF */
1791
1792
0
  return code;
1793
0
}
1794
1795
static int parse_string_outer(struct p_context *ctx, const char *s, int flag)
1796
0
{
1797
0
  struct in_str input;
1798
0
  char *p;
1799
0
  const char *cp;
1800
0
  int rcode;
1801
1802
0
  if ( !s || !*s)
1803
0
    return 1;
1804
1805
0
  cp = strchr(s, '\n');
1806
0
  if (!cp || *++cp) {
1807
0
    p = xmalloc(strlen(s) + 2);
1808
0
    strcpy(p, s);
1809
0
    strcat(p, "\n");
1810
0
    setup_string_in_str(&input, p);
1811
0
    rcode = parse_stream_outer(ctx, &input, flag);
1812
0
    free(p);
1813
0
  } else {
1814
0
    setup_string_in_str(&input, s);
1815
0
    rcode = parse_stream_outer(ctx, &input, flag);
1816
0
  }
1817
1818
0
  return rcode;
1819
0
}
1820
1821
static char *insert_var_value(char *inp)
1822
0
{
1823
0
  int res_str_len = 0;
1824
0
  int len;
1825
0
  int done = 0;
1826
0
  char *p, *res_str = NULL;
1827
0
  const char *p1;
1828
1829
0
  while ((p = strchr(inp, SPECIAL_VAR_SYMBOL))) {
1830
0
    if (p != inp) {
1831
0
      len = p - inp;
1832
0
      res_str = xrealloc(res_str, (res_str_len + len));
1833
0
      strncpy((res_str + res_str_len), inp, len);
1834
0
      res_str_len += len;
1835
0
    }
1836
0
    inp = ++p;
1837
0
    p = strchr(inp, SPECIAL_VAR_SYMBOL);
1838
0
    *p = '\0';
1839
0
    if ((p1 = lookup_param(inp))) {
1840
0
      len = res_str_len + strlen(p1);
1841
0
      res_str = xrealloc(res_str, (1 + len));
1842
0
      strcpy((res_str + res_str_len), p1);
1843
0
      res_str_len = len;
1844
0
    }
1845
0
    *p = SPECIAL_VAR_SYMBOL;
1846
0
    inp = ++p;
1847
0
    done = 1;
1848
0
  }
1849
0
  if (done) {
1850
0
    res_str = xrealloc(res_str, (1 + res_str_len + strlen(inp)));
1851
0
    strcpy((res_str + res_str_len), inp);
1852
0
    while ((p = strchr(res_str, '\n'))) {
1853
0
      *p = ' ';
1854
0
    }
1855
0
  }
1856
0
  return (res_str == NULL) ? inp : res_str;
1857
0
}
1858
1859
static char **make_list_in(char **inp, char *name)
1860
0
{
1861
0
  int len, i;
1862
0
  int name_len = strlen(name);
1863
0
  int n = 0;
1864
0
  char **list;
1865
0
  char *p1, *p2, *p3;
1866
1867
  /* create list of variable values */
1868
0
  list = xmalloc(sizeof(*list));
1869
0
  for (i = 0; inp[i]; i++) {
1870
0
    p3 = insert_var_value(inp[i]);
1871
0
    p1 = p3;
1872
0
    while (*p1) {
1873
0
      if (*p1 == ' ') {
1874
0
        p1++;
1875
0
        continue;
1876
0
      }
1877
0
      if ((p2 = strchr(p1, ' '))) {
1878
0
        len = p2 - p1;
1879
0
      } else {
1880
0
        len = strlen(p1);
1881
0
        p2 = p1 + len;
1882
0
      }
1883
      /* we use n + 2 in realloc for list,because we add
1884
       * new element and then we will add NULL element */
1885
0
      list = xrealloc(list, sizeof(*list) * (n + 2));
1886
0
      list[n] = xmalloc(2 + name_len + len);
1887
0
      strcpy(list[n], name);
1888
0
      strcat(list[n], "=");
1889
0
      strncat(list[n], p1, len);
1890
0
      list[n++][name_len + len + 1] = '\0';
1891
0
      p1 = p2;
1892
0
    }
1893
0
    if (p3 != inp[i])
1894
0
      free(p3);
1895
0
  }
1896
0
  list[n] = NULL;
1897
0
  return list;
1898
0
}
1899
1900
/* Make new string for parser */
1901
static char * make_string(char ** inp)
1902
0
{
1903
0
  char *p;
1904
0
  char *str = NULL;
1905
0
  int n;
1906
0
  int len = 2;
1907
1908
0
  for (n = 0; inp[n]; n++) {
1909
0
    p = insert_var_value(inp[n]);
1910
0
    str = xrealloc(str, (len + strlen(p)));
1911
0
    if (n) {
1912
0
      strcat(str, " ");
1913
0
    } else {
1914
0
      *str = '\0';
1915
0
    }
1916
0
    strcat(str, p);
1917
0
    len = strlen(str) + 3;
1918
0
    if (p != inp[n])
1919
0
      free(p);
1920
0
  }
1921
1922
0
  if (!str)
1923
0
    str = xzalloc(len);
1924
1925
0
  len = strlen(str);
1926
0
  *(str + len) = '\n';
1927
0
  *(str + len + 1) = '\0';
1928
0
  return str;
1929
0
}
1930
1931
static int __run_command(const char *cmd)
1932
0
{
1933
0
  struct p_context ctx = {};
1934
0
  int ret;
1935
1936
0
  if (!IS_ALLOWED(SCONFIG_SHELL))
1937
0
    return -EPERM;
1938
1939
0
  initialize_context(&ctx, true);
1940
1941
0
  ret = parse_string_outer(&ctx, cmd, FLAG_PARSE_SEMICOLON);
1942
0
  release_context(&ctx);
1943
1944
0
  return ret;
1945
0
}
1946
1947
int run_command(const char *fmt, ...)
1948
0
{
1949
0
  va_list vargs;
1950
0
  char *cmd;
1951
0
  int error;
1952
1953
0
  va_start(vargs, fmt);
1954
0
  cmd = xvasprintf(fmt, vargs);
1955
0
  va_end(vargs);
1956
1957
0
  error = __run_command(cmd);
1958
1959
0
  free(cmd);
1960
1961
0
  return error;
1962
0
}
1963
1964
static int execute_script(const char *path, int argc, char *argv[])
1965
0
{
1966
0
  int ret;
1967
1968
0
  if (!IS_ALLOWED(SCONFIG_SHELL))
1969
0
    return -EPERM;
1970
1971
0
  env_push_context();
1972
0
  ret = source_script(path, argc, argv);
1973
0
  env_pop_context();
1974
1975
0
  return ret;
1976
0
}
1977
1978
static int source_script(const char *path, int argc, char *argv[])
1979
0
{
1980
0
  struct p_context ctx = {};
1981
0
  char *script;
1982
0
  int ret;
1983
1984
0
  initialize_context(&ctx, true);
1985
1986
0
  ctx.global_argc = argc;
1987
0
  ctx.global_argv = argv;
1988
1989
0
  script = read_file(path, NULL);
1990
0
  if (!script) {
1991
0
    perror("sh");
1992
0
    return 1;
1993
0
  }
1994
1995
0
  ret = parse_string_outer(&ctx, script, FLAG_PARSE_SEMICOLON);
1996
0
  if (ret < -1)
1997
0
    ret = -ret - 2;
1998
1999
0
  release_context(&ctx);
2000
0
  free(script);
2001
2002
0
  return ret;
2003
0
}
2004
2005
int run_shell(void)
2006
0
{
2007
0
  int rcode;
2008
0
  struct in_str input;
2009
0
  struct p_context ctx = {};
2010
0
  int exit = 0;
2011
2012
0
  if (!IS_ALLOWED(SCONFIG_SHELL_INTERACTIVE))
2013
0
    return -EPERM;
2014
2015
0
  login();
2016
2017
0
  do {
2018
0
    ctrlc_handled();
2019
0
    setup_file_in_str(&input);
2020
0
    rcode = parse_stream_outer(&ctx, &input, FLAG_PARSE_SEMICOLON);
2021
0
    if (rcode < -1) {
2022
0
      exit = 1;
2023
0
      rcode = -rcode - 2;
2024
0
    }
2025
0
    release_context(&ctx);
2026
0
  } while (!exit);
2027
2028
0
  return rcode;
2029
0
}
2030
2031
static int do_sh(int argc, char *argv[])
2032
0
{
2033
0
  if (argc < 2)
2034
0
    return run_shell();
2035
2036
0
  return execute_script(argv[1], argc - 1, argv + 1);
2037
0
}
2038
2039
BAREBOX_CMD_START(sh)
2040
  .cmd    = do_sh,
2041
  BAREBOX_CMD_DESC("execute a shell script")
2042
  BAREBOX_CMD_OPTS("FILE [ARGUMENT...]")
2043
  BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
2044
BAREBOX_CMD_END
2045
2046
static int do_source(int argc, char *argv[])
2047
0
{
2048
0
  char *path;
2049
0
  int ret;
2050
2051
0
  if (argc < 2)
2052
0
    return COMMAND_ERROR_USAGE;
2053
2054
0
  if (strchr(argv[1], '/')) {
2055
0
    path = xstrdup(argv[1]);
2056
0
  } else {
2057
0
    path = find_execable(argv[1]);
2058
0
    if (!path)
2059
0
      return 1;
2060
0
  }
2061
2062
0
  ret = source_script(path, argc - 1, argv + 1);
2063
2064
0
  free(path);
2065
2066
0
  return ret;
2067
0
}
2068
2069
static const char * const source_aliases[] = { ".", NULL};
2070
2071
BAREBOX_CMD_HELP_START(source)
2072
BAREBOX_CMD_HELP_TEXT("Read and execute commands from FILE in the current shell environment.")
2073
BAREBOX_CMD_HELP_TEXT("and return the exit status of the last command executed.")
2074
BAREBOX_CMD_HELP_END
2075
2076
BAREBOX_CMD_START(source)
2077
  .aliases  = source_aliases,
2078
  .cmd    = do_source,
2079
  BAREBOX_CMD_DESC("execute shell script in current shell environment")
2080
  BAREBOX_CMD_OPTS("FILE [ARGUMENT...]")
2081
  BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
2082
  BAREBOX_CMD_HELP(cmd_source_help)
2083
BAREBOX_CMD_END
2084
2085
static int do_dummy_command(int argc, char *argv[])
2086
0
{
2087
  /*
2088
   * This function is never reached. These commands are only here to
2089
   * provide help texts for the builtins.
2090
   */
2091
0
  return 0;
2092
0
}
2093
2094
BAREBOX_CMD_HELP_START(exit)
2095
BAREBOX_CMD_HELP_TEXT("Exit script with status ERRLVL. If ERRLVL is omitted, the exit status is")
2096
BAREBOX_CMD_HELP_TEXT("that of the last command executed")
2097
BAREBOX_CMD_HELP_END
2098
2099
BAREBOX_CMD_START(exit)
2100
  .cmd    = do_dummy_command,
2101
  BAREBOX_CMD_DESC("exit script")
2102
  BAREBOX_CMD_OPTS("[ERRLVL]")
2103
  BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
2104
  BAREBOX_CMD_HELP(cmd_exit_help)
2105
BAREBOX_CMD_END
2106
2107
#ifdef CONFIG_CMD_GETOPT
2108
BAREBOX_CMD_HELP_START(getopt)
2109
BAREBOX_CMD_HELP_TEXT("OPTSTRING contains the option letters. Add a colon to an option if this")
2110
BAREBOX_CMD_HELP_TEXT("option has a required argument or two colons for an optional argument. The")
2111
BAREBOX_CMD_HELP_TEXT("current option is saved in VAR, arguments are saved in $OPTARG. Any")
2112
BAREBOX_CMD_HELP_TEXT("non-option arguments can be accessed starting from $1.")
2113
BAREBOX_CMD_HELP_END
2114
2115
BAREBOX_CMD_START(getopt)
2116
  .cmd    = do_dummy_command,
2117
  BAREBOX_CMD_DESC("parse option arguments")
2118
  BAREBOX_CMD_OPTS("OPTSTRING VAR")
2119
  BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
2120
  BAREBOX_CMD_HELP(cmd_getopt_help)
2121
BAREBOX_CMD_END
2122
#endif
2123
2124
BAREBOX_MAGICVAR(PATH, "colon separated list of paths to search for executables");
2125
#ifdef CONFIG_HUSH_FANCY_PROMPT
2126
BAREBOX_MAGICVAR(PS1, "hush prompt");
2127
BAREBOX_MAGICVAR(PROMPT_COMMAND, "command to execute prior to each primary prompt");
2128
#endif
2129
2130
static int binfmt_sh_excute(struct binfmt_hook *b, char *file, int argc, char **argv)
2131
0
{
2132
0
  return execute_script(file, argc, argv);
2133
0
}
2134
2135
static struct binfmt_hook binfmt_sh_hook = {
2136
  .type = filetype_sh,
2137
  .hook = binfmt_sh_excute,
2138
};
2139
2140
static int binfmt_sh_init(void)
2141
26
{
2142
26
  return binfmt_register(&binfmt_sh_hook);
2143
26
}
2144
fs_initcall(binfmt_sh_init);
2145
2146
/**
2147
 * @file
2148
 * @brief A prototype Bourne shell grammar parser
2149
 */
2150
2151
/** @page sh_command Starting shell
2152
 *
2153
 * Usage: sh \<filename\> [\<arguments\>]
2154
 *
2155
 * Execute a shell script named \<filename\> and forward (if given)
2156
 * \<arguments\> to it.
2157
 *
2158
 * Usage: .  \<filename\> [\<arguments\>]
2159
 * or     source \<filename\> [\<arguments\>]
2160
 *
2161
 * Read and execute commands from \<filename\> in the current shell environment,
2162
 * forward (if given) \<arguments\> to it and return the exit status of the last
2163
 * command  executed from filename.
2164
 */