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