107ce88f6221379a69d439140d3dbf4943471c2b
[platform/upstream/busybox.git] / 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) 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 UNUSED_PARAM *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 UNUSED_PARAM *dummy)
312 {
313         const struct built_in_command *x;
314
315         printf(
316                 "Built-in commands:\n"
317                 "------------------\n");
318         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
319                 if (x->descr == NULL)
320                         continue;
321                 printf("%s\t%s\n", x->cmd, x->descr);
322         }
323         bb_putchar('\n');
324         return EXIT_SUCCESS;
325 }
326
327 /* built-in 'jobs' handler */
328 static int builtin_jobs(struct child_prog *child)
329 {
330         struct job *job;
331         const char *status_string;
332
333         for (job = child->family->job_list->head; job; job = job->next) {
334                 if (job->running_progs == job->stopped_progs)
335                         status_string = "Stopped";
336                 else
337                         status_string = "Running";
338
339                 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
340         }
341         return EXIT_SUCCESS;
342 }
343
344
345 /* built-in 'pwd' handler */
346 static int builtin_pwd(struct child_prog UNUSED_PARAM *dummy)
347 {
348         update_cwd();
349         puts(cwd);
350         return EXIT_SUCCESS;
351 }
352
353 /* built-in 'export VAR=value' handler */
354 static int builtin_export(struct child_prog *child)
355 {
356         int res;
357         char *v = child->argv[1];
358
359         if (v == NULL) {
360                 char **e;
361                 for (e = environ; *e; e++) {
362                         puts(*e);
363                 }
364                 return 0;
365         }
366         res = putenv(v);
367         if (res)
368                 bb_perror_msg("export");
369 #if ENABLE_FEATURE_EDITING_FANCY_PROMPT
370         if (strncmp(v, "PS1=", 4) == 0)
371                 PS1 = getenv("PS1");
372 #endif
373
374 #if ENABLE_LOCALE_SUPPORT
375         // TODO: why getenv? "" would be just as good...
376         if (strncmp(v, "LC_ALL=", 7) == 0)
377                 setlocale(LC_ALL, getenv("LC_ALL"));
378         if (strncmp(v, "LC_CTYPE=", 9) == 0)
379                 setlocale(LC_CTYPE, getenv("LC_CTYPE"));
380 #endif
381
382         return res;
383 }
384
385 /* built-in 'read VAR' handler */
386 static int builtin_read(struct child_prog *child)
387 {
388         int res = 0, len;
389         char *s;
390         char string[MAX_READ];
391
392         if (child->argv[1]) {
393                 /* argument (VAR) given: put "VAR=" into buffer */
394                 safe_strncpy(string, child->argv[1], MAX_READ-1);
395                 len = strlen(string);
396                 string[len++] = '=';
397                 string[len]   = '\0';
398                 fgets(&string[len], sizeof(string) - len, stdin);       /* read string */
399                 res = strlen(string);
400                 if (res > len)
401                         string[--res] = '\0';   /* chomp trailing newline */
402                 /*
403                 ** string should now contain "VAR=<value>"
404                 ** copy it (putenv() won't do that, so we must make sure
405                 ** the string resides in a static buffer!)
406                 */
407                 res = -1;
408                 s = strdup(string);
409                 if (s)
410                         res = putenv(s);
411                 if (res)
412                         bb_perror_msg("read");
413         } else
414                 fgets(string, sizeof(string), stdin);
415
416         return res;
417 }
418
419 /* Built-in '.' handler (read-in and execute commands from file) */
420 static int builtin_source(struct child_prog *child)
421 {
422         FILE *input;
423         int status;
424
425         input = fopen_or_warn(child->argv[1], "r");
426         if (!input) {
427                 return EXIT_FAILURE;
428         }
429
430         llist_add_to(&close_me_list, (void *)(long)fileno(input));
431         /* Now run the file */
432         status = busy_loop(input);
433         fclose(input);
434         llist_pop(&close_me_list);
435         return status;
436 }
437
438 /* built-in 'unset VAR' handler */
439 static int builtin_unset(struct child_prog *child)
440 {
441         if (child->argv[1] == NULL) {
442                 printf(bb_msg_requires_arg, "unset");
443                 return EXIT_FAILURE;
444         }
445         unsetenv(child->argv[1]);
446         return EXIT_SUCCESS;
447 }
448
449 #if ENABLE_LASH_JOB_CONTROL
450 /* free up all memory from a job */
451 static void free_job(struct job *cmd)
452 {
453         int i;
454         struct jobset *keep;
455
456         for (i = 0; i < cmd->num_progs; i++) {
457                 free(cmd->progs[i].argv);
458 #if ENABLE_LASH_PIPE_N_REDIRECTS
459                 free(cmd->progs[i].redirects);
460 #endif
461         }
462         free(cmd->progs);
463         free(cmd->text);
464         free(cmd->cmdbuf);
465         keep = cmd->job_list;
466         memset(cmd, 0, sizeof(struct job));
467         cmd->job_list = keep;
468 }
469
470 /* remove a job from a jobset */
471 static void remove_job(struct jobset *j_list, struct job *job)
472 {
473         struct job *prevjob;
474
475         free_job(job);
476         if (job == j_list->head) {
477                 j_list->head = job->next;
478         } else {
479                 prevjob = j_list->head;
480                 while (prevjob->next != job)
481                         prevjob = prevjob->next;
482                 prevjob->next = job->next;
483         }
484
485         if (j_list->head)
486                 last_jobid = j_list->head->jobid;
487         else
488                 last_jobid = 0;
489
490         free(job);
491 }
492
493 /* Checks to see if any background processes have exited -- if they
494    have, figure out why and see if a job has completed */
495 static void checkjobs(struct jobset *j_list)
496 {
497         struct job *job;
498         pid_t childpid;
499         int status;
500         int prognum = 0;
501
502         while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
503                 for (job = j_list->head; job; job = job->next) {
504                         prognum = 0;
505                         while (prognum < job->num_progs &&
506                                    job->progs[prognum].pid != childpid) prognum++;
507                         if (prognum < job->num_progs)
508                                 break;
509                 }
510
511                 /* This happens on backticked commands */
512                 if (job == NULL)
513                         return;
514
515                 if (WIFEXITED(status) || WIFSIGNALED(status)) {
516                         /* child exited */
517                         job->running_progs--;
518                         job->progs[prognum].pid = 0;
519
520                         if (!job->running_progs) {
521                                 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
522                                 last_jobid = 0;
523                                 remove_job(j_list, job);
524                         }
525                 } else {
526                         /* child stopped */
527                         job->stopped_progs++;
528                         job->progs[prognum].is_stopped = 1;
529                 }
530         }
531
532         if (childpid == -1 && errno != ECHILD)
533                 bb_perror_msg("waitpid");
534 }
535 #else
536 static void checkjobs(struct jobset *j_list)
537 {
538 }
539 static void free_job(struct job *cmd)
540 {
541 }
542 static void remove_job(struct jobset *j_list, struct job *job)
543 {
544 }
545 #endif
546
547 #if ENABLE_LASH_PIPE_N_REDIRECTS
548 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
549  * and stderr if they are redirected. */
550 static int setup_redirects(struct child_prog *prog, int squirrel[])
551 {
552         int i;
553         int openfd;
554         int mode = O_RDONLY;
555         struct redir_struct *redir = prog->redirects;
556
557         for (i = 0; i < prog->num_redirects; i++, redir++) {
558                 switch (redir->type) {
559                 case REDIRECT_INPUT:
560                         mode = O_RDONLY;
561                         break;
562                 case REDIRECT_OVERWRITE:
563                         mode = O_WRONLY | O_CREAT | O_TRUNC;
564                         break;
565                 case REDIRECT_APPEND:
566                         mode = O_WRONLY | O_CREAT | O_APPEND;
567                         break;
568                 }
569
570                 openfd = open_or_warn(redir->filename, mode);
571                 if (openfd < 0) {
572                         /* this could get lost if stderr has been redirected, but
573                            bash and ash both lose it as well (though zsh doesn't!) */
574                         return 1;
575                 }
576
577                 if (openfd != redir->fd) {
578                         if (squirrel && redir->fd < 3) {
579                                 squirrel[redir->fd] = dup(redir->fd);
580                                 close_on_exec_on(squirrel[redir->fd]);
581                         }
582                         dup2(openfd, redir->fd);
583                         close(openfd);
584                 }
585         }
586
587         return 0;
588 }
589
590 static void restore_redirects(int squirrel[])
591 {
592         int i, fd;
593         for (i = 0; i < 3; i++) {
594                 fd = squirrel[i];
595                 if (fd != -1) {
596                         /* No error checking.  I sure wouldn't know what
597                          * to do with an error if I found one! */
598                         dup2(fd, i);
599                         close(fd);
600                 }
601         }
602 }
603 #else
604 static inline int setup_redirects(struct child_prog *prog, int squirrel[])
605 {
606         return 0;
607 }
608 static inline void restore_redirects(int squirrel[])
609 {
610 }
611 #endif
612
613 static inline void cmdedit_set_initial_prompt(void)
614 {
615 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
616         PS1 = NULL;
617 #else
618         PS1 = getenv("PS1");
619         if (PS1 == 0)
620                 PS1 = "\\w \\$ ";
621 #endif
622 }
623
624 static inline const char* setup_prompt_string(void)
625 {
626 #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT
627         /* Set up the prompt */
628         if (shell_context == 0) {
629                 char *ns;
630                 free((char*)PS1);
631                 ns = xmalloc(strlen(cwd)+4);
632                 sprintf(ns, "%s %c ", cwd, (geteuid() != 0) ? '$': '#');
633                 PS1 = ns;
634                 return ns;
635         } else {
636                 return PS2;
637         }
638 #else
639         return (shell_context == 0)? PS1 : PS2;
640 #endif
641 }
642
643 #if ENABLE_FEATURE_EDITING
644 static line_input_t *line_input_state;
645 #endif
646
647 static int get_command_bufsiz(FILE *source, char *command)
648 {
649         const char *prompt_str;
650
651         if (source == NULL) {
652                 if (local_pending_command) {
653                         /* a command specified (-c option): return it & mark it done */
654                         strncpy(command, local_pending_command, BUFSIZ);
655                         local_pending_command = NULL;
656                         return 0;
657                 }
658                 return 1;
659         }
660
661         if (source == stdin) {
662                 prompt_str = setup_prompt_string();
663
664 #if ENABLE_FEATURE_EDITING
665                 /*
666                 ** enable command line editing only while a command line
667                 ** is actually being read; otherwise, we'll end up bequeathing
668                 ** atexit() handlers and other unwanted stuff to our
669                 ** child processes (rob@sysgo.de)
670                 */
671                 read_line_input(prompt_str, command, BUFSIZ, line_input_state);
672                 return 0;
673 #else
674                 fputs(prompt_str, stdout);
675 #endif
676         }
677
678         if (!fgets(command, BUFSIZ - 2, source)) {
679                 if (source == stdin)
680                         bb_putchar('\n');
681                 return 1;
682         }
683
684         return 0;
685 }
686
687 static char * strsep_space(char *string, int * ix)
688 {
689         /* Short circuit the trivial case */
690         if (!string || ! string[*ix])
691                 return NULL;
692
693         /* Find the end of the token. */
694         while (string[*ix] && !isspace(string[*ix]) ) {
695                 (*ix)++;
696         }
697
698         /* Find the end of any whitespace trailing behind
699          * the token and let that be part of the token */
700         while (string[*ix] && isspace(string[*ix])) {
701                 (*ix)++;
702         }
703
704         if (!*ix) {
705                 /* Nothing useful was found */
706                 return NULL;
707         }
708
709         return xstrndup(string, *ix);
710 }
711
712 static int expand_arguments(char *command)
713 {
714         static const char out_of_space[] ALIGN1 = "out of space during expansion";
715
716         int total_length = 0, length, i, retval, ix = 0;
717         expand_t expand_result;
718         char *tmpcmd, *cmd, *cmd_copy;
719         char *src, *dst, *var;
720         int flags = GLOB_NOCHECK
721 #ifdef GLOB_BRACE
722                 | GLOB_BRACE
723 #endif
724 #ifdef GLOB_TILDE
725                 | GLOB_TILDE
726 #endif
727                 ;
728
729         /* get rid of the terminating \n */
730         chomp(command);
731
732         /* Fix up escape sequences to be the Real Thing(tm) */
733         while (command && command[ix]) {
734                 if (command[ix] == '\\') {
735                         const char *tmp = command+ix+1;
736                         command[ix] = bb_process_escape_sequence(  &tmp );
737                         memmove(command+ix + 1, tmp, strlen(tmp)+1);
738                 }
739                 ix++;
740         }
741         /* Use glob and then fixup environment variables and such */
742
743         /* It turns out that glob is very stupid.  We have to feed it one word at a
744          * time since it can't cope with a full string.  Here we convert command
745          * (char*) into cmd (char**, one word per string) */
746
747         /* We need a clean copy, so strsep can mess up the copy while
748          * we write stuff into the original (in a minute) */
749         cmd = cmd_copy = xstrdup(command);
750         *command = '\0';
751         for (ix = 0, tmpcmd = cmd;
752                         (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix = 0) {
753                 if (*tmpcmd == '\0')
754                         break;
755                 /* we need to trim() the result for glob! */
756                 trim(tmpcmd);
757                 retval = glob(tmpcmd, flags, NULL, &expand_result);
758                 free(tmpcmd); /* Free mem allocated by strsep_space */
759                 if (retval == GLOB_NOSPACE) {
760                         /* Mem may have been allocated... */
761                         globfree(&expand_result);
762                         bb_error_msg(out_of_space);
763                         return FALSE;
764                 } else if (retval != 0) {
765                         /* Some other error.  GLOB_NOMATCH shouldn't
766                          * happen because of the GLOB_NOCHECK flag in
767                          * the glob call. */
768                         bb_error_msg("syntax error");
769                         return FALSE;
770                 } else {
771                         /* Convert from char** (one word per string) to a simple char*,
772                          * but don't overflow command which is BUFSIZ in length */
773                         for (i = 0; i < expand_result.gl_pathc; i++) {
774                                 length = strlen(expand_result.gl_pathv[i]);
775                                 if (total_length+length+1 >= BUFSIZ) {
776                                         bb_error_msg(out_of_space);
777                                         return FALSE;
778                                 }
779                                 strcat(command+total_length, " ");
780                                 total_length += 1;
781                                 strcat(command+total_length, expand_result.gl_pathv[i]);
782                                 total_length += length;
783                         }
784                         globfree(&expand_result);
785                 }
786         }
787         free(cmd_copy);
788         trim(command);
789
790         /* Now do the shell variable substitutions which
791          * wordexp can't do for us, namely $? and $! */
792         src = command;
793         while ((dst = strchr(src,'$')) != NULL) {
794                 var = NULL;
795                 switch (*(dst+1)) {
796                         case '?':
797                                 var = itoa(last_return_code);
798                                 break;
799                         case '!':
800                                 if (last_bg_pid == -1)
801                                         *var = '\0';
802                                 else
803                                         var = itoa(last_bg_pid);
804                                 break;
805                                 /* Everything else like $$, $#, $[0-9], etc. should all be
806                                  * expanded by wordexp(), so we can in theory skip that stuff
807                                  * here, but just to be on the safe side (i.e., since uClibc
808                                  * wordexp doesn't do this stuff yet), lets leave it in for
809                                  * now. */
810                         case '$':
811                                 var = itoa(getpid());
812                                 break;
813                         case '#':
814                                 var = itoa(global_argc - 1);
815                                 break;
816                         case '0':case '1':case '2':case '3':case '4':
817                         case '5':case '6':case '7':case '8':case '9':
818                                 {
819                                         int ixx = *(dst+1)-48+1;
820                                         if (ixx >= global_argc) {
821                                                 var = '\0';
822                                         } else {
823                                                 var = global_argv[ixx];
824                                         }
825                                 }
826                                 break;
827
828                 }
829                 if (var) {
830                         /* a single character construction was found, and
831                          * already handled in the case statement */
832                         src = dst + 2;
833                 } else {
834                         /* Looks like an environment variable */
835                         char delim_hold;
836                         int num_skip_chars = 0;
837                         int dstlen = strlen(dst);
838                         /* Is this a ${foo} type variable? */
839                         if (dstlen >= 2 && *(dst+1) == '{') {
840                                 src = strchr(dst+1, '}');
841                                 num_skip_chars = 1;
842                         } else {
843                                 src = dst + 1;
844                                 while (isalnum(*src) || *src == '_') src++;
845                         }
846                         if (src == NULL) {
847                                 src = dst+dstlen;
848                         }
849                         delim_hold = *src;
850                         *src = '\0';  /* temporary */
851                         var = getenv(dst + 1 + num_skip_chars);
852                         *src = delim_hold;
853                         src += num_skip_chars;
854                 }
855                 if (var == NULL) {
856                         /* Seems we got an un-expandable variable.  So delete it. */
857                         var = (char*)"";
858                 }
859                 {
860                         int subst_len = strlen(var);
861                         int trail_len = strlen(src);
862                         if (dst+subst_len+trail_len >= command+BUFSIZ) {
863                                 bb_error_msg(out_of_space);
864                                 return FALSE;
865                         }
866                         /* Move stuff to the end of the string to accommodate
867                          * filling the created gap with the new stuff */
868                         memmove(dst+subst_len, src, trail_len+1);
869                         /* Now copy in the new stuff */
870                         memcpy(dst, var, subst_len);
871                         src = dst+subst_len;
872                 }
873         }
874
875         return TRUE;
876 }
877
878 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
879    line). If a valid command is found, command_ptr is set to point to
880    the beginning of the next command (if the original command had more
881    then one job associated with it) or NULL if no more commands are
882    present. */
883 static int parse_command(char **command_ptr, struct job *job, int *inbg)
884 {
885         char *command;
886         char *return_command = NULL;
887         char *src, *buf;
888         int argc_l;
889         int flag;
890         int argv_alloced;
891         char quote = '\0';
892         struct child_prog *prog;
893 #if ENABLE_LASH_PIPE_N_REDIRECTS
894         int i;
895         char *chptr;
896 #endif
897
898         /* skip leading white space */
899         *command_ptr = skip_whitespace(*command_ptr);
900
901         /* this handles empty lines or leading '#' characters */
902         if (!**command_ptr || (**command_ptr == '#')) {
903                 job->num_progs = 0;
904                 return 0;
905         }
906
907         *inbg = 0;
908         job->num_progs = 1;
909         job->progs = xmalloc(sizeof(*job->progs));
910
911         /* We set the argv elements to point inside of this string. The
912            memory is freed by free_job(). Allocate twice the original
913            length in case we need to quote every single character.
914
915            Getting clean memory relieves us of the task of NULL
916            terminating things and makes the rest of this look a bit
917            cleaner (though it is, admittedly, a tad less efficient) */
918         job->cmdbuf = command = xzalloc(2*strlen(*command_ptr) + 1);
919         job->text = NULL;
920
921         prog = job->progs;
922         prog->num_redirects = 0;
923         prog->is_stopped = 0;
924         prog->family = job;
925 #if ENABLE_LASH_PIPE_N_REDIRECTS
926         prog->redirects = NULL;
927 #endif
928
929         argv_alloced = 5;
930         prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
931         prog->argv[0] = job->cmdbuf;
932
933         flag = argc_l = 0;
934         buf = command;
935         src = *command_ptr;
936         while (*src && !(flag & LASH_OPT_DONE)) {
937                 if (quote == *src) {
938                         quote = '\0';
939                 } else if (quote) {
940                         if (*src == '\\') {
941                                 src++;
942                                 if (!*src) {
943                                         bb_error_msg("character expected after \\");
944                                         free_job(job);
945                                         return 1;
946                                 }
947
948                                 /* in shell, "\'" should yield \' */
949                                 if (*src != quote) {
950                                         *buf++ = '\\';
951                                         *buf++ = '\\';
952                                 }
953                         } else if (*src == '*' || *src == '?' || *src == '[' ||
954                                            *src == ']') *buf++ = '\\';
955                         *buf++ = *src;
956                 } else if (isspace(*src)) {
957                         if (*prog->argv[argc_l] || (flag & LASH_OPT_SAW_QUOTE)) {
958                                 buf++, argc_l++;
959                                 /* +1 here leaves room for the NULL which ends argv */
960                                 if ((argc_l + 1) == argv_alloced) {
961                                         argv_alloced += 5;
962                                         prog->argv = xrealloc(prog->argv,
963                                                         sizeof(*prog->argv) * argv_alloced);
964                                 }
965                                 prog->argv[argc_l] = buf;
966                                 flag ^= LASH_OPT_SAW_QUOTE;
967                         }
968                 } else
969                         switch (*src) {
970                         case '"':
971                         case '\'':
972                                 quote = *src;
973                                 flag |= LASH_OPT_SAW_QUOTE;
974                                 break;
975
976                         case '#':                       /* comment */
977                                 if (*(src-1)== '$')
978                                         *buf++ = *src;
979                                 else
980                                         flag |= LASH_OPT_DONE;
981                                 break;
982
983 #if ENABLE_LASH_PIPE_N_REDIRECTS
984                         case '>':                       /* redirects */
985                         case '<':
986                                 i = prog->num_redirects++;
987                                 prog->redirects = xrealloc(prog->redirects,
988                                                 sizeof(*prog->redirects) * (i + 1));
989
990                                 prog->redirects[i].fd = -1;
991                                 if (buf != prog->argv[argc_l]) {
992                                         /* the stuff before this character may be the file number
993                                            being redirected */
994                                         prog->redirects[i].fd =
995                                                 strtol(prog->argv[argc_l], &chptr, 10);
996
997                                         if (*chptr && *prog->argv[argc_l]) {
998                                                 buf++, argc_l++;
999                                                 prog->argv[argc_l] = buf;
1000                                         }
1001                                 }
1002
1003                                 if (prog->redirects[i].fd == -1) {
1004                                         if (*src == '>')
1005                                                 prog->redirects[i].fd = 1;
1006                                         else
1007                                                 prog->redirects[i].fd = 0;
1008                                 }
1009
1010                                 if (*src++ == '>') {
1011                                         if (*src == '>')
1012                                                 prog->redirects[i].type =
1013                                                         REDIRECT_APPEND, src++;
1014                                         else
1015                                                 prog->redirects[i].type = REDIRECT_OVERWRITE;
1016                                 } else {
1017                                         prog->redirects[i].type = REDIRECT_INPUT;
1018                                 }
1019
1020                                 /* This isn't POSIX sh compliant. Oh well. */
1021                                 chptr = src;
1022                                 chptr = skip_whitespace(chptr);
1023
1024                                 if (!*chptr) {
1025                                         bb_error_msg("file name expected after %c", *(src-1));
1026                                         free_job(job);
1027                                         job->num_progs = 0;
1028                                         return 1;
1029                                 }
1030
1031                                 prog->redirects[i].filename = buf;
1032                                 while (*chptr && !isspace(*chptr))
1033                                         *buf++ = *chptr++;
1034
1035                                 src = chptr - 1;        /* we src++ later */
1036                                 prog->argv[argc_l] = ++buf;
1037                                 break;
1038
1039                         case '|':                       /* pipe */
1040                                 /* finish this command */
1041                                 if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE)
1042                                         argc_l++;
1043                                 if (!argc_l) {
1044                                         goto empty_command_in_pipe;
1045                                 }
1046                                 prog->argv[argc_l] = NULL;
1047
1048                                 /* and start the next */
1049                                 job->num_progs++;
1050                                 job->progs = xrealloc(job->progs,
1051                                                 sizeof(*job->progs) * job->num_progs);
1052                                 prog = job->progs + (job->num_progs - 1);
1053                                 prog->num_redirects = 0;
1054                                 prog->redirects = NULL;
1055                                 prog->is_stopped = 0;
1056                                 prog->family = job;
1057                                 argc_l = 0;
1058
1059                                 argv_alloced = 5;
1060                                 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1061                                 prog->argv[0] = ++buf;
1062
1063                                 src++;
1064                                 src = skip_whitespace(src);
1065
1066                                 if (!*src) {
1067 empty_command_in_pipe:
1068                                         bb_error_msg("empty command in pipe");
1069                                         free_job(job);
1070                                         job->num_progs = 0;
1071                                         return 1;
1072                                 }
1073                                 src--;                  /* we'll ++ it at the end of the loop */
1074
1075                                 break;
1076 #endif
1077
1078 #if ENABLE_LASH_JOB_CONTROL
1079                         case '&':                       /* background */
1080                                 *inbg = 1;
1081                                 /* fallthrough */
1082 #endif
1083                         case ';':                       /* multiple commands */
1084                                 flag |= LASH_OPT_DONE;
1085                                 return_command = *command_ptr + (src - *command_ptr) + 1;
1086                                 break;
1087
1088                         case '\\':
1089                                 src++;
1090                                 if (!*src) {
1091                                         bb_error_msg("character expected after \\");
1092                                         free_job(job);
1093                                         return 1;
1094                                 }
1095                                 if (*src == '*' || *src == '[' || *src == ']'
1096                                         || *src == '?') *buf++ = '\\';
1097                                 /* fallthrough */
1098                         default:
1099                                 *buf++ = *src;
1100                         }
1101
1102                 src++;
1103         }
1104
1105         if (*prog->argv[argc_l] || flag & LASH_OPT_SAW_QUOTE) {
1106                 argc_l++;
1107         }
1108         if (!argc_l) {
1109                 free_job(job);
1110                 return 0;
1111         }
1112         prog->argv[argc_l] = NULL;
1113
1114         if (!return_command) {
1115                 job->text = xstrdup(*command_ptr);
1116         } else {
1117                 /* This leaves any trailing spaces, which is a bit sloppy */
1118                 job->text = xstrndup(*command_ptr, return_command - *command_ptr);
1119         }
1120
1121         *command_ptr = return_command;
1122
1123         return 0;
1124 }
1125
1126 /* Run the child_prog, no matter what kind of command it uses.
1127  */
1128 static int pseudo_exec(struct child_prog *child)
1129 {
1130         const struct built_in_command *x;
1131
1132         /* Check if the command matches any of the non-forking builtins.
1133          * Depending on context, this might be redundant.  But it's
1134          * easier to waste a few CPU cycles than it is to figure out
1135          * if this is one of those cases.
1136          */
1137         /* Check if the command matches any of the forking builtins. */
1138         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
1139                 if (strcmp(child->argv[0], x->cmd) == 0) {
1140                         _exit(x->function(child));
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_nostrip().  This way explicit
1148          * (with 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_simple_perror_msg(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                         xpipe(pipefds);
1226                         nextout = pipefds[1];
1227                 } else if (outpipe[1] != -1) {
1228                         nextout = outpipe[1];
1229                 }
1230
1231                 /* Check if the command matches any non-forking builtins,
1232                  * but only if this is a simple command.
1233                  * Non-forking builtins within pipes have to fork anyway,
1234                  * and are handled in pseudo_exec.  "echo foo | read bar"
1235                  * is doomed to failure, and doesn't work on bash, either.
1236                  */
1237                 if (newjob->num_progs == 1) {
1238                         int rcode;
1239                         int squirrel[] = {-1, -1, -1};
1240
1241                         /* Check if the command sets an environment variable. */
1242                         if (strchr(child->argv[0], '=') != NULL) {
1243                                 child->argv[1] = child->argv[0];
1244                                 return builtin_export(child);
1245                         }
1246
1247                         for (x = bltins; x <= &VEC_LAST(bltins); x++) {
1248                                 if (strcmp(child->argv[0], x->cmd) == 0) {
1249                                         setup_redirects(child, squirrel);
1250                                         rcode = x->function(child);
1251                                         restore_redirects(squirrel);
1252                                         return rcode;
1253                                 }
1254                         }
1255 #if ENABLE_FEATURE_SH_STANDALONE
1256                         {
1257                                 int a = find_applet_by_name(child->argv[i]);
1258                                 if (a >= 0 && APPLET_IS_NOFORK(a)) {
1259                                         setup_redirects(child, squirrel);
1260                                         rcode = run_nofork_applet(a, child->argv + i);
1261                                         restore_redirects(squirrel);
1262                                         return rcode;
1263                                 }
1264                         }
1265 #endif
1266                 }
1267
1268 #if BB_MMU
1269                 child->pid = fork();
1270 #else
1271                 child->pid = vfork();
1272 #endif
1273                 if (!child->pid) {
1274                         /* Set the handling for job control signals back to the default.  */
1275                         signal(SIGINT, SIG_DFL);
1276                         signal(SIGQUIT, SIG_DFL);
1277                         signal(SIGTSTP, SIG_DFL);
1278                         signal(SIGTTIN, SIG_DFL);
1279                         signal(SIGTTOU, SIG_DFL);
1280                         signal(SIGCHLD, SIG_DFL);
1281
1282                         /* Close all open filehandles. */
1283                         while (close_me_list)
1284                                 close((long)llist_pop(&close_me_list));
1285
1286                         if (outpipe[1] != -1) {
1287                                 close(outpipe[0]);
1288                         }
1289                         if (nextin != 0) {
1290                                 dup2(nextin, 0);
1291                                 close(nextin);
1292                         }
1293
1294                         if (nextout != 1) {
1295                                 dup2(nextout, 1);
1296                                 dup2(nextout, 2);  /* Really? */
1297                                 close(nextout);
1298                                 close(pipefds[0]);
1299                         }
1300
1301                         /* explicit redirects override pipes */
1302                         setup_redirects(child,NULL);
1303
1304                         pseudo_exec(child);
1305                 }
1306                 if (outpipe[1] != -1) {
1307                         close(outpipe[1]);
1308                 }
1309
1310                 /* put our child in the process group whose leader is the
1311                    first process in this pipe */
1312                 setpgid(child->pid, newjob->progs[0].pid);
1313                 if (nextin != 0)
1314                         close(nextin);
1315                 if (nextout != 1)
1316                         close(nextout);
1317
1318                 /* If there isn't another process, nextin is garbage
1319                    but it doesn't matter */
1320                 nextin = pipefds[0];
1321         }
1322
1323         newjob->pgrp = newjob->progs[0].pid;
1324
1325         insert_job(newjob, inbg);
1326
1327         return 0;
1328 }
1329
1330 static int busy_loop(FILE *input)
1331 {
1332         char *command;
1333         char *next_command = NULL;
1334         struct job newjob;
1335         int i;
1336         int inbg = 0;
1337         int status;
1338 #if ENABLE_LASH_JOB_CONTROL
1339         pid_t  parent_pgrp;
1340         /* save current owner of TTY so we can restore it on exit */
1341         parent_pgrp = tcgetpgrp(shell_terminal);
1342 #endif
1343         newjob.job_list = &job_list;
1344         newjob.job_context = DEFAULT_CONTEXT;
1345
1346         command = xzalloc(BUFSIZ);
1347
1348         while (1) {
1349                 if (!job_list.fg) {
1350                         /* no job is in the foreground */
1351
1352                         /* see if any background processes have exited */
1353                         checkjobs(&job_list);
1354
1355                         if (!next_command) {
1356                                 if (get_command_bufsiz(input, command))
1357                                         break;
1358                                 next_command = command;
1359                         }
1360
1361                         if (!expand_arguments(next_command)) {
1362                                 free(command);
1363                                 command = xzalloc(BUFSIZ);
1364                                 next_command = NULL;
1365                                 continue;
1366                         }
1367
1368                         if (!parse_command(&next_command, &newjob, &inbg) &&
1369                                 newjob.num_progs) {
1370                                 int pipefds[2] = { -1, -1 };
1371                                 debug_printf("job=%p fed to run_command by busy_loop()'\n",
1372                                                 &newjob);
1373                                 run_command(&newjob, inbg, pipefds);
1374                         }
1375                         else {
1376                                 free(command);
1377                                 command = xzalloc(BUFSIZ);
1378                                 next_command = NULL;
1379                         }
1380                 } else {
1381                         /* a job is running in the foreground; wait for it */
1382                         i = 0;
1383                         while (!job_list.fg->progs[i].pid ||
1384                                    job_list.fg->progs[i].is_stopped == 1) i++;
1385
1386                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED) < 0) {
1387                                 if (errno != ECHILD) {
1388                                         bb_perror_msg_and_die("waitpid(%d)", job_list.fg->progs[i].pid);
1389                                 }
1390                         }
1391
1392                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1393                                 /* the child exited */
1394                                 job_list.fg->running_progs--;
1395                                 job_list.fg->progs[i].pid = 0;
1396
1397                                 last_return_code = WEXITSTATUS(status);
1398
1399                                 if (!job_list.fg->running_progs) {
1400                                         /* child exited */
1401                                         remove_job(&job_list, job_list.fg);
1402                                         job_list.fg = NULL;
1403                                 }
1404                         }
1405 #if ENABLE_LASH_JOB_CONTROL
1406                         else {
1407                                 /* the child was stopped */
1408                                 job_list.fg->stopped_progs++;
1409                                 job_list.fg->progs[i].is_stopped = 1;
1410
1411                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1412                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1413                                                    "Stopped", job_list.fg->text);
1414                                         job_list.fg = NULL;
1415                                 }
1416                         }
1417
1418                         if (!job_list.fg) {
1419                                 /* move the shell to the foreground */
1420                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1421                                 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
1422                                         bb_perror_msg("tcsetpgrp");
1423                         }
1424 #endif
1425                 }
1426         }
1427         free(command);
1428
1429 #if ENABLE_LASH_JOB_CONTROL
1430         /* return controlling TTY back to parent process group before exiting */
1431         if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
1432                 bb_perror_msg("tcsetpgrp");
1433 #endif
1434
1435         /* return exit status if called with "-c" */
1436         if (input == NULL && WIFEXITED(status))
1437                 return WEXITSTATUS(status);
1438
1439         return 0;
1440 }
1441
1442 #if ENABLE_FEATURE_CLEAN_UP
1443 static void free_memory(void)
1444 {
1445         free(cwd);
1446
1447         if (job_list.fg && !job_list.fg->running_progs) {
1448                 remove_job(&job_list, job_list.fg);
1449         }
1450 }
1451 #else
1452 void free_memory(void);
1453 #endif
1454
1455 #if ENABLE_LASH_JOB_CONTROL
1456 /* Make sure we have a controlling tty.  If we get started under a job
1457  * aware app (like bash for example), make sure we are now in charge so
1458  * we don't fight over who gets the foreground */
1459 static void setup_job_control(void)
1460 {
1461         int status;
1462         pid_t shell_pgrp;
1463
1464         /* Loop until we are in the foreground.  */
1465         while ((status = tcgetpgrp(shell_terminal)) >= 0) {
1466                 shell_pgrp = getpgrp();
1467                 if (status == shell_pgrp) {
1468                         break;
1469                 }
1470                 kill(- shell_pgrp, SIGTTIN);
1471         }
1472
1473         /* Ignore interactive and job-control signals.  */
1474         signal(SIGINT, SIG_IGN);
1475         signal(SIGQUIT, SIG_IGN);
1476         signal(SIGTSTP, SIG_IGN);
1477         signal(SIGTTIN, SIG_IGN);
1478         signal(SIGTTOU, SIG_IGN);
1479         signal(SIGCHLD, SIG_IGN);
1480
1481         /* Put ourselves in our own process group.  */
1482         setsid();
1483         shell_pgrp = getpid();
1484         setpgid(shell_pgrp, shell_pgrp);
1485
1486         /* Grab control of the terminal.  */
1487         tcsetpgrp(shell_terminal, shell_pgrp);
1488 }
1489 #else
1490 static inline void setup_job_control(void)
1491 {
1492 }
1493 #endif
1494
1495 int lash_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1496 int lash_main(int argc, char **argv)
1497 {
1498         unsigned opt;
1499         FILE *input = stdin;
1500
1501         global_argc = argc;
1502         global_argv = argv;
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 (global_argv[0] && global_argv[0][0] == '-') {
1516                 FILE *prof_input;
1517                 prof_input = fopen_for_read("/etc/profile");
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(argv, "+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                 global_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 (global_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 && global_argv[optind]) {
1556                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1557                 input = xfopen_for_read(global_argv[optind]);
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 }