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