Fixed time command segfault with no arguments
[busybox4maemo] / shell / lash_unused.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 #include <getopt.h>
24 #include <glob.h>
25
26 #include "libbb.h"
27
28 #define expand_t        glob_t
29
30 /* Always enable for the moment... */
31 #define CONFIG_LASH_PIPE_N_REDIRECTS
32 #define CONFIG_LASH_JOB_CONTROL
33 #define ENABLE_LASH_PIPE_N_REDIRECTS 1
34 #define ENABLE_LASH_JOB_CONTROL      1
35
36
37 enum { MAX_READ = 128 }; /* size of input buffer for 'read' builtin */
38 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
39
40
41 #if ENABLE_LASH_PIPE_N_REDIRECTS
42 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
43         REDIRECT_APPEND
44 };
45 #endif
46
47 enum {
48         DEFAULT_CONTEXT = 0x1,
49         IF_TRUE_CONTEXT = 0x2,
50         IF_FALSE_CONTEXT = 0x4,
51         THEN_EXP_CONTEXT = 0x8,
52         ELSE_EXP_CONTEXT = 0x10
53 };
54
55 #define LASH_OPT_DONE (1)
56 #define LASH_OPT_SAW_QUOTE (2)
57
58 #if ENABLE_LASH_PIPE_N_REDIRECTS
59 struct redir_struct {
60         enum redir_type type;   /* type of redirection */
61         int fd;                                         /* file descriptor being redirected */
62         char *filename;                         /* file to redirect fd to */
63 };
64 #endif
65
66 struct child_prog {
67         pid_t pid;                                      /* 0 if exited */
68         char **argv;                            /* program name and arguments */
69         int num_redirects;                      /* elements in redirection array */
70         int is_stopped;                         /* is the program currently running? */
71         struct job *family;                     /* pointer back to the child's parent job */
72 #if ENABLE_LASH_PIPE_N_REDIRECTS
73         struct redir_struct *redirects; /* I/O redirects */
74 #endif
75 };
76
77 struct jobset {
78         struct job *head;                       /* head of list of running jobs */
79         struct job *fg;                         /* current foreground job */
80 };
81
82 struct job {
83         int jobid;                                      /* job number */
84         int num_progs;                          /* total number of programs in job */
85         int running_progs;                      /* number of programs running */
86         char *text;                                     /* name of job */
87         char *cmdbuf;                           /* buffer various argv's point into */
88         pid_t pgrp;                                     /* process group ID for the job */
89         struct child_prog *progs;       /* array of programs in job */
90         struct job *next;                       /* to track background commands */
91         int stopped_progs;                      /* number of programs alive, but stopped */
92         unsigned int job_context;       /* bitmask defining current context */
93         struct jobset *job_list;
94 };
95
96 struct built_in_command {
97         const char *cmd;   /* name */
98         const char *descr; /* description */
99         int (*function) (struct child_prog *);  /* function ptr */
100 };
101
102 /* function prototypes for builtins */
103 static int builtin_cd(struct child_prog *cmd);
104 static int builtin_exec(struct child_prog *cmd);
105 static int builtin_exit(struct child_prog *cmd);
106 static int builtin_fg_bg(struct child_prog *cmd);
107 static int builtin_help(struct child_prog *cmd);
108 static int builtin_jobs(struct child_prog *dummy);
109 static int builtin_pwd(struct child_prog *dummy);
110 static int builtin_export(struct child_prog *cmd);
111 static int builtin_source(struct child_prog *cmd);
112 static int builtin_unset(struct child_prog *cmd);
113 static int builtin_read(struct child_prog *cmd);
114
115
116 /* function prototypes for shell stuff */
117 static void checkjobs(struct jobset *job_list);
118 static void remove_job(struct jobset *j_list, struct job *job);
119 static int get_command_bufsiz(FILE * source, char *command);
120 static int parse_command(char **command_ptr, struct job *job, int *inbg);
121 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
122 static int pseudo_exec(struct child_prog *cmd) ATTRIBUTE_NORETURN;
123 static int busy_loop(FILE * input);
124
125
126 /* Table of built-in functions (these are non-forking builtins, meaning they
127  * can change global variables in the parent shell process but they will not
128  * work with pipes and redirects; 'unset foo | whatever' will not work) */
129 static const struct built_in_command bltins[] = {
130         {"bg"    , "Resume a job in the background", builtin_fg_bg},
131         {"cd"    , "Change working directory", builtin_cd},
132         {"exec"  , "Exec command, replacing this shell with the exec'd process", builtin_exec},
133         {"exit"  , "Exit from shell()", builtin_exit},
134         {"fg"    , "Bring job into the foreground", builtin_fg_bg},
135         {"jobs"  , "Lists the active jobs", builtin_jobs},
136         {"export", "Set environment variable", builtin_export},
137         {"unset" , "Unset environment variable", builtin_unset},
138         {"read"  , "Input environment variable", builtin_read},
139         {"."     , "Source-in and run commands in a file", builtin_source},
140         /* These were "forked applets", but distinction was nuked */
141         /* Original comment retained: */
142         /* Table of forking built-in functions (things that fork cannot change global
143          * variables in the parent process, such as the current working directory) */
144         {"pwd"   , "Print current directory", builtin_pwd},
145         {"help"  , "List shell built-in commands", builtin_help},
146         /* to do: add ulimit */
147 };
148
149
150 #define VEC_LAST(v) v[ARRAY_SIZE(v)-1]
151
152
153 static int shell_context;  /* Type prompt trigger (PS1 or PS2) */
154
155
156 /* Globals that are static to this file */
157 static char *cwd;
158 static char *local_pending_command;
159 static struct jobset job_list = { NULL, NULL };
160 static int global_argc;
161 static char **global_argv;
162 static llist_t *close_me_list;
163 static int last_return_code;
164 static int last_bg_pid;
165 static unsigned int last_jobid;
166 static int shell_terminal;
167 static const char *PS1;
168 static const char *PS2 = "> ";
169
170
171 #ifdef DEBUG_SHELL
172 static inline void debug_printf(const char *format, ...)
173 {
174         va_list args;
175         va_start(args, format);
176         vfprintf(stderr, format, args);
177         va_end(args);
178 }
179 #else
180 static inline void debug_printf(const char ATTRIBUTE_UNUSED *format, ...) { }
181 #endif
182
183 /*
184         Most builtins need access to the struct child_prog that has
185         their arguments, previously coded as cmd->progs[0].  That coding
186         can exhibit a bug, if the builtin is not the first command in
187         a pipeline: "echo foo | exec sort" will attempt to exec foo.
188
189 builtin   previous use      notes
190 ------ -----------------  ---------
191 cd      cmd->progs[0]
192 exec    cmd->progs[0]  squashed bug: didn't look for applets or forking builtins
193 exit    cmd->progs[0]
194 fg_bg   cmd->progs[0], job_list->head, job_list->fg
195 help    0
196 jobs    job_list->head
197 pwd     0
198 export  cmd->progs[0]
199 source  cmd->progs[0]
200 unset   cmd->progs[0]
201 read    cmd->progs[0]
202
203 I added "struct job *family;" to struct child_prog,
204 and switched API to builtin_foo(struct child_prog *child);
205 So   cmd->text        becomes  child->family->text
206      cmd->job_context  becomes  child->family->job_context
207      cmd->progs[0]    becomes  *child
208      job_list          becomes  child->family->job_list
209  */
210
211
212 static void update_cwd(void)
213 {
214         cwd = xrealloc_getcwd_or_warn(cwd);
215         if (!cwd)
216                 cwd = xstrdup(bb_msg_unknown);
217 }
218
219 /* built-in 'cd <path>' handler */
220 static int builtin_cd(struct child_prog *child)
221 {
222         char *newdir;
223
224         if (child->argv[1] == NULL)
225                 newdir = getenv("HOME");
226         else
227                 newdir = child->argv[1];
228         if (chdir(newdir)) {
229                 bb_perror_msg("cd: %s", newdir);
230                 return EXIT_FAILURE;
231         }
232         update_cwd();
233         return EXIT_SUCCESS;
234 }
235
236 /* built-in 'exec' handler */
237 static int builtin_exec(struct child_prog *child)
238 {
239         if (child->argv[1] == NULL)
240                 return EXIT_SUCCESS;   /* Really? */
241         child->argv++;
242         while (close_me_list)
243                 close((long)llist_pop(&close_me_list));
244         pseudo_exec(child);
245         /* never returns */
246 }
247
248 /* built-in 'exit' handler */
249 static int builtin_exit(struct child_prog *child)
250 {
251         if (child->argv[1] == NULL)
252                 exit(EXIT_SUCCESS);
253
254         exit(atoi(child->argv[1]));
255 }
256
257 /* built-in 'fg' and 'bg' handler */
258 static int builtin_fg_bg(struct child_prog *child)
259 {
260         int i, jobnum;
261         struct job *job;
262
263         /* If they gave us no args, assume they want the last backgrounded task */
264         if (!child->argv[1]) {
265                 for (job = child->family->job_list->head; job; job = job->next) {
266                         if (job->jobid == last_jobid) {
267                                 goto found;
268                         }
269                 }
270                 bb_error_msg("%s: no current job", child->argv[0]);
271                 return EXIT_FAILURE;
272         }
273         if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
274                 bb_error_msg(bb_msg_invalid_arg, child->argv[1], child->argv[0]);
275                 return EXIT_FAILURE;
276         }
277         for (job = child->family->job_list->head; job; job = job->next) {
278                 if (job->jobid == jobnum) {
279                         goto found;
280                 }
281         }
282         bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
283         return EXIT_FAILURE;
284  found:
285         if (*child->argv[0] == 'f') {
286                 /* Put the job into the foreground.  */
287                 tcsetpgrp(shell_terminal, job->pgrp);
288
289                 child->family->job_list->fg = job;
290         }
291
292         /* Restart the processes in the job */
293         for (i = 0; i < job->num_progs; i++)
294                 job->progs[i].is_stopped = 0;
295
296         job->stopped_progs = 0;
297
298         i = kill(- job->pgrp, SIGCONT);
299         if (i < 0) {
300                 if (errno == ESRCH) {
301                         remove_job(&job_list, job);
302                 } else {
303                         bb_perror_msg("kill (SIGCONT)");
304                 }
305         }
306
307         return EXIT_SUCCESS;
308 }
309
310 /* built-in 'help' handler */
311 static int builtin_help(struct child_prog ATTRIBUTE_UNUSED *dummy)
312 {
313         const struct built_in_command *x;
314
315         printf("\nBuilt-in commands:\n"
316                "-------------------\n");
317         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
318                 if (x->descr == NULL)
319                         continue;
320                 printf("%s\t%s\n", x->cmd, x->descr);
321         }
322         bb_putchar('\n');
323         return EXIT_SUCCESS;
324 }
325
326 /* built-in 'jobs' handler */
327 static int builtin_jobs(struct child_prog *child)
328 {
329         struct job *job;
330         const char *status_string;
331
332         for (job = child->family->job_list->head; job; job = job->next) {
333                 if (job->running_progs == job->stopped_progs)
334                         status_string = "Stopped";
335                 else
336                         status_string = "Running";
337
338                 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
339         }
340         return EXIT_SUCCESS;
341 }
342
343
344 /* built-in 'pwd' handler */
345 static int builtin_pwd(struct child_prog ATTRIBUTE_UNUSED *dummy)
346 {
347         update_cwd();
348         puts(cwd);
349         return EXIT_SUCCESS;
350 }
351
352 /* built-in 'export VAR=value' handler */
353 static int builtin_export(struct child_prog *child)
354 {
355         int res;
356         char *v = child->argv[1];
357
358         if (v == NULL) {
359                 char **e;
360                 for (e = environ; *e; e++) {
361                         puts(*e);
362                 }
363                 return 0;
364         }
365         res = putenv(v);
366         if (res)
367                 bb_perror_msg("export");
368 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
369         if (strncmp(v, "PS1=", 4) == 0)
370                 PS1 = getenv("PS1");
371 #endif
372
373 #if ENABLE_LOCALE_SUPPORT
374         // TODO: why getenv? "" would be just as good...
375         if (strncmp(v, "LC_ALL=", 7) == 0)
376                 setlocale(LC_ALL, getenv("LC_ALL"));
377         if (strncmp(v, "LC_CTYPE=", 9) == 0)
378                 setlocale(LC_CTYPE, getenv("LC_CTYPE"));
379 #endif
380
381         return res;
382 }
383
384 /* built-in 'read VAR' handler */
385 static int builtin_read(struct child_prog *child)
386 {
387         int res = 0, len;
388         char *s;
389         char string[MAX_READ];
390
391         if (child->argv[1]) {
392                 /* argument (VAR) given: put "VAR=" into buffer */
393                 safe_strncpy(string, child->argv[1], MAX_READ-1);
394                 len = strlen(string);
395                 string[len++] = '=';
396                 string[len]   = '\0';
397                 fgets(&string[len], sizeof(string) - len, stdin);       /* read string */
398                 res = strlen(string);
399                 if (res > len)
400                         string[--res] = '\0';   /* chomp trailing newline */
401                 /*
402                 ** string should now contain "VAR=<value>"
403                 ** copy it (putenv() won't do that, so we must make sure
404                 ** the string resides in a static buffer!)
405                 */
406                 res = -1;
407                 s = strdup(string);
408                 if (s)
409                         res = putenv(s);
410                 if (res)
411                         bb_perror_msg("read");
412         } else
413                 fgets(string, sizeof(string), stdin);
414
415         return res;
416 }
417
418 /* Built-in '.' handler (read-in and execute commands from file) */
419 static int builtin_source(struct child_prog *child)
420 {
421         FILE *input;
422         int status;
423
424         input = fopen_or_warn(child->argv[1], "r");
425         if (!input) {
426                 return EXIT_FAILURE;
427         }
428
429         llist_add_to(&close_me_list, (void *)(long)fileno(input));
430         /* Now run the file */
431         status = busy_loop(input);
432         fclose(input);
433         llist_pop(&close_me_list);
434         return status;
435 }
436
437 /* built-in 'unset VAR' handler */
438 static int builtin_unset(struct child_prog *child)
439 {
440         if (child->argv[1] == NULL) {
441                 printf(bb_msg_requires_arg, "unset");
442                 return EXIT_FAILURE;
443         }
444         unsetenv(child->argv[1]);
445         return EXIT_SUCCESS;
446 }
447
448 #if ENABLE_LASH_JOB_CONTROL
449 /* free up all memory from a job */
450 static void free_job(struct job *cmd)
451 {
452         int i;
453         struct jobset *keep;
454
455         for (i = 0; i < cmd->num_progs; i++) {
456                 free(cmd->progs[i].argv);
457 #if ENABLE_LASH_PIPE_N_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 = open_or_warn(redir->filename, mode);
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                                 close_on_exec_on(squirrel[redir->fd]);
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                         bb_putchar('\n');
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[] ALIGN1 = "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(global_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 >= global_argc) {
820                                                 var = '\0';
821                                         } else {
822                                                 var = global_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         /* Check if the command matches any busybox internal
1144          * commands ("applets") here.  Following discussions from
1145          * November 2000 on busybox@busybox.net, don't use
1146          * bb_get_last_path_component_nostrip().  This way explicit
1147          * (with slashes) filenames will never be interpreted as an
1148          * applet, just like with builtins.  This way the user can
1149          * override an applet with an explicit filename reference.
1150          * The only downside to this change is that an explicit
1151          * /bin/foo invocation will fork and exec /bin/foo, even if
1152          * /bin/foo is a symlink to busybox.
1153          */
1154         if (ENABLE_FEATURE_SH_STANDALONE) {
1155                 run_applet_and_exit(child->argv[0], child->argv);
1156         }
1157
1158         execvp(child->argv[0], child->argv);
1159
1160         /* Do not use bb_perror_msg_and_die() here, since we must not
1161          * call exit() but should call _exit() instead */
1162         bb_simple_perror_msg(child->argv[0]);
1163         _exit(EXIT_FAILURE);
1164 }
1165
1166 static void insert_job(struct job *newjob, int inbg)
1167 {
1168         struct job *thejob;
1169         struct jobset *j_list = newjob->job_list;
1170
1171         /* find the ID for thejob to use */
1172         newjob->jobid = 1;
1173         for (thejob = j_list->head; thejob; thejob = thejob->next)
1174                 if (thejob->jobid >= newjob->jobid)
1175                         newjob->jobid = thejob->jobid + 1;
1176
1177         /* add thejob to the list of running jobs */
1178         if (!j_list->head) {
1179                 thejob = j_list->head = xmalloc(sizeof(*thejob));
1180         } else {
1181                 for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1182                 thejob->next = xmalloc(sizeof(*thejob));
1183                 thejob = thejob->next;
1184         }
1185
1186         *thejob = *newjob;   /* physically copy the struct job */
1187         thejob->next = NULL;
1188         thejob->running_progs = thejob->num_progs;
1189         thejob->stopped_progs = 0;
1190
1191 #if ENABLE_LASH_JOB_CONTROL
1192         if (inbg) {
1193                 /* we don't wait for background thejobs to return -- append it
1194                    to the list of backgrounded thejobs and leave it alone */
1195                 printf("[%d] %d\n", thejob->jobid,
1196                            newjob->progs[newjob->num_progs - 1].pid);
1197                 last_jobid = newjob->jobid;
1198                 last_bg_pid = newjob->progs[newjob->num_progs - 1].pid;
1199         } else {
1200                 newjob->job_list->fg = thejob;
1201
1202                 /* move the new process group into the foreground */
1203                 /* Ignore errors since child could have already exited */
1204                 tcsetpgrp(shell_terminal, newjob->pgrp);
1205         }
1206 #endif
1207 }
1208
1209 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1210 {
1211         /* struct job *thejob; */
1212         int i;
1213         int nextin, nextout;
1214         int pipefds[2];                         /* pipefd[0] is for reading */
1215         const struct built_in_command *x;
1216         struct child_prog *child;
1217
1218         nextin = 0;
1219         for (i = 0; i < newjob->num_progs; i++) {
1220                 child = &(newjob->progs[i]);
1221
1222                 nextout = 1;
1223                 if ((i + 1) < newjob->num_progs) {
1224                         xpipe(pipefds);
1225                         nextout = pipefds[1];
1226                 } else if (outpipe[1] != -1) {
1227                         nextout = outpipe[1];
1228                 }
1229
1230                 /* Check if the command matches any non-forking builtins,
1231                  * but only if this is a simple command.
1232                  * Non-forking builtins within pipes have to fork anyway,
1233                  * and are handled in pseudo_exec.  "echo foo | read bar"
1234                  * is doomed to failure, and doesn't work on bash, either.
1235                  */
1236                 if (newjob->num_progs == 1) {
1237                         int rcode;
1238                         int squirrel[] = {-1, -1, -1};
1239
1240                         /* Check if the command sets an environment variable. */
1241                         if (strchr(child->argv[0], '=') != NULL) {
1242                                 child->argv[1] = child->argv[0];
1243                                 return builtin_export(child);
1244                         }
1245
1246                         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
1247                                 if (strcmp(child->argv[0], x->cmd) == 0) {
1248                                         setup_redirects(child, squirrel);
1249                                         rcode = x->function(child);
1250                                         restore_redirects(squirrel);
1251                                         return rcode;
1252                                 }
1253                         }
1254 #if ENABLE_FEATURE_SH_STANDALONE
1255                         {
1256                                 int a = find_applet_by_name(child->argv[i]);
1257                                 if (a >= 0 && APPLET_IS_NOFORK(a)) {
1258                                         setup_redirects(child, squirrel);
1259                                         rcode = run_nofork_applet(a, child->argv + i);
1260                                         restore_redirects(squirrel);
1261                                         return rcode;
1262                                 }
1263                         }
1264 #endif
1265                 }
1266
1267 #if BB_MMU
1268                 child->pid = fork();
1269 #else
1270                 child->pid = vfork();
1271 #endif
1272                 if (!child->pid) {
1273                         /* Set the handling for job control signals back to the default.  */
1274                         signal(SIGINT, SIG_DFL);
1275                         signal(SIGQUIT, SIG_DFL);
1276                         signal(SIGTSTP, SIG_DFL);
1277                         signal(SIGTTIN, SIG_DFL);
1278                         signal(SIGTTOU, SIG_DFL);
1279                         signal(SIGCHLD, SIG_DFL);
1280
1281                         /* Close all open filehandles. */
1282                         while (close_me_list)
1283                                 close((long)llist_pop(&close_me_list));
1284
1285                         if (outpipe[1] != -1) {
1286                                 close(outpipe[0]);
1287                         }
1288                         if (nextin != 0) {
1289                                 dup2(nextin, 0);
1290                                 close(nextin);
1291                         }
1292
1293                         if (nextout != 1) {
1294                                 dup2(nextout, 1);
1295                                 dup2(nextout, 2);  /* Really? */
1296                                 close(nextout);
1297                                 close(pipefds[0]);
1298                         }
1299
1300                         /* explicit redirects override pipes */
1301                         setup_redirects(child,NULL);
1302
1303                         pseudo_exec(child);
1304                 }
1305                 if (outpipe[1] != -1) {
1306                         close(outpipe[1]);
1307                 }
1308
1309                 /* put our child in the process group whose leader is the
1310                    first process in this pipe */
1311                 setpgid(child->pid, newjob->progs[0].pid);
1312                 if (nextin != 0)
1313                         close(nextin);
1314                 if (nextout != 1)
1315                         close(nextout);
1316
1317                 /* If there isn't another process, nextin is garbage
1318                    but it doesn't matter */
1319                 nextin = pipefds[0];
1320         }
1321
1322         newjob->pgrp = newjob->progs[0].pid;
1323
1324         insert_job(newjob, inbg);
1325
1326         return 0;
1327 }
1328
1329 static int busy_loop(FILE * input)
1330 {
1331         char *command;
1332         char *next_command = NULL;
1333         struct job newjob;
1334         int i;
1335         int inbg = 0;
1336         int status;
1337 #if ENABLE_LASH_JOB_CONTROL
1338         pid_t  parent_pgrp;
1339         /* save current owner of TTY so we can restore it on exit */
1340         parent_pgrp = tcgetpgrp(shell_terminal);
1341 #endif
1342         newjob.job_list = &job_list;
1343         newjob.job_context = DEFAULT_CONTEXT;
1344
1345         command = xzalloc(BUFSIZ);
1346
1347         while (1) {
1348                 if (!job_list.fg) {
1349                         /* no job is in the foreground */
1350
1351                         /* see if any background processes have exited */
1352                         checkjobs(&job_list);
1353
1354                         if (!next_command) {
1355                                 if (get_command_bufsiz(input, command))
1356                                         break;
1357                                 next_command = command;
1358                         }
1359
1360                         if (!expand_arguments(next_command)) {
1361                                 free(command);
1362                                 command = xzalloc(BUFSIZ);
1363                                 next_command = NULL;
1364                                 continue;
1365                         }
1366
1367                         if (!parse_command(&next_command, &newjob, &inbg) &&
1368                                 newjob.num_progs) {
1369                                 int pipefds[2] = { -1, -1 };
1370                                 debug_printf("job=%p fed to run_command by busy_loop()'\n",
1371                                                 &newjob);
1372                                 run_command(&newjob, inbg, pipefds);
1373                         }
1374                         else {
1375                                 free(command);
1376                                 command = xzalloc(BUFSIZ);
1377                                 next_command = NULL;
1378                         }
1379                 } else {
1380                         /* a job is running in the foreground; wait for it */
1381                         i = 0;
1382                         while (!job_list.fg->progs[i].pid ||
1383                                    job_list.fg->progs[i].is_stopped == 1) i++;
1384
1385                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED) < 0) {
1386                                 if (errno != ECHILD) {
1387                                         bb_perror_msg_and_die("waitpid(%d)", job_list.fg->progs[i].pid);
1388                                 }
1389                         }
1390
1391                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1392                                 /* the child exited */
1393                                 job_list.fg->running_progs--;
1394                                 job_list.fg->progs[i].pid = 0;
1395
1396                                 last_return_code = WEXITSTATUS(status);
1397
1398                                 if (!job_list.fg->running_progs) {
1399                                         /* child exited */
1400                                         remove_job(&job_list, job_list.fg);
1401                                         job_list.fg = NULL;
1402                                 }
1403                         }
1404 #if ENABLE_LASH_JOB_CONTROL
1405                         else {
1406                                 /* the child was stopped */
1407                                 job_list.fg->stopped_progs++;
1408                                 job_list.fg->progs[i].is_stopped = 1;
1409
1410                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1411                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1412                                                    "Stopped", job_list.fg->text);
1413                                         job_list.fg = NULL;
1414                                 }
1415                         }
1416
1417                         if (!job_list.fg) {
1418                                 /* move the shell to the foreground */
1419                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1420                                 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
1421                                         bb_perror_msg("tcsetpgrp");
1422                         }
1423 #endif
1424                 }
1425         }
1426         free(command);
1427
1428 #if ENABLE_LASH_JOB_CONTROL
1429         /* return controlling TTY back to parent process group before exiting */
1430         if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
1431                 bb_perror_msg("tcsetpgrp");
1432 #endif
1433
1434         /* return exit status if called with "-c" */
1435         if (input == NULL && WIFEXITED(status))
1436                 return WEXITSTATUS(status);
1437
1438         return 0;
1439 }
1440
1441 #if ENABLE_FEATURE_CLEAN_UP
1442 static void free_memory(void)
1443 {
1444         free(cwd);
1445
1446         if (job_list.fg && !job_list.fg->running_progs) {
1447                 remove_job(&job_list, job_list.fg);
1448         }
1449 }
1450 #else
1451 void free_memory(void);
1452 #endif
1453
1454 #if ENABLE_LASH_JOB_CONTROL
1455 /* Make sure we have a controlling tty.  If we get started under a job
1456  * aware app (like bash for example), make sure we are now in charge so
1457  * we don't fight over who gets the foreground */
1458 static void setup_job_control(void)
1459 {
1460         int status;
1461         pid_t shell_pgrp;
1462
1463         /* Loop until we are in the foreground.  */
1464         while ((status = tcgetpgrp(shell_terminal)) >= 0) {
1465                 shell_pgrp = getpgrp();
1466                 if (status == shell_pgrp) {
1467                         break;
1468                 }
1469                 kill(- shell_pgrp, SIGTTIN);
1470         }
1471
1472         /* Ignore interactive and job-control signals.  */
1473         signal(SIGINT, SIG_IGN);
1474         signal(SIGQUIT, SIG_IGN);
1475         signal(SIGTSTP, SIG_IGN);
1476         signal(SIGTTIN, SIG_IGN);
1477         signal(SIGTTOU, SIG_IGN);
1478         signal(SIGCHLD, SIG_IGN);
1479
1480         /* Put ourselves in our own process group.  */
1481         setsid();
1482         shell_pgrp = getpid();
1483         setpgid(shell_pgrp, shell_pgrp);
1484
1485         /* Grab control of the terminal.  */
1486         tcsetpgrp(shell_terminal, shell_pgrp);
1487 }
1488 #else
1489 static inline void setup_job_control(void)
1490 {
1491 }
1492 #endif
1493
1494 int lash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1495 int lash_main(int argc, char **argv)
1496 {
1497         unsigned opt;
1498         FILE *input = stdin;
1499
1500         global_argc = argc;
1501         global_argv = argv;
1502
1503 #if ENABLE_FEATURE_EDITING
1504         line_input_state = new_line_input_t(FOR_SHELL);
1505 #endif
1506
1507         /* These variables need re-initializing when recursing */
1508         last_jobid = 0;
1509         close_me_list = NULL;
1510         job_list.head = NULL;
1511         job_list.fg = NULL;
1512         last_return_code = 1;
1513
1514         if (global_argv[0] && global_argv[0][0] == '-') {
1515                 FILE *prof_input;
1516                 prof_input = fopen("/etc/profile", "r");
1517                 if (prof_input) {
1518                         llist_add_to(&close_me_list, (void *)(long)fileno(prof_input));
1519                         /* Now run the file */
1520                         busy_loop(prof_input);
1521                         fclose_if_not_stdin(prof_input);
1522                         llist_pop(&close_me_list);
1523                 }
1524         }
1525
1526         opt = getopt32(argv, "+ic:", &local_pending_command);
1527 #define LASH_OPT_i (1<<0)
1528 #define LASH_OPT_c (1<<1)
1529         if (opt & LASH_OPT_c) {
1530                 input = NULL;
1531                 optind++;
1532                 global_argv += optind;
1533         }
1534         /* A shell is interactive if the `-i' flag was given, or if all of
1535          * the following conditions are met:
1536          *        no -c command
1537          *    no arguments remaining or the -s flag given
1538          *    standard input is a terminal
1539          *    standard output is a terminal
1540          *    Refer to Posix.2, the description of the `sh' utility. */
1541         if (global_argv[optind] == NULL && input == stdin
1542          && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)
1543         ) {
1544                 opt |= LASH_OPT_i;
1545         }
1546         setup_job_control();
1547         if (opt & LASH_OPT_i) {
1548                 /* Looks like they want an interactive shell */
1549                 if (!ENABLE_FEATURE_SH_EXTRA_QUIET) {
1550                         printf("\n\n%s built-in shell (lash)\n"
1551                                         "Enter 'help' for a list of built-in commands.\n\n",
1552                                         bb_banner);
1553                 }
1554         } else if (!local_pending_command && global_argv[optind]) {
1555                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1556                 input = xfopen(global_argv[optind], "r");
1557                 /* be lazy, never mark this closed */
1558                 llist_add_to(&close_me_list, (void *)(long)fileno(input));
1559         }
1560
1561         /* initialize the cwd -- this is never freed...*/
1562         update_cwd();
1563
1564         if (ENABLE_FEATURE_CLEAN_UP) atexit(free_memory);
1565
1566         if (ENABLE_FEATURE_EDITING) cmdedit_set_initial_prompt();
1567         else PS1 = NULL;
1568
1569         return busy_loop(input);
1570 }