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