Rework environment variable handling to use wordexp, per a suggestion from
[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 #if 0
963                                 /* Everything else like $$, $#, $[0-9], etcshould all be 
964                                  * expanded by wordexp(), so we can skip that stuff here */
965                                 case '$':
966                                 case '#':
967                                 case '0':case '1':case '2':case '3':case '4':
968                                 case '5':case '6':case '7':case '8':case '9':
969                                         break;
970 #endif  
971                         }
972                 }
973                 if (var) {
974                         int subst_len = strlen(var);
975                         char *next_dst;
976                         if ((next_dst=strpbrk(dst+1, " \t~`!$^&*()=|\\{}[];\"'<>?")) == NULL) {
977                                 next_dst = dst;
978                         }
979                         src = (char*)xrealloc(src, strlen(src) - strlen(next_dst)+strlen(var)+1);
980                         /* Move stuff to the end of the string to accommodate filling 
981                          * the created gap with the new stuff */
982                         memmove(dst+subst_len, next_dst+1, subst_len); 
983                         /* Now copy in the new stuff */
984                         strncpy(dst, var, subst_len);
985                 }
986                 src = dst;
987                 src++;
988         }
989
990
991
992
993 #endif  
994         return TRUE;
995 }
996
997 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
998    line). If a valid command is found, command_ptr is set to point to
999    the beginning of the next command (if the original command had more 
1000    then one job associated with it) or NULL if no more commands are 
1001    present. */
1002 static int parse_command(char **command_ptr, struct job *job, int *inbg)
1003 {
1004         char *command;
1005         char *return_command = NULL;
1006         char *src, *buf, *chptr;
1007         int argc_l = 0;
1008         int done = 0;
1009         int argv_alloced;
1010         int i;
1011         char quote = '\0';
1012         int count;
1013         struct child_prog *prog;
1014
1015         /* skip leading white space */
1016         while (**command_ptr && isspace(**command_ptr))
1017                 (*command_ptr)++;
1018
1019         /* this handles empty lines or leading '#' characters */
1020         if (!**command_ptr || (**command_ptr == '#')) {
1021                 job->num_progs=0;
1022                 return 0;
1023         }
1024
1025         *inbg = 0;
1026         job->num_progs = 1;
1027         job->progs = xmalloc(sizeof(*job->progs));
1028
1029         /* We set the argv elements to point inside of this string. The 
1030            memory is freed by free_job(). Allocate twice the original
1031            length in case we need to quote every single character.
1032
1033            Getting clean memory relieves us of the task of NULL 
1034            terminating things and makes the rest of this look a bit 
1035            cleaner (though it is, admittedly, a tad less efficient) */
1036         job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
1037         job->text = NULL;
1038
1039         prog = job->progs;
1040         prog->num_redirects = 0;
1041         prog->redirects = NULL;
1042         prog->is_stopped = 0;
1043         prog->family = job;
1044
1045         argv_alloced = 5;
1046         prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1047         prog->argv[0] = job->cmdbuf;
1048
1049         buf = command;
1050         src = *command_ptr;
1051         while (*src && !done) {
1052                 if (quote == *src) {
1053                         quote = '\0';
1054                 } else if (quote) {
1055                         if (*src == '\\') {
1056                                 src++;
1057                                 if (!*src) {
1058                                         error_msg("character expected after \\");
1059                                         free_job(job);
1060                                         return 1;
1061                                 }
1062
1063                                 /* in shell, "\'" should yield \' */
1064                                 if (*src != quote) {
1065                                         *buf++ = '\\';
1066                                         *buf++ = '\\';
1067                                 }
1068                         } else if (*src == '*' || *src == '?' || *src == '[' ||
1069                                            *src == ']') *buf++ = '\\';
1070                         *buf++ = *src;
1071                 } else if (isspace(*src)) {
1072                         if (*prog->argv[argc_l]) {
1073                                 buf++, argc_l++;
1074                                 /* +1 here leaves room for the NULL which ends argv */
1075                                 if ((argc_l + 1) == argv_alloced) {
1076                                         argv_alloced += 5;
1077                                         prog->argv = xrealloc(prog->argv,
1078                                                                                   sizeof(*prog->argv) *
1079                                                                                   argv_alloced);
1080                                 }
1081                                 prog->argv[argc_l] = buf;
1082                         }
1083                 } else
1084                         switch (*src) {
1085                         case '"':
1086                         case '\'':
1087                                 quote = *src;
1088                                 break;
1089
1090                         case '#':                       /* comment */
1091                                 if (*(src-1)== '$')
1092                                         *buf++ = *src;
1093                                 else
1094                                         done = 1;
1095                                 break;
1096
1097                         case '>':                       /* redirects */
1098                         case '<':
1099                                 i = prog->num_redirects++;
1100                                 prog->redirects = xrealloc(prog->redirects,
1101                                                                                           sizeof(*prog->redirects) *
1102                                                                                           (i + 1));
1103
1104                                 prog->redirects[i].fd = -1;
1105                                 if (buf != prog->argv[argc_l]) {
1106                                         /* the stuff before this character may be the file number 
1107                                            being redirected */
1108                                         prog->redirects[i].fd =
1109                                                 strtol(prog->argv[argc_l], &chptr, 10);
1110
1111                                         if (*chptr && *prog->argv[argc_l]) {
1112                                                 buf++, argc_l++;
1113                                                 prog->argv[argc_l] = buf;
1114                                         }
1115                                 }
1116
1117                                 if (prog->redirects[i].fd == -1) {
1118                                         if (*src == '>')
1119                                                 prog->redirects[i].fd = 1;
1120                                         else
1121                                                 prog->redirects[i].fd = 0;
1122                                 }
1123
1124                                 if (*src++ == '>') {
1125                                         if (*src == '>')
1126                                                 prog->redirects[i].type =
1127                                                         REDIRECT_APPEND, src++;
1128                                         else
1129                                                 prog->redirects[i].type = REDIRECT_OVERWRITE;
1130                                 } else {
1131                                         prog->redirects[i].type = REDIRECT_INPUT;
1132                                 }
1133
1134                                 /* This isn't POSIX sh compliant. Oh well. */
1135                                 chptr = src;
1136                                 while (isspace(*chptr))
1137                                         chptr++;
1138
1139                                 if (!*chptr) {
1140                                         error_msg("file name expected after %c", *src);
1141                                         free_job(job);
1142                                         job->num_progs=0;
1143                                         return 1;
1144                                 }
1145
1146                                 prog->redirects[i].filename = buf;
1147                                 while (*chptr && !isspace(*chptr))
1148                                         *buf++ = *chptr++;
1149
1150                                 src = chptr - 1;        /* we src++ later */
1151                                 prog->argv[argc_l] = ++buf;
1152                                 break;
1153
1154                         case '|':                       /* pipe */
1155                                 /* finish this command */
1156                                 if (*prog->argv[argc_l])
1157                                         argc_l++;
1158                                 if (!argc_l) {
1159                                         error_msg("empty command in pipe");
1160                                         free_job(job);
1161                                         job->num_progs=0;
1162                                         return 1;
1163                                 }
1164                                 prog->argv[argc_l] = NULL;
1165
1166                                 /* and start the next */
1167                                 job->num_progs++;
1168                                 job->progs = xrealloc(job->progs,
1169                                                                           sizeof(*job->progs) * job->num_progs);
1170                                 prog = job->progs + (job->num_progs - 1);
1171                                 prog->num_redirects = 0;
1172                                 prog->redirects = NULL;
1173                                 prog->is_stopped = 0;
1174                                 prog->family = job;
1175                                 argc_l = 0;
1176
1177                                 argv_alloced = 5;
1178                                 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1179                                 prog->argv[0] = ++buf;
1180
1181                                 src++;
1182                                 while (*src && isspace(*src))
1183                                         src++;
1184
1185                                 if (!*src) {
1186                                         error_msg("empty command in pipe");
1187                                         free_job(job);
1188                                         job->num_progs=0;
1189                                         return 1;
1190                                 }
1191                                 src--;                  /* we'll ++ it at the end of the loop */
1192
1193                                 break;
1194
1195                         case '&':                       /* background */
1196                                 *inbg = 1;
1197                         case ';':                       /* multiple commands */
1198                                 done = 1;
1199                                 return_command = *command_ptr + (src - *command_ptr) + 1;
1200                                 break;
1201
1202 #ifdef BB_FEATURE_SH_BACKTICKS
1203                         case '`':
1204                                 /* Exec a backtick-ed command */
1205                                 /* Besides any previous brokenness, I have not
1206                                  * updated backtick handling for close_me support.
1207                                  * I don't know if it needs it or not.  -- LRD */
1208                                 {
1209                                         char* charptr1=NULL, *charptr2;
1210                                         char* ptr=NULL;
1211                                         struct job *newjob;
1212                                         struct jobset njob_list = { NULL, NULL };
1213                                         int pipefd[2];
1214                                         int size;
1215
1216                                         ptr=strchr(++src, '`');
1217                                         if (ptr==NULL) {
1218                                                 fprintf(stderr, "Unmatched '`' in command\n");
1219                                                 free_job(job);
1220                                                 return 1;
1221                                         }
1222
1223                                         /* Make some space to hold just the backticked command */
1224                                         charptr1 = charptr2 = xmalloc(1+ptr-src);
1225                                         memcpy(charptr1, src, ptr-src);
1226                                         charptr1[ptr-src] = '\0';
1227                                         newjob = xmalloc(sizeof(struct job));
1228                                         newjob->job_list = &njob_list;
1229                                         /* Now parse and run the backticked command */
1230                                         if (!parse_command(&charptr1, newjob, inbg) 
1231                                                         && newjob->num_progs) {
1232                                                 pipe(pipefd);
1233                                                 run_command(newjob, 0, pipefd);
1234                                         }
1235                                         checkjobs(job->job_list);
1236                                         free_job(newjob);  /* doesn't actually free newjob,
1237                                                              looks like a memory leak */
1238                                         free(charptr2);
1239                                         
1240                                         /* Make a copy of any stuff left over in the command 
1241                                          * line after the second backtick */
1242                                         charptr2 = xmalloc(strlen(ptr)+1);
1243                                         memcpy(charptr2, ptr+1, strlen(ptr));
1244
1245
1246                                         /* Copy the output from the backtick-ed command into the
1247                                          * command line, making extra room as needed  */
1248                                         --src;
1249                                         charptr1 = xmalloc(BUFSIZ);
1250                                         while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1251                                                 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1252                                                 if (newsize > BUFSIZ) {
1253                                                         *command_ptr=xrealloc(*command_ptr, newsize);
1254                                                 }
1255                                                 memcpy(src, charptr1, size); 
1256                                                 src+=size;
1257                                         }
1258                                         free(charptr1);
1259                                         close(pipefd[0]);
1260                                         if (*(src-1)=='\n')
1261                                                 --src;
1262
1263                                         /* Now paste into the *command_ptr all the stuff 
1264                                          * leftover after the second backtick */
1265                                         memcpy(src, charptr2, strlen(charptr2)+1);
1266                                         free(charptr2);
1267
1268                                         /* Now recursively call parse_command to deal with the new
1269                                          * and improved version of the command line with the backtick
1270                                          * results expanded in place... */
1271                                         {
1272                                                 struct jobset *jl=job->job_list;
1273                                                 free_job(job);
1274                                                 job->job_list = jl;
1275                                         }
1276                                         return(parse_command(command_ptr, job, inbg));
1277                                 }
1278                                 break;
1279 #endif // BB_FEATURE_SH_BACKTICKS
1280
1281                         case '\\':
1282                                 src++;
1283                                 if (!*src) {
1284 /* This is currently a little broken... */
1285 #ifdef HANDLE_CONTINUATION_CHARS
1286                                         /* They fed us a continuation char, so continue reading stuff
1287                                          * on the next line, then tack that onto the end of the current
1288                                          * command */
1289                                         char *command;
1290                                         int newsize;
1291                                         printf("erik: found a continue char at EOL...\n");
1292                                         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1293                                         if (get_command(input, command)) {
1294                                                 error_msg("character expected after \\");
1295                                                 free(command);
1296                                                 free_job(job);
1297                                                 return 1;
1298                                         }
1299                                         newsize = strlen(*command_ptr) + strlen(command) + 2;
1300                                         if (newsize > BUFSIZ) {
1301                                                 printf("erik: doing realloc\n");
1302                                                 *command_ptr=xrealloc(*command_ptr, newsize);
1303                                         }
1304                                         printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1305                                         memcpy(--src, command, strlen(command)); 
1306                                         printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1307                                         free(command);
1308                                         break;
1309 #else
1310                                         error_msg("character expected after \\");
1311                                         free(command);
1312                                         free_job(job);
1313                                         return 1;
1314 #endif
1315                                 }
1316                                 if (*src == '*' || *src == '[' || *src == ']'
1317                                         || *src == '?') *buf++ = '\\';
1318                                 /* fallthrough */
1319                         default:
1320                                 *buf++ = *src;
1321                         }
1322
1323                 src++;
1324         }
1325
1326         if (*prog->argv[argc_l]) {
1327                 argc_l++;
1328         }
1329         if (!argc_l) {
1330                 free_job(job);
1331                 return 0;
1332         }
1333         prog->argv[argc_l] = NULL;
1334
1335         if (!return_command) {
1336                 job->text = xmalloc(strlen(*command_ptr) + 1);
1337                 strcpy(job->text, *command_ptr);
1338         } else {
1339                 /* This leaves any trailing spaces, which is a bit sloppy */
1340                 count = return_command - *command_ptr;
1341                 job->text = xmalloc(count + 1);
1342                 strncpy(job->text, *command_ptr, count);
1343                 job->text[count] = '\0';
1344         }
1345
1346         *command_ptr = return_command;
1347         
1348         return 0;
1349 }
1350
1351 /* Run the child_prog, no matter what kind of command it uses.
1352  */
1353 static int pseudo_exec(struct child_prog *child)
1354 {
1355         struct built_in_command *x;
1356 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1357         char *name;
1358 #endif
1359
1360         /* Check if the command matches any of the non-forking builtins.
1361          * Depending on context, this might be redundant.  But it's
1362          * easier to waste a few CPU cycles than it is to figure out
1363          * if this is one of those cases.
1364          */
1365         for (x = bltins; x->cmd; x++) {
1366                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1367                         exit(x->function(child));
1368                 }
1369         }
1370
1371         /* Check if the command matches any of the forking builtins. */
1372         for (x = bltins_forking; x->cmd; x++) {
1373                 if (strcmp(child->argv[0], x->cmd) == 0) {
1374                         applet_name=x->cmd;
1375                         exit (x->function(child));
1376                 }
1377         }
1378 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1379         /* Check if the command matches any busybox internal
1380          * commands ("applets") here.  Following discussions from
1381          * November 2000 on busybox@opensource.lineo.com, don't use
1382          * get_last_path_component().  This way explicit (with
1383          * slashes) filenames will never be interpreted as an
1384          * applet, just like with builtins.  This way the user can
1385          * override an applet with an explicit filename reference.
1386          * The only downside to this change is that an explicit
1387          * /bin/foo invocation will fork and exec /bin/foo, even if
1388          * /bin/foo is a symlink to busybox.
1389          */
1390         name = child->argv[0];
1391
1392 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1393         /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1394          * if you run /bin/cat, it will use BusyBox cat even if 
1395          * /bin/cat exists on the filesystem and is _not_ busybox.
1396          * Some systems want this, others do not.  Choose wisely.  :-)
1397          */
1398         name = get_last_path_component(name);
1399 #endif
1400
1401         {
1402             char** argv=child->argv;
1403             int argc_l;
1404             for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1405             optind = 1;
1406             run_applet_by_name(name, argc_l, child->argv);
1407         }
1408 #endif
1409
1410         execvp(child->argv[0], child->argv);
1411         perror_msg_and_die("%s", child->argv[0]);
1412 }
1413
1414 static void insert_job(struct job *newjob, int inbg)
1415 {
1416         struct job *thejob;
1417         struct jobset *job_list=newjob->job_list;
1418
1419         /* find the ID for thejob to use */
1420         newjob->jobid = 1;
1421         for (thejob = job_list->head; thejob; thejob = thejob->next)
1422                 if (thejob->jobid >= newjob->jobid)
1423                         newjob->jobid = thejob->jobid + 1;
1424
1425         /* add thejob to the list of running jobs */
1426         if (!job_list->head) {
1427                 thejob = job_list->head = xmalloc(sizeof(*thejob));
1428         } else {
1429                 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1430                 thejob->next = xmalloc(sizeof(*thejob));
1431                 thejob = thejob->next;
1432         }
1433
1434         *thejob = *newjob;   /* physically copy the struct job */
1435         thejob->next = NULL;
1436         thejob->running_progs = thejob->num_progs;
1437         thejob->stopped_progs = 0;
1438
1439         if (inbg) {
1440                 /* we don't wait for background thejobs to return -- append it 
1441                    to the list of backgrounded thejobs and leave it alone */
1442                 printf("[%d] %d\n", thejob->jobid,
1443                            newjob->progs[newjob->num_progs - 1].pid);
1444 #ifdef BB_FEATURE_SH_ENVIRONMENT
1445                 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1446 #endif
1447         } else {
1448                 newjob->job_list->fg = thejob;
1449
1450                 /* move the new process group into the foreground */
1451                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1452                 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1453                         perror_msg("tcsetpgrp");
1454         }
1455 }
1456
1457 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1458 {
1459         /* struct job *thejob; */
1460         int i;
1461         int nextin, nextout;
1462         int pipefds[2];                         /* pipefd[0] is for reading */
1463         struct built_in_command *x;
1464         struct child_prog *child;
1465
1466         nextin = 0, nextout = 1;
1467         for (i = 0; i < newjob->num_progs; i++) {
1468                 child = & (newjob->progs[i]);
1469
1470                 if ((i + 1) < newjob->num_progs) {
1471                         if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1472                         nextout = pipefds[1];
1473                 } else {
1474                         if (outpipe[1]!=-1) {
1475                                 nextout = outpipe[1];
1476                         } else {
1477                                 nextout = 1;
1478                         }
1479                 }
1480
1481 #ifdef BB_FEATURE_SH_ENVIRONMENT
1482                 if (show_x_trace==TRUE) {
1483                         int j;
1484                         fputc('+', stderr);
1485                         for (j = 0; child->argv[j]; j++) {
1486                                 fputc(' ', stderr);
1487                                 fputs(child->argv[j], stderr);
1488                         }
1489                         fputc('\n', stderr);
1490                 }
1491 #endif
1492
1493                 /* Check if the command matches any non-forking builtins,
1494                  * but only if this is a simple command.
1495                  * Non-forking builtins within pipes have to fork anyway,
1496                  * and are handled in pseudo_exec.  "echo foo | read bar"
1497                  * is doomed to failure, and doesn't work on bash, either.
1498                  */
1499                 if (newjob->num_progs == 1) {
1500                         for (x = bltins; x->cmd; x++) {
1501                                 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1502                                         int squirrel[] = {-1, -1, -1};
1503                                         int rcode;
1504                                         setup_redirects(child, squirrel);
1505                                         rcode = x->function(child);
1506                                         restore_redirects(squirrel);
1507                                         return rcode;
1508                                 }
1509                         }
1510                 }
1511
1512                 if (!(child->pid = fork())) {
1513                         signal(SIGTTOU, SIG_DFL);
1514
1515                         close_all();
1516
1517                         if (outpipe[1]!=-1) {
1518                                 close(outpipe[0]);
1519                         }
1520                         if (nextin != 0) {
1521                                 dup2(nextin, 0);
1522                                 close(nextin);
1523                         }
1524
1525                         if (nextout != 1) {
1526                                 dup2(nextout, 1);
1527                                 dup2(nextout, 2);  /* Really? */
1528                                 close(nextout);
1529                                 close(pipefds[0]);
1530                         }
1531
1532                         /* explicit redirects override pipes */
1533                         setup_redirects(child,NULL);
1534
1535                         pseudo_exec(child);
1536                 }
1537                 if (outpipe[1]!=-1) {
1538                         close(outpipe[1]);
1539                 }
1540
1541                 /* put our child in the process group whose leader is the
1542                    first process in this pipe */
1543                 setpgid(child->pid, newjob->progs[0].pid);
1544                 if (nextin != 0)
1545                         close(nextin);
1546                 if (nextout != 1)
1547                         close(nextout);
1548
1549                 /* If there isn't another process, nextin is garbage 
1550                    but it doesn't matter */
1551                 nextin = pipefds[0];
1552         }
1553
1554         newjob->pgrp = newjob->progs[0].pid;
1555
1556         insert_job(newjob, inbg);
1557
1558         return 0;
1559 }
1560
1561 static int busy_loop(FILE * input)
1562 {
1563         char *command;
1564         char *next_command = NULL;
1565         struct job newjob;
1566         pid_t  parent_pgrp;
1567         int i;
1568         int inbg;
1569         int status;
1570         newjob.job_list = &job_list;
1571         newjob.job_context = DEFAULT_CONTEXT;
1572
1573         /* save current owner of TTY so we can restore it on exit */
1574         parent_pgrp = tcgetpgrp(0);
1575
1576         command = (char *) xcalloc(BUFSIZ, sizeof(char));
1577
1578         /* don't pay any attention to this signal; it just confuses 
1579            things and isn't really meant for shells anyway */
1580         signal(SIGTTOU, SIG_IGN);
1581
1582         while (1) {
1583                 if (!job_list.fg) {
1584                         /* no job is in the foreground */
1585
1586                         /* see if any background processes have exited */
1587                         checkjobs(&job_list);
1588
1589                         if (!next_command) {
1590                                 if (get_command(input, command))
1591                                         break;
1592                                 next_command = command;
1593                         }
1594
1595                         if (expand_arguments(next_command) == FALSE) {
1596                                 free(command);
1597                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1598                                 next_command = NULL;
1599                                 continue;
1600                         }
1601
1602                         if (!parse_command(&next_command, &newjob, &inbg) &&
1603                                 newjob.num_progs) {
1604                                 int pipefds[2] = {-1,-1};
1605                                 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1606                                 run_command(&newjob, inbg, pipefds);
1607                         }
1608                         else {
1609                                 free(command);
1610                                 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1611                                 next_command = NULL;
1612                         }
1613                 } else {
1614                         /* a job is running in the foreground; wait for it */
1615                         i = 0;
1616                         while (!job_list.fg->progs[i].pid ||
1617                                    job_list.fg->progs[i].is_stopped == 1) i++;
1618
1619                         if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0)
1620                                 perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
1621
1622                         if (WIFEXITED(status) || WIFSIGNALED(status)) {
1623                                 /* the child exited */
1624                                 job_list.fg->running_progs--;
1625                                 job_list.fg->progs[i].pid = 0;
1626
1627 #ifdef BB_FEATURE_SH_ENVIRONMENT
1628                                 last_return_code=WEXITSTATUS(status);
1629 #endif
1630                                 debug_printf("'%s' exited -- return code %d\n",
1631                                                 job_list.fg->text, last_return_code);
1632                                 if (!job_list.fg->running_progs) {
1633                                         /* child exited */
1634                                         remove_job(&job_list, job_list.fg);
1635                                         job_list.fg = NULL;
1636                                 }
1637                         } else {
1638                                 /* the child was stopped */
1639                                 job_list.fg->stopped_progs++;
1640                                 job_list.fg->progs[i].is_stopped = 1;
1641
1642                                 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1643                                         printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1644                                                    "Stopped", job_list.fg->text);
1645                                         job_list.fg = NULL;
1646                                 }
1647                         }
1648
1649                         if (!job_list.fg) {
1650                                 /* move the shell to the foreground */
1651                                 /* suppress messages when run from /linuxrc mag@sysgo.de */
1652                                 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1653                                         perror_msg("tcsetpgrp"); 
1654                         }
1655                 }
1656         }
1657         free(command);
1658
1659         /* return controlling TTY back to parent process group before exiting */
1660         if (tcsetpgrp(0, parent_pgrp))
1661                 perror_msg("tcsetpgrp");
1662
1663         /* return exit status if called with "-c" */
1664         if (input == NULL && WIFEXITED(status))
1665                 return WEXITSTATUS(status);
1666         
1667         return 0;
1668 }
1669
1670
1671 #ifdef BB_FEATURE_CLEAN_UP
1672 void free_memory(void)
1673 {
1674         if (cwd)
1675                 free(cwd);
1676         if (local_pending_command)
1677                 free(local_pending_command);
1678
1679         if (job_list.fg && !job_list.fg->running_progs) {
1680                 remove_job(&job_list, job_list.fg);
1681         }
1682 }
1683 #endif
1684
1685
1686 int shell_main(int argc_l, char **argv_l)
1687 {
1688         int opt, interactive=FALSE;
1689         FILE *input = stdin;
1690         argc = argc_l;
1691         argv = argv_l;
1692
1693         /* These variables need re-initializing when recursing */
1694         shell_context = 0;
1695         cwd=NULL;
1696         local_pending_command = NULL;
1697         close_me_head = NULL;
1698         job_list.head = NULL;
1699         job_list.fg = NULL;
1700 #ifdef BB_FEATURE_SH_ENVIRONMENT
1701         last_bg_pid=1;
1702         last_return_code=1;
1703         show_x_trace=FALSE;
1704 #endif
1705
1706         if (argv[0] && argv[0][0] == '-') {
1707                 FILE *prof_input;
1708                 prof_input = fopen("/etc/profile", "r");
1709                 if (!prof_input) {
1710                         printf( "Couldn't open file '/etc/profile'\n");
1711                 } else {
1712                         int tmp_fd = fileno(prof_input);
1713                         mark_open(tmp_fd);      
1714                         /* Now run the file */
1715                         busy_loop(prof_input);
1716                         fclose(prof_input);
1717                         mark_closed(tmp_fd);
1718                 }
1719         }
1720
1721         while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1722                 switch (opt) {
1723                         case 'c':
1724                                 input = NULL;
1725                                 if (local_pending_command != 0)
1726                                         error_msg_and_die("multiple -c arguments");
1727                                 local_pending_command = xstrdup(argv[optind]);
1728                                 optind++;
1729                                 argv = argv+optind;
1730                                 break;
1731 #ifdef BB_FEATURE_SH_ENVIRONMENT
1732                         case 'x':
1733                                 show_x_trace = TRUE;
1734                                 break;
1735 #endif
1736                         case 'i':
1737                                 interactive = TRUE;
1738                                 break;
1739                         default:
1740                                 show_usage();
1741                 }
1742         }
1743         /* A shell is interactive if the `-i' flag was given, or if all of
1744          * the following conditions are met:
1745          *        no -c command
1746          *    no arguments remaining or the -s flag given
1747          *    standard input is a terminal
1748          *    standard output is a terminal
1749          *    Refer to Posix.2, the description of the `sh' utility. */
1750         if (argv[optind]==NULL && input==stdin &&
1751                         isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1752                 interactive=TRUE;
1753         }
1754         if (interactive==TRUE) {
1755                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1756                 /* Looks like they want an interactive shell */
1757                 printf( "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1758                 printf( "Enter 'help' for a list of built-in commands.\n\n");
1759         } else if (local_pending_command==NULL) {
1760                 //printf( "optind=%d  argv[optind]='%s'\n", optind, argv[optind]);
1761                 input = xfopen(argv[optind], "r");
1762                 mark_open(fileno(input));  /* be lazy, never mark this closed */
1763         }
1764
1765         /* initialize the cwd -- this is never freed...*/
1766         cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1767         getcwd(cwd, sizeof(char)*MAX_LINE);
1768
1769 #ifdef BB_FEATURE_CLEAN_UP
1770         atexit(free_memory);
1771 #endif
1772
1773         return (busy_loop(input));
1774 }