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