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