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