hush: fix double-free in "echo TEST &"
[oweals/busybox.git] / shell / lash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * lash -- the BusyBox Lame-Ass SHell
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
8  * under the following liberal license: "We have placed this source code in the
9  * public domain. Use it in any project, free or commercial."
10  *
11  * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
12  */
13
14 /* This shell's parsing engine is officially at a dead-end.  Future
15  * work shell work should be done using hush, msh, or ash.  This is
16  * still a very useful, small shell -- it just don't need any more
17  * features beyond what it already has...
18  */
19
20 //For debugging/development on the shell only...
21 //#define DEBUG_SHELL
22
23
24 #include "busybox.h"
25 #include <getopt.h>
26 #include <glob.h>
27 #define expand_t        glob_t
28
29 /* Always enable for the moment... */
30 #define CONFIG_LASH_PIPE_N_REDIRECTS
31 #define CONFIG_LASH_JOB_CONTROL
32 #define ENABLE_LASH_PIPE_N_REDIRECTS 1
33 #define ENABLE_LASH_JOB_CONTROL      1
34
35
36 enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */
37 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
38
39
40 #if ENABLE_LASH_PIPE_N_REDIRECTS
41 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
42         REDIRECT_APPEND
43 };
44 #endif
45
46 enum {
47         DEFAULT_CONTEXT = 0x1,
48         IF_TRUE_CONTEXT = 0x2,
49         IF_FALSE_CONTEXT = 0x4,
50         THEN_EXP_CONTEXT = 0x8,
51         ELSE_EXP_CONTEXT = 0x10
52 };
53
54 #define LASH_OPT_DONE (1)
55 #define LASH_OPT_SAW_QUOTE (2)
56
57 #if ENABLE_LASH_PIPE_N_REDIRECTS
58 struct redir_struct {
59         enum redir_type type;   /* type of redirection */
60         int fd;                                         /* file descriptor being redirected */
61         char *filename;                         /* file to redirect fd to */
62 };
63 #endif
64
65 struct child_prog {
66         pid_t pid;                                      /* 0 if exited */
67         char **argv;                            /* program name and arguments */
68         int num_redirects;                      /* elements in redirection array */
69         int is_stopped;                         /* is the program currently running? */
70         struct job *family;                     /* pointer back to the child's parent job */
71 #if ENABLE_LASH_PIPE_N_REDIRECTS
72         struct redir_struct *redirects; /* I/O redirects */
73 #endif
74 };
75
76 struct jobset {
77         struct job *head;                       /* head of list of running jobs */
78         struct job *fg;                         /* current foreground job */
79 };
80
81 struct job {
82         int jobid;                                      /* job number */
83         int num_progs;                          /* total number of programs in job */
84         int running_progs;                      /* number of programs running */
85         char *text;                                     /* name of job */
86         char *cmdbuf;                           /* buffer various argv's point into */
87         pid_t pgrp;                                     /* process group ID for the job */
88         struct child_prog *progs;       /* array of programs in job */
89         struct job *next;                       /* to track background commands */
90         int stopped_progs;                      /* number of programs alive, but stopped */
91         unsigned int job_context;       /* bitmask defining current context */
92         struct jobset *job_list;
93 };
94
95 struct built_in_command {
96         const char *cmd;   /* name */
97         const char *descr; /* description */
98         int (*function) (struct child_prog *);  /* function ptr */
99 };
100
101 /* function prototypes for builtins */
102 static int builtin_cd(struct child_prog *cmd);
103 static int builtin_exec(struct child_prog *cmd);
104 static int builtin_exit(struct child_prog *cmd);
105 static int builtin_fg_bg(struct child_prog *cmd);
106 static int builtin_help(struct child_prog *cmd);
107 static int builtin_jobs(struct child_prog *dummy);
108 static int builtin_pwd(struct child_prog *dummy);
109 static int builtin_export(struct child_prog *cmd);
110 static int builtin_source(struct child_prog *cmd);
111 static int builtin_unset(struct child_prog *cmd);
112 static int builtin_read(struct child_prog *cmd);
113
114
115 /* function prototypes for shell stuff */
116 static void checkjobs(struct jobset *job_list);
117 static void remove_job(struct jobset *j_list, struct job *job);
118 static int get_command_bufsiz(FILE * source, char *command);
119 static int parse_command(char **command_ptr, struct job *job, int *inbg);
120 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
121 static int pseudo_exec(struct child_prog *cmd) ATTRIBUTE_NORETURN;
122 static int busy_loop(FILE * input);
123
124
125 /* Table of built-in functions (these are non-forking builtins, meaning they
126  * can change global variables in the parent shell process but they will not
127  * work with pipes and redirects; 'unset foo | whatever' will not work) */
128 static const struct built_in_command bltins[] = {
129         {"bg"    , "Resume a job in the background", builtin_fg_bg},
130         {"cd"    , "Change working directory", builtin_cd},
131         {"exec"  , "Exec command, replacing this shell with the exec'd process", builtin_exec},
132         {"exit"  , "Exit from shell()", builtin_exit},
133         {"fg"    , "Bring job into the foreground", builtin_fg_bg},
134         {"jobs"  , "Lists the active jobs", builtin_jobs},
135         {"export", "Set environment variable", builtin_export},
136         {"unset" , "Unset environment variable", builtin_unset},
137         {"read"  , "Input environment variable", builtin_read},
138         {"."     , "Source-in and run commands in a file", builtin_source},
139         /* These were "forked applets", but distinction was nuked */
140         /* Original comment retained: */
141         /* Table of forking built-in functions (things that fork cannot change global
142          * variables in the parent process, such as the current working directory) */
143         {"pwd"   , "Print current directory", builtin_pwd},
144         {"help"  , "List shell built-in commands", builtin_help},
145         /* to do: add ulimit */
146 };
147
148 #define VEC_SIZE(v) (sizeof(v)/sizeof(v[0]))
149 #define VEC_LAST(v) v[VEC_SIZE(v)-1]
150
151
152 static int shell_context;  /* Type prompt trigger (PS1 or PS2) */
153
154
155 /* Globals that are static to this file */
156 static char *cwd;
157 static char *local_pending_command;
158 static struct jobset job_list = { NULL, NULL };
159 static int argc;
160 static char **argv;
161 static llist_t *close_me_list;
162 static int last_return_code;
163 static int last_bg_pid;
164 static unsigned int last_jobid;
165 static int shell_terminal;
166 static const char *PS1;
167 static const char *PS2 = "> ";
168
169
170 #ifdef DEBUG_SHELL
171 static inline void debug_printf(const char *format, ...)
172 {
173         va_list args;
174         va_start(args, format);
175         vfprintf(stderr, format, args);
176         va_end(args);
177 }
178 #else
179 static inline void debug_printf(const char ATTRIBUTE_UNUSED *format, ...) { }
180 #endif
181
182 /*
183         Most builtins need access to the struct child_prog that has
184         their arguments, previously coded as cmd->progs[0].  That coding
185         can exhibit a bug, if the builtin is not the first command in
186         a pipeline: "echo foo | exec sort" will attempt to exec foo.
187
188 builtin   previous use      notes
189 ------ -----------------  ---------
190 cd      cmd->progs[0]
191 exec    cmd->progs[0]  squashed bug: didn't look for applets or forking builtins
192 exit    cmd->progs[0]
193 fg_bg   cmd->progs[0], job_list->head, job_list->fg
194 help    0
195 jobs    job_list->head
196 pwd     0
197 export  cmd->progs[0]
198 source  cmd->progs[0]
199 unset   cmd->progs[0]
200 read    cmd->progs[0]
201
202 I added "struct job *family;" to struct child_prog,
203 and switched API to builtin_foo(struct child_prog *child);
204 So   cmd->text        becomes  child->family->text
205      cmd->job_context  becomes  child->family->job_context
206      cmd->progs[0]    becomes  *child
207      job_list          becomes  child->family->job_list
208  */
209
210
211 static void update_cwd(void)
212 {
213         cwd = xrealloc_getcwd_or_warn(cwd);
214         if (!cwd)
215                 cwd = xstrdup(bb_msg_unknown);
216 }
217
218 /* built-in 'cd <path>' handler */
219 static int builtin_cd(struct child_prog *child)
220 {
221         char *newdir;
222
223         if (child->argv[1] == NULL)
224                 newdir = getenv("HOME");
225         else
226                 newdir = child->argv[1];
227         if (chdir(newdir)) {
228                 bb_perror_msg("cd: %s", newdir);
229                 return EXIT_FAILURE;
230         }
231         update_cwd();
232         return EXIT_SUCCESS;
233 }
234
235 /* built-in 'exec' handler */
236 static int builtin_exec(struct child_prog *child)
237 {
238         if (child->argv[1] == NULL)
239                 return EXIT_SUCCESS;   /* Really? */
240         child->argv++;
241         while (close_me_list)
242                 close((long)llist_pop(&close_me_list));
243         pseudo_exec(child);
244         /* never returns */
245 }
246
247 /* built-in 'exit' handler */
248 static int builtin_exit(struct child_prog *child)
249 {
250         if (child->argv[1] == NULL)
251                 exit(EXIT_SUCCESS);
252
253         exit(atoi(child->argv[1]));
254 }
255
256 /* built-in 'fg' and 'bg' handler */
257 static int builtin_fg_bg(struct child_prog *child)
258 {
259         int i, jobnum;
260         struct job *job;
261
262         /* If they gave us no args, assume they want the last backgrounded task */
263         if (!child->argv[1]) {
264                 for (job = child->family->job_list->head; job; job = job->next) {
265                         if (job->jobid == last_jobid) {
266                                 goto found;
267                         }
268                 }
269                 bb_error_msg("%s: no current job", child->argv[0]);
270                 return EXIT_FAILURE;
271         }
272         if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
273                 bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
274                 return EXIT_FAILURE;
275         }
276         for (job = child->family->job_list->head; job; job = job->next) {
277                 if (job->jobid == jobnum) {
278                         goto found;
279                 }
280         }
281         bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
282         return EXIT_FAILURE;
283  found:
284         if (*child->argv[0] == 'f') {
285                 /* Put the job into the foreground.  */
286                 tcsetpgrp(shell_terminal, job->pgrp);
287
288                 child->family->job_list->fg = job;
289         }
290
291         /* Restart the processes in the job */
292         for (i = 0; i < job->num_progs; i++)
293                 job->progs[i].is_stopped = 0;
294
295         job->stopped_progs = 0;
296
297         i = kill(- job->pgrp, SIGCONT);
298         if (i < 0) {
299                 if (errno == ESRCH) {
300                         remove_job(&job_list, job);
301                 } else {
302                         bb_perror_msg("kill (SIGCONT)");
303                 }
304         }
305
306         return EXIT_SUCCESS;
307 }
308
309 /* built-in 'help' handler */
310 static int builtin_help(struct child_prog ATTRIBUTE_UNUSED *dummy)
311 {
312         const struct built_in_command *x;
313
314         printf("\nBuilt-in commands:\n"
315                "-------------------\n");
316         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
317                 if (x->descr == NULL)
318                         continue;
319                 printf("%s\t%s\n", x->cmd, x->descr);
320         }
321         putchar('\n');
322         return EXIT_SUCCESS;
323 }
324
325 /* built-in 'jobs' handler */
326 static int builtin_jobs(struct child_prog *child)
327 {
328         struct job *job;
329         const char *status_string;
330
331         for (job = child->family->job_list->head; job; job = job->next) {
332                 if (job->running_progs == job->stopped_progs)
333                         status_string = "Stopped";
334                 else
335                         status_string = "Running";
336
337                 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
338         }
339         return EXIT_SUCCESS;
340 }
341
342
343 /* built-in 'pwd' handler */
344 static int builtin_pwd(struct child_prog ATTRIBUTE_UNUSED *dummy)
345 {
346         update_cwd();
347         puts(cwd);
348         return EXIT_SUCCESS;
349 }
350
351 /* built-in 'export VAR=value' handler */
352 static int builtin_export(struct child_prog *child)
353 {
354         int res;
355         char *v = child->argv[1];
356
357         if (v == NULL) {
358                 char **e;
359                 for (e = environ; *e; e++) {
360                         puts(*e);
361                 }
362                 return 0;
363         }
364         res = putenv(v);
365         if (res)
366                 bb_perror_msg("export");
367 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
368         if (strncmp(v, "PS1=", 4) == 0)
369                 PS1 = getenv("PS1");
370 #endif
371
372 #if ENABLE_LOCALE_SUPPORT
373         // TODO: why getenv? "" would be just as good...
374         if (strncmp(v, "LC_ALL=", 7) == 0)
375                 setlocale(LC_ALL, getenv("LC_ALL"));
376         if (strncmp(v, "LC_CTYPE=", 9) == 0)
377                 setlocale(LC_CTYPE, getenv("LC_CTYPE"));
378 #endif
379
380         return res;
381 }
382
383 /* built-in 'read VAR' handler */
384 static int builtin_read(struct child_prog *child)
385 {
386         int res = 0, len;
387         char *s;
388         char string[MAX_READ];
389
390         if (child->argv[1]) {
391                 /* argument (VAR) given: put "VAR=" into buffer */
392                 safe_strncpy(string, child->argv[1], MAX_READ-1);
393                 len = strlen(string);
394                 string[len++] = '=';
395                 string[len]   = '\0';
396                 fgets(&string[len], sizeof(string) - len, stdin);       /* read string */
397                 res = strlen(string);
398                 if (res > len)
399                         string[--res] = '\0';   /* chomp trailing newline */
400                 /*
401                 ** string should now contain "VAR=<value>"
402                 ** copy it (putenv() won't do that, so we must make sure
403                 ** the string resides in a static buffer!)
404                 */
405                 res = -1;
406                 s = strdup(string);
407                 if (s)
408                         res = putenv(s);
409                 if (res)
410                         bb_perror_msg("read");
411         } else
412                 fgets(string, sizeof(string), stdin);
413
414         return res;
415 }
416
417 /* Built-in '.' handler (read-in and execute commands from file) */
418 static int builtin_source(struct child_prog *child)
419 {
420         FILE *input;
421         int status;
422
423         input = fopen_or_warn(child->argv[1], "r");
424         if (!input) {
425                 return EXIT_FAILURE;
426         }
427
428         llist_add_to(&close_me_list, (void *)(long)fileno(input));
429         /* Now run the file */
430         status = busy_loop(input);
431         fclose(input);
432         llist_pop(&close_me_list);
433         return status;
434 }
435
436 /* built-in 'unset VAR' handler */
437 static int builtin_unset(struct child_prog *child)
438 {
439         if (child->argv[1] == NULL) {
440                 printf(bb_msg_requires_arg, "unset");
441                 return EXIT_FAILURE;
442         }
443         unsetenv(child->argv[1]);
444         return EXIT_SUCCESS;
445 }
446
447 #if ENABLE_LASH_JOB_CONTROL
448 /* free up all memory from a job */
449 static void free_job(struct job *cmd)
450 {
451         int i;
452         struct jobset *keep;
453
454         for (i = 0; i < cmd->num_progs; i++) {
455                 free(cmd->progs[i].argv);
456 #if ENABLE_LASH_PIPE_N_REDIRECTS
457                 if (cmd->progs[i].redirects)
458                         free(cmd->progs[i].redirects);
459 #endif
460         }
461         free(cmd->progs);
462         free(cmd->text);
463         free(cmd->cmdbuf);
464         keep = cmd->job_list;
465         memset(cmd, 0, sizeof(struct job));
466         cmd->job_list = keep;
467 }
468
469 /* remove a job from a jobset */
470 static void remove_job(struct jobset *j_list, struct job *job)
471 {
472         struct job *prevjob;
473
474         free_job(job);
475         if (job == j_list->head) {
476                 j_list->head = job->next;
477         } else {
478                 prevjob = j_list->head;
479                 while (prevjob->next != job)
480                         prevjob = prevjob->next;
481                 prevjob->next = job->next;
482         }
483
484         if (j_list->head)
485                 last_jobid = j_list->head->jobid;
486         else
487                 last_jobid = 0;
488
489         free(job);
490 }
491
492 /* Checks to see if any background processes have exited -- if they
493    have, figure out why and see if a job has completed */
494 static void checkjobs(struct jobset *j_list)
495 {
496         struct job *job;
497         pid_t childpid;
498         int status;
499         int prognum = 0;
500
501         while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
502                 for (job = j_list->head; job; job = job->next) {
503                         prognum = 0;
504                         while (prognum < job->num_progs &&
505                                    job->progs[prognum].pid != childpid) prognum++;
506                         if (prognum < job->num_progs)
507                                 break;
508                 }
509
510                 /* This happens on backticked commands */
511                 if (job == NULL)
512                         return;
513
514                 if (WIFEXITED(status) || WIFSIGNALED(status)) {
515                         /* child exited */
516                         job->running_progs--;
517                         job->progs[prognum].pid = 0;
518
519                         if (!job->running_progs) {
520                                 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
521                                 last_jobid = 0;
522                                 remove_job(j_list, job);
523                         }
524                 } else {
525                         /* child stopped */
526                         job->stopped_progs++;
527                         job->progs[prognum].is_stopped = 1;
528                 }
529         }
530
531         if (childpid == -1 && errno != ECHILD)
532                 bb_perror_msg("waitpid");
533 }
534 #else
535 static void checkjobs(struct jobset *j_list)
536 {
537 }
538 static void free_job(struct job *cmd)
539 {
540 }
541 static void remove_job(struct jobset *j_list, struct job *job)
542 {
543 }
544 #endif
545
546 #if ENABLE_LASH_PIPE_N_REDIRECTS
547 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
548  * and stderr if they are redirected. */
549 static int setup_redirects(struct child_prog *prog, int squirrel[])
550 {
551         int i;
552         int openfd;
553         int mode = O_RDONLY;
554         struct redir_struct *redir = prog->redirects;
555
556         for (i = 0; i < prog->num_redirects; i++, redir++) {
557                 switch (redir->type) {
558                 case REDIRECT_INPUT:
559                         mode = O_RDONLY;
560                         break;
561                 case REDIRECT_OVERWRITE:
562                         mode = O_WRONLY | O_CREAT | O_TRUNC;
563                         break;
564                 case REDIRECT_APPEND:
565                         mode = O_WRONLY | O_CREAT | O_APPEND;
566                         break;
567                 }
568
569                 openfd = open3_or_warn(redir->filename, mode, 0666);
570                 if (openfd < 0) {
571                         /* this could get lost if stderr has been redirected, but
572                            bash and ash both lose it as well (though zsh doesn't!) */
573                         return 1;
574                 }
575
576                 if (openfd != redir->fd) {
577                         if (squirrel && redir->fd < 3) {
578                                 squirrel[redir->fd] = dup(redir->fd);
579                                 fcntl(squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
580                         }
581                         dup2(openfd, redir->fd);
582                         close(openfd);
583                 }
584         }
585
586         return 0;
587 }
588
589 static void restore_redirects(int squirrel[])
590 {
591         int i, fd;
592         for (i = 0; i < 3; i++) {
593                 fd = squirrel[i];
594                 if (fd != -1) {
595                         /* No error checking.  I sure wouldn't know what
596                          * to do with an error if I found one! */
597                         dup2(fd, i);
598                         close(fd);
599                 }
600         }
601 }
602 #else
603 static inline int setup_redirects(struct child_prog *prog, int squirrel[])
604 {
605         return 0;
606 }
607 static inline void restore_redirects(int squirrel[])
608 {
609 }
610 #endif
611
612 static inline void cmdedit_set_initial_prompt(void)
613 {
614 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
615         PS1 = NULL;
616 #else
617         PS1 = getenv("PS1");
618         if (PS1 == 0)
619                 PS1 = "\\w \\$ ";
620 #endif
621 }
622
623 static inline const char* setup_prompt_string(void)
624 {
625 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
626         /* Set up the prompt */
627         if (shell_context == 0) {
628                 char *ns;
629                 free((char*)PS1);
630                 ns = xmalloc(strlen(cwd)+4);
631                 sprintf(ns, "%s %c ", cwd, (geteuid() != 0) ? '$': '#');
632                 PS1 = ns;
633                 return ns;
634         } else {
635                 return PS2;
636         }
637 #else
638         return (shell_context == 0)? PS1 : PS2;
639 #endif
640 }
641
642 #if ENABLE_FEATURE_EDITING
643 static line_input_t *line_input_state;
644 #endif
645
646 static int get_command_bufsiz(FILE * source, char *command)
647 {
648         const char *prompt_str;
649
650         if (source == NULL) {
651                 if (local_pending_command) {
652                         /* a command specified (-c option): return it & mark it done */
653                         strncpy(command, local_pending_command, BUFSIZ);
654                         local_pending_command = NULL;
655                         return 0;
656                 }
657                 return 1;
658         }
659
660         if (source == stdin) {
661                 prompt_str = setup_prompt_string();
662
663 #if ENABLE_FEATURE_EDITING
664                 /*
665                 ** enable command line editing only while a command line
666                 ** is actually being read; otherwise, we'll end up bequeathing
667                 ** atexit() handlers and other unwanted stuff to our
668                 ** child processes (rob@sysgo.de)
669                 */
670                 read_line_input(prompt_str, command, BUFSIZ, line_input_state);
671                 return 0;
672 #else
673                 fputs(prompt_str, stdout);
674 #endif
675         }
676
677         if (!fgets(command, BUFSIZ - 2, source)) {
678                 if (source == stdin)
679                         puts("");
680                 return 1;
681         }
682
683         return 0;
684 }
685
686 static char * strsep_space(char *string, int * ix)
687 {
688         /* Short circuit the trivial case */
689         if (!string || ! string[*ix])
690                 return NULL;
691
692         /* Find the end of the token. */
693         while (string[*ix] && !isspace(string[*ix]) ) {
694                 (*ix)++;
695         }
696
697         /* Find the end of any whitespace trailing behind
698          * the token and let that be part of the token */
699         while (string[*ix] && (isspace)(string[*ix]) ) {
700                 (*ix)++;
701         }
702
703         if (!*ix) {
704                 /* Nothing useful was found */
705                 return NULL;
706         }
707
708         return xstrndup(string, *ix);
709 }
710
711 static int expand_arguments(char *command)
712 {
713         static const char out_of_space[] = "out of space during expansion";
714
715         int total_length = 0, length, i, retval, ix = 0;
716         expand_t expand_result;
717         char *tmpcmd, *cmd, *cmd_copy;
718         char *src, *dst, *var;
719         int flags = GLOB_NOCHECK
720 #ifdef GLOB_BRACE
721                 | GLOB_BRACE
722 #endif
723 #ifdef GLOB_TILDE
724                 | GLOB_TILDE
725 #endif
726                 ;
727
728         /* get rid of the terminating \n */
729         chomp(command);
730
731         /* Fix up escape sequences to be the Real Thing(tm) */
732         while (command && command[ix]) {
733                 if (command[ix] == '\\') {
734                         const char *tmp = command+ix+1;
735                         command[ix] = bb_process_escape_sequence(  &tmp );
736                         memmove(command+ix + 1, tmp, strlen(tmp)+1);
737                 }
738                 ix++;
739         }
740         /* Use glob and then fixup environment variables and such */
741
742         /* It turns out that glob is very stupid.  We have to feed it one word at a
743          * time since it can't cope with a full string.  Here we convert command
744          * (char*) into cmd (char**, one word per string) */
745
746         /* We need a clean copy, so strsep can mess up the copy while
747          * we write stuff into the original (in a minute) */
748         cmd = cmd_copy = xstrdup(command);
749         *command = '\0';
750         for (ix = 0, tmpcmd = cmd;
751                         (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix = 0) {
752                 if (*tmpcmd == '\0')
753                         break;
754                 /* we need to trim() the result for glob! */
755                 trim(tmpcmd);
756                 retval = glob(tmpcmd, flags, NULL, &expand_result);
757                 free(tmpcmd); /* Free mem allocated by strsep_space */
758                 if (retval == GLOB_NOSPACE) {
759                         /* Mem may have been allocated... */
760                         globfree(&expand_result);
761                         bb_error_msg(out_of_space);
762                         return FALSE;
763                 } else if (retval != 0) {
764                         /* Some other error.  GLOB_NOMATCH shouldn't
765                          * happen because of the GLOB_NOCHECK flag in
766                          * the glob call. */
767                         bb_error_msg("syntax error");
768                         return FALSE;
769                 } else {
770                         /* Convert from char** (one word per string) to a simple char*,
771                          * but don't overflow command which is BUFSIZ in length */
772                         for (i = 0; i < expand_result.gl_pathc; i++) {
773                                 length = strlen(expand_result.gl_pathv[i]);
774                                 if (total_length+length+1 >= BUFSIZ) {
775                                         bb_error_msg(out_of_space);
776                                         return FALSE;
777                                 }
778                                 strcat(command+total_length, " ");
779                                 total_length += 1;
780                                 strcat(command+total_length, expand_result.gl_pathv[i]);
781                                 total_length += length;
782                         }
783                         globfree(&expand_result);
784                 }
785         }
786         free(cmd_copy);
787         trim(command);
788
789         /* Now do the shell variable substitutions which
790          * wordexp can't do for us, namely $? and $! */
791         src = command;
792         while ((dst = strchr(src,'$')) != NULL) {
793                 var = NULL;
794                 switch (*(dst+1)) {
795                         case '?':
796                                 var = itoa(last_return_code);
797                                 break;
798                         case '!':
799                                 if (last_bg_pid == -1)
800                                         *var = '\0';
801                                 else
802                                         var = itoa(last_bg_pid);
803                                 break;
804                                 /* Everything else like $$, $#, $[0-9], etc. should all be
805                                  * expanded by wordexp(), so we can in theory skip that stuff
806                                  * here, but just to be on the safe side (i.e., since uClibc
807                                  * wordexp doesn't do this stuff yet), lets leave it in for
808                                  * now. */
809                         case '$':
810                                 var = itoa(getpid());
811                                 break;
812                         case '#':
813                                 var = itoa(argc-1);
814                                 break;
815                         case '0':case '1':case '2':case '3':case '4':
816                         case '5':case '6':case '7':case '8':case '9':
817                                 {
818                                         int ixx = *(dst+1)-48+1;
819                                         if (ixx >= argc) {
820                                                 var = '\0';
821                                         } else {
822                                                 var = argv[ixx];
823                                         }
824                                 }
825                                 break;
826
827                 }
828                 if (var) {
829                         /* a single character construction was found, and
830                          * already handled in the case statement */
831                         src = dst + 2;
832                 } else {
833                         /* Looks like an environment variable */
834                         char delim_hold;
835                         int num_skip_chars = 0;
836                         int dstlen = strlen(dst);
837                         /* Is this a ${foo} type variable? */
838                         if (dstlen >= 2 && *(dst+1) == '{') {
839                                 src = strchr(dst+1, '}');
840                                 num_skip_chars = 1;
841                         } else {
842                                 src = dst + 1;
843                                 while ((isalnum)(*src) || *src == '_') src++;
844                         }
845                         if (src == NULL) {
846                                 src = dst+dstlen;
847                         }
848                         delim_hold = *src;
849                         *src = '\0';  /* temporary */
850                         var = getenv(dst + 1 + num_skip_chars);
851                         *src = delim_hold;
852                         src += num_skip_chars;
853                 }
854                 if (var == NULL) {
855                         /* Seems we got an un-expandable variable.  So delete it. */
856                         var = (char*)"";
857                 }
858                 {
859                         int subst_len = strlen(var);
860                         int trail_len = strlen(src);
861                         if (dst+subst_len+trail_len >= command+BUFSIZ) {
862                                 bb_error_msg(out_of_space);
863                                 return FALSE;
864                         }
865                         /* Move stuff to the end of the string to accommodate
866                          * filling the created gap with the new stuff */
867                         memmove(dst+subst_len, src, trail_len+1);
868                         /* Now copy in the new stuff */
869                         memcpy(dst, var, subst_len);
870                         src = dst+subst_len;
871                 }
872         }
873
874         return TRUE;
875 }
876
877 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
878    line). If a valid command is found, command_ptr is set to point to
879    the beginning of the next command (if the original command had more
880    then one job associated with it) or NULL if no more commands are
881    present. */
882 static int parse_command(char **command_ptr, struct job *job, int *inbg)
883 {
884         char *command;
885         char *return_command = NULL;
886         char *src, *buf;
887         int argc_l;
888         int flag;
889         int argv_alloced;
890         char quote = '\0';
891         struct child_prog *prog;
892 #if ENABLE_LASH_PIPE_N_REDIRECTS
893         int i;
894         char *chptr;
895 #endif
896
897         /* skip leading white space */
898         *command_ptr = skip_whitespace(*command_ptr);
899
900         /* this handles empty lines or leading '#' characters */
901         if (!**command_ptr || (**command_ptr == '#')) {
902                 job->num_progs = 0;
903                 return 0;
904         }
905
906         *inbg = 0;
907         job->num_progs = 1;
908         job->progs = xmalloc(sizeof(*job->progs));
909
910         /* We set the argv elements to point inside of this string. The
911            memory is freed by free_job(). Allocate twice the original
912            length in case we need to quote every single character.
913
914            Getting clean memory relieves us of the task of NULL
915            terminating things and makes the rest of this look a bit
916            cleaner (though it is, admittedly, a tad less efficient) */
917         job->cmdbuf = command = xzalloc(2*strlen(*command_ptr) + 1);
918         job->text = NULL;
919
920         prog = job->progs;
921         prog->num_redirects = 0;
922         prog->is_stopped = 0;
923         prog->family = job;
924 #if ENABLE_LASH_PIPE_N_REDIRECTS
925         prog->redirects = NULL;
926 #endif
927
928         argv_alloced = 5;
929         prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
930         prog->argv[0] = job->cmdbuf;
931
932         flag = argc_l = 0;
933         buf = command;
934         src = *command_ptr;
935         while (*src && !(flag & LASH_OPT_DONE)) {
936                 if (quote == *src) {
937                         quote = '\0';
938                 } else if (quote) {
939                         if (*src == '\\') {
940                                 src++;
941                                 if (!*src) {
942                                         bb_error_msg("character expected after \\");
943                                         free_job(job);
944                                         return 1;
945                                 }
946
947                                 /* in shell, "\'" should yield \' */
948                                 if (*src != quote) {
949                                         *buf++ = '\\';
950                                         *buf++ = '\\';
951                                 }
952                         } else if (*src == '*' || *src == '?' || *src == '[' ||
953                                            *src == ']') *buf++ = '\\';
954                         *buf++ = *src;
955                 } else if (isspace(*src)) {
956                         if (*prog->argv[argc_l] || (flag & LASH_OPT_SAW_QUOTE)) {
957                                 buf++, argc_l++;
958                                 /* +1 here leaves room for the NULL which ends argv */
959                                 if ((argc_l + 1) == argv_alloced) {
960                                         argv_alloced += 5;
961                                         prog->argv = xrealloc(prog->argv,
962                                                         sizeof(*prog->argv) * argv_alloced);
963                                 }
964                                 prog->argv[argc_l] = buf;
965                                 flag ^= LASH_OPT_SAW_QUOTE;
966                         }
967                 } else
968                         switch (*src) {
969                         case '"':
970                         case '\'':
971                                 quote = *src;
972                                 flag |= LASH_OPT_SAW_QUOTE;
973                                 break;
974
975                         case '#':                       /* comment */
976                                 if (*(src-1)== '$')
977                                         *buf++ = *src;
978                                 else
979                                         flag |= LASH_OPT_DONE;
980                                 break;
981
982 #if ENABLE_LASH_PIPE_N_REDIRECTS
983                         case '>':                       /* redirects */
984                         case '<':
985                                 i = prog->num_redirects++;
986                                 prog->redirects = xrealloc(prog->redirects,
987                                                 sizeof(*prog->redirects) * (i + 1));
988
989                                 prog->redirects[i].fd = -1;
990                                 if (buf != prog->argv[argc_l]) {
991                                         /* the stuff before this character may be the file number
992                                            being redirected */
993                                         prog->redirects[i].fd =
994                                                 strtol(prog->argv[argc_l], &chptr, 10);
995
996                                         if (*chptr && *prog->argv[argc_l]) {
997                                                 buf++, argc_l++;
998                                                 prog->argv[argc_l] = buf;
999                                         }
1000                                 }
1001
1002                                 if (prog->redirects[i].fd == -1) {
1003                                         if (*src == '>')
1004                                                 prog->redirects[i].fd = 1;
1005                                         else
1006                                                 prog->redirects[i].fd = 0;
1007                                 }
1008
1009                                 if (*src++ == '>') {
1010                                         if (*src == '>')
1011                                                 prog->redirects[i].type =
1012                                                         REDIRECT_APPEND, src++;
1013                                         else
1014                                                 prog->redirects[i].type = REDIRECT_OVERWRITE;
1015                                 } else {
1016                                         prog->redirects[i].type = REDIRECT_INPUT;
1017                                 }
1018
1019                                 /* This isn't POSIX sh compliant. Oh well. */
1020                                 chptr = src;
1021                                 chptr = skip_whitespace(chptr);
1022
1023                                 if (!*chptr) {
1024                                         bb_error_msg("file name expected after %c", *(src-1));
1025                                         free_job(job);
1026                                         job->num_progs = 0;
1027                                         return 1;
1028                                 }
1029
1030                                 prog->redirects[i].filename = buf;
1031                                 while (*chptr && !isspace(*chptr))
1032                                         *buf++ = *chptr++;
1033
1034                                 src = chptr - 1;        /* we src++ later */
1035                                 prog->argv[argc_l] = ++buf;
1036                                 break;
1037
1038                         case '|':                       /* pipe */
1039                                 /* finish this command */
1040                                 if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE)
1041                                         argc_l++;
1042                                 if (!argc_l) {
1043                                         goto empty_command_in_pipe;
1044                                 }
1045                                 prog->argv[argc_l] = NULL;
1046
1047                                 /* and start the next */
1048                                 job->num_progs++;
1049                                 job->progs = xrealloc(job->progs,
1050                                                 sizeof(*job->progs) * job->num_progs);
1051                                 prog = job->progs + (job->num_progs - 1);
1052                                 prog->num_redirects = 0;
1053                                 prog->redirects = NULL;
1054                                 prog->is_stopped = 0;
1055                                 prog->family = job;
1056                                 argc_l = 0;
1057
1058                                 argv_alloced = 5;
1059                                 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1060                                 prog->argv[0] = ++buf;
1061
1062                                 src++;
1063                                 src = skip_whitespace(src);
1064
1065                                 if (!*src) {
1066 empty_command_in_pipe:
1067                                         bb_error_msg("empty command in pipe");
1068                                         free_job(job);
1069                                         job->num_progs = 0;
1070                                         return 1;
1071                                 }
1072                                 src--;                  /* we'll ++ it at the end of the loop */
1073
1074                                 break;
1075 #endif
1076
1077 #if ENABLE_LASH_JOB_CONTROL
1078                         case '&':                       /* background */
1079                                 *inbg = 1;
1080                                 /* fallthrough */
1081 #endif
1082                         case ';':                       /* multiple commands */
1083                                 flag |= LASH_OPT_DONE;
1084                                 return_command = *command_ptr + (src - *command_ptr) + 1;
1085                                 break;
1086
1087                         case '\\':
1088                                 src++;
1089                                 if (!*src) {
1090                                         bb_error_msg("character expected after \\");
1091                                         free_job(job);
1092                                         return 1;
1093                                 }
1094                                 if (*src == '*' || *src == '[' || *src == ']'
1095                                         || *src == '?') *buf++ = '\\';
1096                                 /* fallthrough */
1097                         default:
1098                                 *buf++ = *src;
1099                         }
1100
1101                 src++;
1102         }
1103
1104         if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE) {
1105                 argc_l++;
1106         }
1107         if (!argc_l) {
1108                 free_job(job);
1109                 return 0;
1110         }
1111         prog->argv[argc_l] = NULL;
1112
1113         if (!return_command) {
1114                 job->text = xstrdup(*command_ptr);
1115         } else {
1116                 /* This leaves any trailing spaces, which is a bit sloppy */
1117                 job->text = xstrndup(*command_ptr, return_command - *command_ptr);
1118         }
1119
1120         *command_ptr = return_command;
1121
1122         return 0;
1123 }
1124
1125 /* Run the child_prog, no matter what kind of command it uses.
1126  */
1127 static int pseudo_exec(struct child_prog *child)
1128 {
1129         const struct built_in_command *x;
1130
1131         /* Check if the command matches any of the non-forking builtins.
1132          * Depending on context, this might be redundant.  But it's
1133          * easier to waste a few CPU cycles than it is to figure out
1134          * if this is one of those cases.
1135          */
1136         /* Check if the command matches any of the forking builtins. */
1137         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
1138                 if (strcmp(child->argv[0], x->cmd) == 0) {
1139                         _exit(x->function(child));
1140                 }
1141         }
1142
1143
1144         /* Check if the command matches any busybox internal
1145          * commands ("applets") here.  Following discussions from
1146          * November 2000 on busybox@busybox.net, don't use
1147          * bb_get_last_path_component().  This way explicit (with
1148          * slashes) filenames will never be interpreted as an
1149          * applet, just like with builtins.  This way the user can
1150          * override an applet with an explicit filename reference.
1151          * The only downside to this change is that an explicit
1152          * /bin/foo invocation will fork and exec /bin/foo, even if
1153          * /bin/foo is a symlink to busybox.
1154          */
1155         if (ENABLE_FEATURE_SH_STANDALONE) {
1156                 run_applet_and_exit(child->argv[0], child->argv);
1157         }
1158
1159         execvp(child->argv[0], child->argv);
1160
1161         /* Do not use bb_perror_msg_and_die() here, since we must not
1162          * call exit() but should call _exit() instead */
1163         bb_perror_msg("%s", child->argv[0]);
1164         _exit(EXIT_FAILURE);
1165 }
1166
1167 static void insert_job(struct job *newjob, int inbg)
1168 {
1169         struct job *thejob;
1170         struct jobset *j_list = newjob->job_list;
1171
1172         /* find the ID for thejob to use */
1173         newjob->jobid = 1;
1174         for (thejob = j_list->head; thejob; thejob = thejob->next)
1175                 if (thejob->jobid >= newjob->jobid)
1176                         newjob->jobid = thejob->jobid + 1;
1177
1178         /* add thejob to the list of running jobs */
1179         if (!j_list->head) {
1180                 thejob = j_list->head = xmalloc(sizeof(*thejob));
1181         } else {
1182                 for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1183                 thejob->next = xmalloc(sizeof(*thejob));
1184                 thejob = thejob->next;
1185         }
1186
1187         *thejob = *newjob;   /* physically copy the struct job */
1188         thejob->next = NULL;
1189         thejob->running_progs = thejob->num_progs;
1190         thejob->stopped_progs = 0;
1191
1192 #if ENABLE_LASH_JOB_CONTROL
1193         if (inbg) {
1194                 /* we don't wait for background thejobs to return -- append it
1195                    to the list of backgrounded thejobs and leave it alone */
1196                 printf("[%d] %d\n", thejob->jobid,
1197                            newjob->progs[newjob->num_progs - 1].pid);
1198                 last_jobid = newjob->jobid;
1199                 last_bg_pid = newjob->progs[newjob->num_progs - 1].pid;
1200         } else {
1201                 newjob->job_list->fg = thejob;
1202
1203                 /* move the new process group into the foreground */
1204                 /* Ignore errors since child could have already exited */
1205                 tcsetpgrp(shell_terminal, newjob->pgrp);
1206         }
1207 #endif
1208 }
1209
1210 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1211 {
1212         /* struct job *thejob; */
1213         int i;
1214         int nextin, nextout;
1215         int pipefds[2];                         /* pipefd[0] is for reading */
1216         const struct built_in_command *x;
1217         struct child_prog *child;
1218
1219         nextin = 0;
1220         for (i = 0; i < newjob->num_progs; i++) {
1221                 child = &(newjob->progs[i]);
1222
1223                 nextout = 1;
1224                 if ((i + 1) < newjob->num_progs) {
1225                         if (pipe(pipefds) < 0)
1226                                 bb_perror_msg_and_die("pipe");
1227                         nextout = pipefds[1];
1228                 } else if (outpipe[1] != -1) {
1229                         nextout = outpipe[1];
1230                 }
1231
1232                 /* Check if the command matches any non-forking builtins,
1233                  * but only if this is a simple command.
1234                  * Non-forking builtins within pipes have to fork anyway,
1235                  * and are handled in pseudo_exec.  "echo foo | read bar"
1236                  * is doomed to failure, and doesn't work on bash, either.
1237                  */
1238                 if (newjob->num_progs == 1) {
1239                         int rcode;
1240                         int squirrel[] = {-1, -1, -1};
1241
1242                         /* Check if the command sets an environment variable. */
1243                         if (strchr(child->argv[0], '=') != NULL) {
1244                                 child->argv[1] = child->argv[0];
1245                                 return builtin_export(child);
1246                         }
1247
1248                         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
1249                                 if (strcmp(child->argv[0], x->cmd) == 0) {
1250                                         setup_redirects(child, squirrel);
1251                                         rcode = x->function(child);
1252                                         restore_redirects(squirrel);
1253                                         return rcode;
1254                                 }
1255                         }
1256 #if ENABLE_FEATURE_SH_STANDALONE
1257                         {
1258                                 const struct bb_applet *a = find_applet_by_name(child->argv[i]);
1259                                 if (a && a->nofork) {
1260                                         setup_redirects(child, squirrel);
1261                                         rcode = run_nofork_applet(a, child->argv + i);
1262                                         restore_redirects(squirrel);
1263                                         return rcode;
1264                                 }
1265                         }
1266 #endif
1267                 }
1268
1269 #if BB_MMU
1270                 child->pid = fork();
1271 #else
1272                 child->pid = vfork();
1273 #endif
1274                 if (!child->pid) {
1275                         /* Set the handling for job control signals back to the default.  */
1276                         signal(SIGINT, SIG_DFL);
1277                         signal(SIGQUIT, SIG_DFL);
1278                         signal(SIGTSTP, SIG_DFL);
1279                         signal(SIGTTIN, SIG_DFL);
1280                         signal(SIGTTOU, SIG_DFL);
1281                         signal(SIGCHLD, SIG_DFL);
1282
1283                         /* Close all open filehandles. */
1284                         while (close_me_list)
1285                                 close((long)llist_pop(&close_me_list));
1286
1287                         if (outpipe[1] != -1) {
1288                                 close(outpipe[0]);
1289                         }
1290                         if (nextin != 0) {
1291                                 dup2(nextin, 0);
1292                                 close(nextin);
1293                         }
1294
1295                         if (nextout != 1) {
1296                                 dup2(nextout, 1);
1297                                 dup2(nextout, 2);  /* Really? */
1298                                 close(nextout);
1299                                 close(pipefds[0]);
1300                         }
1301
1302                         /* explicit redirects override pipes */
1303                         setup_redirects(child,NULL);
1304
1305                         pseudo_exec(child);
1306                 }
1307                 if (outpipe[1] != -1) {
1308                         close(outpipe[1]);
1309                 }
1310
1311                 /* put our child in the process group whose leader is the
1312                    first process in this pipe */
1313                 setpgid(child->pid, newjob->progs[0].pid);
1314                 if (nextin != 0)
1315                         close(nextin);
1316                 if (nextout != 1)
1317                         close(nextout);
1318
1319                 /* If there isn't another process, nextin is garbage
1320                    but it doesn't matter */
1321                 nextin = pipefds[0];
1322         }
1323
1324         newjob->pgrp = newjob->progs[0].pid;
1325
1326         insert_job(newjob, inbg);
1327
1328         return 0;
1329 }
1330
1331 static int busy_loop(FILE * input)
1332 {
1333         char *command;
1334         char *next_command = NULL;
1335         struct job newjob;
1336         int i;
1337         int inbg = 0;
1338         int status;
1339 #if ENABLE_LASH_JOB_CONTROL
1340         pid_t  parent_pgrp;
1341         /* save current owner of TTY so we can restore it on exit */
1342         parent_pgrp = tcgetpgrp(shell_terminal);
1343 #endif
1344         newjob.job_list = &job_list;
1345         newjob.job_context = DEFAULT_CONTEXT;
1346
1347         command = xzalloc(BUFSIZ);
1348
1349         while (1) {
1350                 if (!job_list.fg) {
1351                         /* no job is in the foreground */
1352
1353                         /* see if any background processes have exited */
1354                         checkjobs(&job_list);
1355
1356                         if (!next_command) {
1357                                 if (get_command_bufsiz(input, command))
1358                                         break;
1359                                 next_command = command;
1360                         }
1361
1362                         if (!expand_arguments(next_command)) {
1363                                 free(command);
1364                                 command = xzalloc(BUFSIZ);
1365                                 next_command = NULL;
1366                                 continue;
1367                         }
1368
1369                         if (!parse_command(&next_command, &newjob, &inbg) &&
1370                                 newjob.num_progs) {
1371                                 int pipefds[2] = { -1, -1 };
1372                                 debug_printf("job=%p fed to run_command by busy_loop()'\n",
1373                                                 &newjob);
1374                                 run_command(&newjob, inbg, pipefds);
1375                         }
1376                         else {
1377                                 free(command);
1378                                 command = xzalloc(BUFSIZ);
1379                                 next_command = NULL;
1380                         }
1381                 } else {
1382                         /* a job is running in the foreground; wait for it */
1383                         i = 0;
1384                         while (!job_list.fg->progs[i].pid ||
1385                                    job_list.fg->progs[i].is_stopped == 1) i++;
1386
1387                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED) < 0) {
1388                                 if (errno != ECHILD) {
1389                                         bb_perror_msg_and_die("waitpid(%d)", job_list.fg->progs[i].pid);
1390                                 }
1391                         }
1392
1393                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1394                                 /* the child exited */
1395                                 job_list.fg->running_progs--;
1396                                 job_list.fg->progs[i].pid = 0;
1397
1398                                 last_return_code = WEXITSTATUS(status);
1399
1400                                 if (!job_list.fg->running_progs) {
1401                                         /* child exited */
1402                                         remove_job(&job_list, job_list.fg);
1403                                         job_list.fg = NULL;
1404                                 }
1405                         }
1406 #if ENABLE_LASH_JOB_CONTROL
1407                         else {
1408                                 /* the child was stopped */
1409                                 job_list.fg->stopped_progs++;
1410                                 job_list.fg->progs[i].is_stopped = 1;
1411
1412                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1413                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1414                                                    "Stopped", job_list.fg->text);
1415                                         job_list.fg = NULL;
1416                                 }
1417                         }
1418
1419                         if (!job_list.fg) {
1420                                 /* move the shell to the foreground */
1421                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1422                                 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
1423                                         bb_perror_msg("tcsetpgrp");
1424                         }
1425 #endif
1426                 }
1427         }
1428         free(command);
1429
1430 #if ENABLE_LASH_JOB_CONTROL
1431         /* return controlling TTY back to parent process group before exiting */
1432         if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
1433                 bb_perror_msg("tcsetpgrp");
1434 #endif
1435
1436         /* return exit status if called with "-c" */
1437         if (input == NULL && WIFEXITED(status))
1438                 return WEXITSTATUS(status);
1439
1440         return 0;
1441 }
1442
1443 #if ENABLE_FEATURE_CLEAN_UP
1444 static void free_memory(void)
1445 {
1446         free(cwd);
1447
1448         if (job_list.fg && !job_list.fg->running_progs) {
1449                 remove_job(&job_list, job_list.fg);
1450         }
1451 }
1452 #else
1453 void free_memory(void);
1454 #endif
1455
1456 #if ENABLE_LASH_JOB_CONTROL
1457 /* Make sure we have a controlling tty.  If we get started under a job
1458  * aware app (like bash for example), make sure we are now in charge so
1459  * we don't fight over who gets the foreground */
1460 static void setup_job_control(void)
1461 {
1462         int status;
1463         pid_t shell_pgrp;
1464
1465         /* Loop until we are in the foreground.  */
1466         while ((status = tcgetpgrp(shell_terminal)) >= 0) {
1467                 shell_pgrp = getpgrp();
1468                 if (status == shell_pgrp) {
1469                         break;
1470                 }
1471                 kill(- shell_pgrp, SIGTTIN);
1472         }
1473
1474         /* Ignore interactive and job-control signals.  */
1475         signal(SIGINT, SIG_IGN);
1476         signal(SIGQUIT, SIG_IGN);
1477         signal(SIGTSTP, SIG_IGN);
1478         signal(SIGTTIN, SIG_IGN);
1479         signal(SIGTTOU, SIG_IGN);
1480         signal(SIGCHLD, SIG_IGN);
1481
1482         /* Put ourselves in our own process group.  */
1483         setsid();
1484         shell_pgrp = getpid();
1485         setpgid(shell_pgrp, shell_pgrp);
1486
1487         /* Grab control of the terminal.  */
1488         tcsetpgrp(shell_terminal, shell_pgrp);
1489 }
1490 #else
1491 static inline void setup_job_control(void)
1492 {
1493 }
1494 #endif
1495
1496 int lash_main(int argc_l, char **argv_l);
1497 int lash_main(int argc_l, char **argv_l)
1498 {
1499         unsigned opt;
1500         FILE *input = stdin;
1501         argc = argc_l;
1502         argv = argv_l;
1503
1504 #if ENABLE_FEATURE_EDITING
1505         line_input_state = new_line_input_t(FOR_SHELL);
1506 #endif
1507
1508         /* These variables need re-initializing when recursing */
1509         last_jobid = 0;
1510         close_me_list = NULL;
1511         job_list.head = NULL;
1512         job_list.fg = NULL;
1513         last_return_code = 1;
1514
1515         if (argv[0] && argv[0][0] == '-') {
1516                 FILE *prof_input;
1517                 prof_input = fopen("/etc/profile", "r");
1518                 if (prof_input) {
1519                         llist_add_to(&close_me_list, (void *)(long)fileno(prof_input));
1520                         /* Now run the file */
1521                         busy_loop(prof_input);
1522                         fclose_if_not_stdin(prof_input);
1523                         llist_pop(&close_me_list);
1524                 }
1525         }
1526
1527         opt = getopt32(argc_l, argv_l, "+ic:", &local_pending_command);
1528 #define LASH_OPT_i (1<<0)
1529 #define LASH_OPT_c (1<<1)
1530         if (opt & LASH_OPT_c) {
1531                 input = NULL;
1532                 optind++;
1533                 argv += optind;
1534         }
1535         /* A shell is interactive if the `-i' flag was given, or if all of
1536          * the following conditions are met:
1537          *        no -c command
1538          *    no arguments remaining or the -s flag given
1539          *    standard input is a terminal
1540          *    standard output is a terminal
1541          *    Refer to Posix.2, the description of the `sh' utility. */
1542         if (argv[optind] == NULL && input == stdin
1543          && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
1544         ) {
1545                 opt |= LASH_OPT_i;
1546         }
1547         setup_job_control();
1548         if (opt & LASH_OPT_i) {
1549                 /* Looks like they want an interactive shell */
1550                 if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
1551                         printf("\n\n%s Built-in shell (lash)\n"
1552                                         "Enter 'help' for a list of built-in commands.\n\n",
1553                                         BB_BANNER);
1554                 }
1555         } else if (!local_pending_command && argv[optind]) {
1556                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1557                 input = xfopen(argv[optind], "r");
1558                 /* be lazy, never mark this closed */
1559                 llist_add_to(&close_me_list, (void *)(long)fileno(input));
1560         }
1561
1562         /* initialize the cwd -- this is never freed...*/
1563         update_cwd();
1564
1565         if (ENABLE_FEATURE_CLEAN_UP) atexit(free_memory);
1566
1567         if (ENABLE_FEATURE_EDITING) cmdedit_set_initial_prompt();
1568         else PS1 = NULL;
1569
1570         return busy_loop(input);
1571 }