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