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