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