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