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