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