1 /* vi: set sw=4 ts=4: */
3 * lash -- the BusyBox Lame-Ass SHell
5 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
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."
11 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
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...
20 //For debugging/development on the shell only...
31 #include <sys/ioctl.h>
39 #ifdef CONFIG_LOCALE_SUPPORT
44 #define expand_t glob_t
46 /* Always enable for the moment... */
47 #define CONFIG_LASH_PIPE_N_REDIRECTS
48 #define CONFIG_LASH_JOB_CONTROL
50 static const int MAX_READ = 128; /* size of input buffer for `read' builtin */
51 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
54 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
55 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
60 static const unsigned int DEFAULT_CONTEXT=0x1;
61 static const unsigned int IF_TRUE_CONTEXT=0x2;
62 static const unsigned int IF_FALSE_CONTEXT=0x4;
63 static const unsigned int THEN_EXP_CONTEXT=0x8;
64 static const unsigned int ELSE_EXP_CONTEXT=0x10;
66 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
68 enum redir_type type; /* type of redirection */
69 int fd; /* file descriptor being redirected */
70 char *filename; /* file to redirect fd to */
75 pid_t pid; /* 0 if exited */
76 char **argv; /* program name and arguments */
77 int num_redirects; /* elements in redirection array */
78 int is_stopped; /* is the program currently running? */
79 struct job *family; /* pointer back to the child's parent job */
80 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
81 struct redir_struct *redirects; /* I/O redirects */
86 struct job *head; /* head of list of running jobs */
87 struct job *fg; /* current foreground job */
91 int jobid; /* job number */
92 int num_progs; /* total number of programs in job */
93 int running_progs; /* number of programs running */
94 char *text; /* name of job */
95 char *cmdbuf; /* buffer various argv's point into */
96 pid_t pgrp; /* process group ID for the job */
97 struct child_prog *progs; /* array of programs in job */
98 struct job *next; /* to track background commands */
99 int stopped_progs; /* number of programs alive, but stopped */
100 unsigned int job_context; /* bitmask defining current context */
101 struct jobset *job_list;
104 struct built_in_command {
105 char *cmd; /* name */
106 char *descr; /* description */
107 int (*function) (struct child_prog *); /* function ptr */
112 struct close_me *next;
115 /* function prototypes for builtins */
116 static int builtin_cd(struct child_prog *cmd);
117 static int builtin_exec(struct child_prog *cmd);
118 static int builtin_exit(struct child_prog *cmd);
119 static int builtin_fg_bg(struct child_prog *cmd);
120 static int builtin_help(struct child_prog *cmd);
121 static int builtin_jobs(struct child_prog *dummy);
122 static int builtin_pwd(struct child_prog *dummy);
123 static int builtin_export(struct child_prog *cmd);
124 static int builtin_source(struct child_prog *cmd);
125 static int builtin_unset(struct child_prog *cmd);
126 static int builtin_read(struct child_prog *cmd);
129 /* function prototypes for shell stuff */
130 static void mark_open(int fd);
131 static void mark_closed(int fd);
132 static void close_all(void);
133 static void checkjobs(struct jobset *job_list);
134 static void remove_job(struct jobset *j_list, struct job *job);
135 static int get_command(FILE * source, char *command);
136 static int parse_command(char **command_ptr, struct job *job, int *inbg);
137 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
138 static int pseudo_exec(struct child_prog *cmd) ATTRIBUTE_NORETURN;
139 static int busy_loop(FILE * input);
142 /* Table of built-in functions (these are non-forking builtins, meaning they
143 * can change global variables in the parent shell process but they will not
144 * work with pipes and redirects; 'unset foo | whatever' will not work) */
145 static struct built_in_command bltins[] = {
146 {"bg", "Resume a job in the background", builtin_fg_bg},
147 {"cd", "Change working directory", builtin_cd},
148 {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
149 {"exit", "Exit from shell()", builtin_exit},
150 {"fg", "Bring job into the foreground", builtin_fg_bg},
151 {"jobs", "Lists the active jobs", builtin_jobs},
152 {"export", "Set environment variable", builtin_export},
153 {"unset", "Unset environment variable", builtin_unset},
154 {"read", "Input environment variable", builtin_read},
155 {".", "Source-in and run commands in a file", builtin_source},
156 /* to do: add ulimit */
160 /* Table of forking built-in functions (things that fork cannot change global
161 * variables in the parent process, such as the current working directory) */
162 static struct built_in_command bltins_forking[] = {
163 {"pwd", "Print current directory", builtin_pwd},
164 {"help", "List shell built-in commands", builtin_help},
169 static int shell_context; /* Type prompt trigger (PS1 or PS2) */
172 /* Globals that are static to this file */
173 static const char *cwd;
174 static char *local_pending_command = NULL;
175 static struct jobset job_list = { NULL, NULL };
178 static struct close_me *close_me_head;
179 static int last_return_code;
180 static int last_bg_pid;
181 static unsigned int last_jobid;
182 static int shell_terminal;
184 static char *PS2 = "> ";
188 static inline void debug_printf(const char *format, ...)
191 va_start(args, format);
192 vfprintf(stderr, format, args);
196 static inline void debug_printf(const char *format, ...) { }
200 Most builtins need access to the struct child_prog that has
201 their arguments, previously coded as cmd->progs[0]. That coding
202 can exhibit a bug, if the builtin is not the first command in
203 a pipeline: "echo foo | exec sort" will attempt to exec foo.
205 builtin previous use notes
206 ------ ----------------- ---------
208 exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins
210 fg_bg cmd->progs[0], job_list->head, job_list->fg
219 I added "struct job *family;" to struct child_prog,
220 and switched API to builtin_foo(struct child_prog *child);
221 So cmd->text becomes child->family->text
222 cmd->job_context becomes child->family->job_context
223 cmd->progs[0] becomes *child
224 job_list becomes child->family->job_list
227 /* built-in 'cd <path>' handler */
228 static int builtin_cd(struct child_prog *child)
232 if (child->argv[1] == NULL)
233 newdir = getenv("HOME");
235 newdir = child->argv[1];
237 printf("cd: %s: %m\n", newdir);
240 cwd = xgetcwd((char *)cwd);
242 cwd = bb_msg_unknown;
246 /* built-in 'exec' handler */
247 static int builtin_exec(struct child_prog *child)
249 if (child->argv[1] == NULL)
250 return EXIT_SUCCESS; /* Really? */
257 /* built-in 'exit' handler */
258 static int builtin_exit(struct child_prog *child)
260 if (child->argv[1] == NULL)
263 exit (atoi(child->argv[1]));
266 /* built-in 'fg' and 'bg' handler */
267 static int builtin_fg_bg(struct child_prog *child)
270 struct job *job=NULL;
272 /* If they gave us no args, assume they want the last backgrounded task */
273 if (!child->argv[1]) {
274 for (job = child->family->job_list->head; job; job = job->next) {
275 if (job->jobid == last_jobid) {
280 bb_error_msg("%s: no current job", child->argv[0]);
284 if (sscanf(child->argv[1], "%%%d", &jobnum) != 1) {
285 bb_error_msg("%s: bad argument '%s'", child->argv[0], child->argv[1]);
288 for (job = child->family->job_list->head; job; job = job->next) {
289 if (job->jobid == jobnum) {
294 bb_error_msg("%s: %d: no such job", child->argv[0], jobnum);
299 if (*child->argv[0] == 'f') {
300 /* Put the job into the foreground. */
301 tcsetpgrp(shell_terminal, job->pgrp);
303 child->family->job_list->fg = job;
306 /* Restart the processes in the job */
307 for (i = 0; i < job->num_progs; i++)
308 job->progs[i].is_stopped = 0;
310 job->stopped_progs = 0;
312 if ( (i=kill(- job->pgrp, SIGCONT)) < 0) {
314 remove_job(&job_list, job);
316 bb_perror_msg("kill (SIGCONT)");
323 /* built-in 'help' handler */
324 static int builtin_help(struct child_prog *dummy)
326 struct built_in_command *x;
328 printf("\nBuilt-in commands:\n");
329 printf("-------------------\n");
330 for (x = bltins; x->cmd; x++) {
333 printf("%s\t%s\n", x->cmd, x->descr);
335 for (x = bltins_forking; x->cmd; x++) {
338 printf("%s\t%s\n", x->cmd, x->descr);
344 /* built-in 'jobs' handler */
345 static int builtin_jobs(struct child_prog *child)
350 for (job = child->family->job_list->head; job; job = job->next) {
351 if (job->running_progs == job->stopped_progs)
352 status_string = "Stopped";
354 status_string = "Running";
356 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
362 /* built-in 'pwd' handler */
363 static int builtin_pwd(struct child_prog *dummy)
365 cwd = xgetcwd((char *)cwd);
367 cwd = bb_msg_unknown;
372 /* built-in 'export VAR=value' handler */
373 static int builtin_export(struct child_prog *child)
376 char *v = child->argv[1];
380 for (e = environ; *e; e++) {
387 fprintf(stderr, "export: %m\n");
388 #ifdef CONFIG_FEATURE_SH_FANCY_PROMPT
389 if (strncmp(v, "PS1=", 4)==0)
393 #ifdef CONFIG_LOCALE_SUPPORT
394 if(strncmp(v, "LC_ALL=", 7)==0)
395 setlocale(LC_ALL, getenv("LC_ALL"));
396 if(strncmp(v, "LC_CTYPE=", 9)==0)
397 setlocale(LC_CTYPE, getenv("LC_CTYPE"));
403 /* built-in 'read VAR' handler */
404 static int builtin_read(struct child_prog *child)
406 int res = 0, len, newlen;
408 char string[MAX_READ];
410 if (child->argv[1]) {
411 /* argument (VAR) given: put "VAR=" into buffer */
412 safe_strncpy(string, child->argv[1], MAX_READ-1);
413 len = strlen(string);
416 fgets(&string[len], sizeof(string) - len, stdin); /* read string */
417 newlen = strlen(string);
419 string[--newlen] = '\0'; /* chomp trailing newline */
421 ** string should now contain "VAR=<value>"
422 ** copy it (putenv() won't do that, so we must make sure
423 ** the string resides in a static buffer!)
426 if((s = strdup(string)))
429 fprintf(stderr, "read: %m\n");
432 fgets(string, sizeof(string), stdin);
437 /* Built-in '.' handler (read-in and execute commands from file) */
438 static int builtin_source(struct child_prog *child)
444 if (child->argv[1] == NULL)
447 input = fopen(child->argv[1], "r");
449 printf( "Couldn't open file '%s'\n", child->argv[1]);
455 /* Now run the file */
456 status = busy_loop(input);
462 /* built-in 'unset VAR' handler */
463 static int builtin_unset(struct child_prog *child)
465 if (child->argv[1] == NULL) {
466 printf( "unset: parameter required.\n");
469 unsetenv(child->argv[1]);
473 static void mark_open(int fd)
475 struct close_me *new = xmalloc(sizeof(struct close_me));
477 new->next = close_me_head;
481 static void mark_closed(int fd)
483 struct close_me *tmp;
484 if (close_me_head == NULL || close_me_head->fd != fd)
485 bb_error_msg_and_die("corrupt close_me");
487 close_me_head = close_me_head->next;
491 static void close_all()
493 struct close_me *c, *tmp;
494 for (c=close_me_head; c; c=tmp) {
499 close_me_head = NULL;
503 #ifdef CONFIG_LASH_JOB_CONTROL
504 /* free up all memory from a job */
505 static void free_job(struct job *cmd)
510 for (i = 0; i < cmd->num_progs; i++) {
511 free(cmd->progs[i].argv);
512 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
513 if (cmd->progs[i].redirects)
514 free(cmd->progs[i].redirects);
520 keep = cmd->job_list;
521 memset(cmd, 0, sizeof(struct job));
522 cmd->job_list = keep;
525 /* remove a job from a jobset */
526 static void remove_job(struct jobset *j_list, struct job *job)
531 if (job == j_list->head) {
532 j_list->head = job->next;
534 prevjob = j_list->head;
535 while (prevjob->next != job)
536 prevjob = prevjob->next;
537 prevjob->next = job->next;
541 last_jobid = j_list->head->jobid;
548 /* Checks to see if any background processes have exited -- if they
549 have, figure out why and see if a job has completed */
550 static void checkjobs(struct jobset *j_list)
557 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
558 for (job = j_list->head; job; job = job->next) {
560 while (prognum < job->num_progs &&
561 job->progs[prognum].pid != childpid) prognum++;
562 if (prognum < job->num_progs)
566 /* This happens on backticked commands */
570 if (WIFEXITED(status) || WIFSIGNALED(status)) {
572 job->running_progs--;
573 job->progs[prognum].pid = 0;
575 if (!job->running_progs) {
576 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
578 remove_job(j_list, job);
582 job->stopped_progs++;
583 job->progs[prognum].is_stopped = 1;
586 /* Printing this stuff is a pain, since it tends to
587 * overwrite the prompt an inconveinient moments. So
589 if (job->stopped_progs == job->num_progs) {
590 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
597 if (childpid == -1 && errno != ECHILD)
598 bb_perror_msg("waitpid");
601 static void checkjobs(struct jobset *j_list)
604 static void free_job(struct job *cmd)
607 static void remove_job(struct jobset *j_list, struct job *job)
612 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
613 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
614 * and stderr if they are redirected. */
615 static int setup_redirects(struct child_prog *prog, int squirrel[])
620 struct redir_struct *redir = prog->redirects;
622 for (i = 0; i < prog->num_redirects; i++, redir++) {
623 switch (redir->type) {
627 case REDIRECT_OVERWRITE:
628 mode = O_WRONLY | O_CREAT | O_TRUNC;
630 case REDIRECT_APPEND:
631 mode = O_WRONLY | O_CREAT | O_APPEND;
635 openfd = open(redir->filename, mode, 0666);
637 /* this could get lost if stderr has been redirected, but
638 bash and ash both lose it as well (though zsh doesn't!) */
639 bb_perror_msg("error opening %s", redir->filename);
643 if (openfd != redir->fd) {
644 if (squirrel && redir->fd < 3) {
645 squirrel[redir->fd] = dup(redir->fd);
646 fcntl (squirrel[redir->fd], F_SETFD, FD_CLOEXEC);
648 dup2(openfd, redir->fd);
656 static void restore_redirects(int squirrel[])
659 for (i=0; i<3; i++) {
662 /* No error checking. I sure wouldn't know what
663 * to do with an error if I found one! */
670 static inline int setup_redirects(struct child_prog *prog, int squirrel[])
674 static inline void restore_redirects(int squirrel[])
679 static inline void cmdedit_set_initial_prompt(void)
681 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
690 static inline void setup_prompt_string(char **prompt_str)
692 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
693 /* Set up the prompt */
694 if (shell_context == 0) {
696 PS1=xmalloc(strlen(cwd)+4);
697 sprintf(PS1, "%s %s", cwd, ( geteuid() != 0 ) ? "$ ":"# ");
703 *prompt_str = (shell_context==0)? PS1 : PS2;
707 static int get_command(FILE * source, char *command)
711 if (source == NULL) {
712 if (local_pending_command) {
713 /* a command specified (-c option): return it & mark it done */
714 strcpy(command, local_pending_command);
715 free(local_pending_command);
716 local_pending_command = NULL;
722 if (source == stdin) {
723 setup_prompt_string(&prompt_str);
725 #ifdef CONFIG_FEATURE_COMMAND_EDITING
727 ** enable command line editing only while a command line
728 ** is actually being read; otherwise, we'll end up bequeathing
729 ** atexit() handlers and other unwanted stuff to our
730 ** child processes (rob@sysgo.de)
732 cmdedit_read_input(prompt_str, command);
735 fputs(prompt_str, stdout);
739 if (!fgets(command, BUFSIZ - 2, source)) {
748 static char* itoa(register int i)
750 static char a[7]; /* Max 7 ints */
751 register char *b = a + sizeof(a) - 1;
759 *--b = '0' + (i % 10);
768 static char * strsep_space( char *string, int * ix)
774 /* Short circuit the trivial case */
775 if ( !string || ! string[*ix])
778 /* Find the end of the token. */
779 while( string && string[*ix] && !isspace(string[*ix]) ) {
783 /* Find the end of any whitespace trailing behind
784 * the token and let that be part of the token */
785 while( string && string[*ix] && isspace(string[*ix]) ) {
789 if (! string && *ix==0) {
790 /* Nothing useful was found */
794 token = xmalloc(*ix+1);
796 strncpy(token, string, *ix);
801 static int expand_arguments(char *command)
803 int total_length=0, length, i, retval, ix = 0;
804 expand_t expand_result;
805 char *tmpcmd, *cmd, *cmd_copy;
806 char *src, *dst, *var;
807 const char *out_of_space = "out of space during expansion";
808 int flags = GLOB_NOCHECK
817 /* get rid of the terminating \n */
820 /* Fix up escape sequences to be the Real Thing(tm) */
821 while( command && command[ix]) {
822 if (command[ix] == '\\') {
823 const char *tmp = command+ix+1;
824 command[ix] = bb_process_escape_sequence( &tmp );
825 memmove(command+ix + 1, tmp, strlen(tmp)+1);
829 /* Use glob and then fixup environment variables and such */
831 /* It turns out that glob is very stupid. We have to feed it one word at a
832 * time since it can't cope with a full string. Here we convert command
833 * (char*) into cmd (char**, one word per string) */
835 /* We need a clean copy, so strsep can mess up the copy while
836 * we write stuff into the original (in a minute) */
837 cmd = cmd_copy = bb_xstrdup(command);
839 for (ix = 0, tmpcmd = cmd;
840 (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) {
843 /* we need to trim() the result for glob! */
845 retval = glob(tmpcmd, flags, NULL, &expand_result);
846 free(tmpcmd); /* Free mem allocated by strsep_space */
847 if (retval == GLOB_NOSPACE) {
848 /* Mem may have been allocated... */
849 globfree (&expand_result);
850 bb_error_msg(out_of_space);
852 } else if (retval != 0) {
853 /* Some other error. GLOB_NOMATCH shouldn't
854 * happen because of the GLOB_NOCHECK flag in
856 bb_error_msg("syntax error");
859 /* Convert from char** (one word per string) to a simple char*,
860 * but don't overflow command which is BUFSIZ in length */
861 for (i=0; i < expand_result.gl_pathc; i++) {
862 length=strlen(expand_result.gl_pathv[i]);
863 if (total_length+length+1 >= BUFSIZ) {
864 bb_error_msg(out_of_space);
867 strcat(command+total_length, " ");
869 strcat(command+total_length, expand_result.gl_pathv[i]);
870 total_length+=length;
872 globfree (&expand_result);
878 /* Now do the shell variable substitutions which
879 * wordexp can't do for us, namely $? and $! */
881 while((dst = strchr(src,'$')) != NULL){
885 var = itoa(last_return_code);
891 var = itoa(last_bg_pid);
893 /* Everything else like $$, $#, $[0-9], etc. should all be
894 * expanded by wordexp(), so we can in theory skip that stuff
895 * here, but just to be on the safe side (i.e., since uClibc
896 * wordexp doesn't do this stuff yet), lets leave it in for
899 var = itoa(getpid());
904 case '0':case '1':case '2':case '3':case '4':
905 case '5':case '6':case '7':case '8':case '9':
907 int ixx=*(dst+1)-48+1;
918 /* a single character construction was found, and
919 * already handled in the case statement */
922 /* Looks like an environment variable */
924 int num_skip_chars=0;
925 int dstlen = strlen(dst);
926 /* Is this a ${foo} type variable? */
927 if (dstlen >=2 && *(dst+1) == '{') {
928 src=strchr(dst+1, '}');
932 while(isalnum(*src) || *src=='_') src++;
938 *src='\0'; /* temporary */
939 var = getenv(dst + 1 + num_skip_chars);
941 src += num_skip_chars;
944 /* Seems we got an un-expandable variable. So delete it. */
948 int subst_len = strlen(var);
949 int trail_len = strlen(src);
950 if (dst+subst_len+trail_len >= command+BUFSIZ) {
951 bb_error_msg(out_of_space);
954 /* Move stuff to the end of the string to accommodate
955 * filling the created gap with the new stuff */
956 memmove(dst+subst_len, src, trail_len+1);
957 /* Now copy in the new stuff */
958 memcpy(dst, var, subst_len);
966 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
967 line). If a valid command is found, command_ptr is set to point to
968 the beginning of the next command (if the original command had more
969 then one job associated with it) or NULL if no more commands are
971 static int parse_command(char **command_ptr, struct job *job, int *inbg)
974 char *return_command = NULL;
982 struct child_prog *prog;
983 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
988 /* skip leading white space */
989 while (**command_ptr && isspace(**command_ptr))
992 /* this handles empty lines or leading '#' characters */
993 if (!**command_ptr || (**command_ptr == '#')) {
1000 job->progs = xmalloc(sizeof(*job->progs));
1002 /* We set the argv elements to point inside of this string. The
1003 memory is freed by free_job(). Allocate twice the original
1004 length in case we need to quote every single character.
1006 Getting clean memory relieves us of the task of NULL
1007 terminating things and makes the rest of this look a bit
1008 cleaner (though it is, admittedly, a tad less efficient) */
1009 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
1013 prog->num_redirects = 0;
1014 prog->is_stopped = 0;
1016 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
1017 prog->redirects = NULL;
1021 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1022 prog->argv[0] = job->cmdbuf;
1026 while (*src && !done) {
1027 if (quote == *src) {
1033 bb_error_msg("character expected after \\");
1038 /* in shell, "\'" should yield \' */
1039 if (*src != quote) {
1043 } else if (*src == '*' || *src == '?' || *src == '[' ||
1044 *src == ']') *buf++ = '\\';
1046 } else if (isspace(*src)) {
1047 if (*prog->argv[argc_l] || saw_quote) {
1049 /* +1 here leaves room for the NULL which ends argv */
1050 if ((argc_l + 1) == argv_alloced) {
1052 prog->argv = xrealloc(prog->argv,
1053 sizeof(*prog->argv) *
1056 prog->argv[argc_l] = buf;
1067 case '#': /* comment */
1074 #ifdef CONFIG_LASH_PIPE_N_REDIRECTS
1075 case '>': /* redirects */
1077 i = prog->num_redirects++;
1078 prog->redirects = xrealloc(prog->redirects,
1079 sizeof(*prog->redirects) *
1082 prog->redirects[i].fd = -1;
1083 if (buf != prog->argv[argc_l]) {
1084 /* the stuff before this character may be the file number
1086 prog->redirects[i].fd =
1087 strtol(prog->argv[argc_l], &chptr, 10);
1089 if (*chptr && *prog->argv[argc_l]) {
1091 prog->argv[argc_l] = buf;
1095 if (prog->redirects[i].fd == -1) {
1097 prog->redirects[i].fd = 1;
1099 prog->redirects[i].fd = 0;
1102 if (*src++ == '>') {
1104 prog->redirects[i].type =
1105 REDIRECT_APPEND, src++;
1107 prog->redirects[i].type = REDIRECT_OVERWRITE;
1109 prog->redirects[i].type = REDIRECT_INPUT;
1112 /* This isn't POSIX sh compliant. Oh well. */
1114 while (isspace(*chptr))
1118 bb_error_msg("file name expected after %c", *(src-1));
1124 prog->redirects[i].filename = buf;
1125 while (*chptr && !isspace(*chptr))
1128 src = chptr - 1; /* we src++ later */
1129 prog->argv[argc_l] = ++buf;
1132 case '|': /* pipe */
1133 /* finish this command */
1134 if (*prog->argv[argc_l] || saw_quote)
1137 bb_error_msg("empty command in pipe");
1142 prog->argv[argc_l] = NULL;
1144 /* and start the next */
1146 job->progs = xrealloc(job->progs,
1147 sizeof(*job->progs) * job->num_progs);
1148 prog = job->progs + (job->num_progs - 1);
1149 prog->num_redirects = 0;
1150 prog->redirects = NULL;
1151 prog->is_stopped = 0;
1156 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1157 prog->argv[0] = ++buf;
1160 while (*src && isspace(*src))
1164 bb_error_msg("empty command in pipe");
1169 src--; /* we'll ++ it at the end of the loop */
1174 #ifdef CONFIG_LASH_JOB_CONTROL
1175 case '&': /* background */
1178 case ';': /* multiple commands */
1180 return_command = *command_ptr + (src - *command_ptr) + 1;
1186 bb_error_msg("character expected after \\");
1190 if (*src == '*' || *src == '[' || *src == ']'
1191 || *src == '?') *buf++ = '\\';
1200 if (*prog->argv[argc_l] || saw_quote) {
1207 prog->argv[argc_l] = NULL;
1209 if (!return_command) {
1210 job->text = xmalloc(strlen(*command_ptr) + 1);
1211 strcpy(job->text, *command_ptr);
1213 /* This leaves any trailing spaces, which is a bit sloppy */
1214 count = return_command - *command_ptr;
1215 job->text = xmalloc(count + 1);
1216 strncpy(job->text, *command_ptr, count);
1217 job->text[count] = '\0';
1220 *command_ptr = return_command;
1225 /* Run the child_prog, no matter what kind of command it uses.
1227 static int pseudo_exec(struct child_prog *child)
1229 struct built_in_command *x;
1230 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
1234 /* Check if the command matches any of the non-forking builtins.
1235 * Depending on context, this might be redundant. But it's
1236 * easier to waste a few CPU cycles than it is to figure out
1237 * if this is one of those cases.
1239 for (x = bltins; x->cmd; x++) {
1240 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1241 _exit(x->function(child));
1245 /* Check if the command matches any of the forking builtins. */
1246 for (x = bltins_forking; x->cmd; x++) {
1247 if (strcmp(child->argv[0], x->cmd) == 0) {
1248 bb_applet_name=x->cmd;
1249 _exit (x->function(child));
1252 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
1253 /* Check if the command matches any busybox internal
1254 * commands ("applets") here. Following discussions from
1255 * November 2000 on busybox@busybox.net, don't use
1256 * bb_get_last_path_component(). This way explicit (with
1257 * slashes) filenames will never be interpreted as an
1258 * applet, just like with builtins. This way the user can
1259 * override an applet with an explicit filename reference.
1260 * The only downside to this change is that an explicit
1261 * /bin/foo invocation will fork and exec /bin/foo, even if
1262 * /bin/foo is a symlink to busybox.
1264 name = child->argv[0];
1267 char** argv_l=child->argv;
1269 #ifdef _NEWLIB_VERSION
1270 /* newlib uses __getopt_initialized for getopt() in
1271 * addition to optind, see newlib/libc/sys/linux/getopt.c
1273 extern int __getopt_initialized = 0;
1275 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++);
1277 run_applet_by_name(name, argc_l, child->argv);
1281 execvp(child->argv[0], child->argv);
1283 /* Do not use bb_perror_msg_and_die() here, since we must not
1284 * call exit() but should call _exit() instead */
1285 fprintf(stderr, "%s: %m\n", child->argv[0]);
1286 _exit(EXIT_FAILURE);
1289 static void insert_job(struct job *newjob, int inbg)
1292 struct jobset *j_list=newjob->job_list;
1294 /* find the ID for thejob to use */
1296 for (thejob = j_list->head; thejob; thejob = thejob->next)
1297 if (thejob->jobid >= newjob->jobid)
1298 newjob->jobid = thejob->jobid + 1;
1300 /* add thejob to the list of running jobs */
1301 if (!j_list->head) {
1302 thejob = j_list->head = xmalloc(sizeof(*thejob));
1304 for (thejob = j_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1305 thejob->next = xmalloc(sizeof(*thejob));
1306 thejob = thejob->next;
1309 *thejob = *newjob; /* physically copy the struct job */
1310 thejob->next = NULL;
1311 thejob->running_progs = thejob->num_progs;
1312 thejob->stopped_progs = 0;
1314 #ifdef CONFIG_LASH_JOB_CONTROL
1316 /* we don't wait for background thejobs to return -- append it
1317 to the list of backgrounded thejobs and leave it alone */
1318 printf("[%d] %d\n", thejob->jobid,
1319 newjob->progs[newjob->num_progs - 1].pid);
1320 last_jobid = newjob->jobid;
1321 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1323 newjob->job_list->fg = thejob;
1325 /* move the new process group into the foreground */
1326 /* suppress messages when run from /linuxrc mag@sysgo.de */
1327 if (tcsetpgrp(shell_terminal, newjob->pgrp) && errno != ENOTTY)
1328 bb_perror_msg("tcsetpgrp");
1333 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1335 /* struct job *thejob; */
1337 int nextin, nextout;
1338 int pipefds[2]; /* pipefd[0] is for reading */
1339 struct built_in_command *x;
1340 struct child_prog *child;
1342 nextin = 0, nextout = 1;
1343 for (i = 0; i < newjob->num_progs; i++) {
1344 child = & (newjob->progs[i]);
1346 if ((i + 1) < newjob->num_progs) {
1347 if (pipe(pipefds)<0) bb_perror_msg_and_die("pipe");
1348 nextout = pipefds[1];
1350 if (outpipe[1]!=-1) {
1351 nextout = outpipe[1];
1358 /* Check if the command matches any non-forking builtins,
1359 * but only if this is a simple command.
1360 * Non-forking builtins within pipes have to fork anyway,
1361 * and are handled in pseudo_exec. "echo foo | read bar"
1362 * is doomed to failure, and doesn't work on bash, either.
1364 if (newjob->num_progs == 1) {
1365 for (x = bltins; x->cmd; x++) {
1366 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1368 int squirrel[] = {-1, -1, -1};
1369 setup_redirects(child, squirrel);
1370 rcode = x->function(child);
1371 restore_redirects(squirrel);
1377 #if !defined(__UCLIBC__) || defined(__ARCH_HAS_MMU__)
1378 if (!(child->pid = fork()))
1380 if (!(child->pid = vfork()))
1383 /* Set the handling for job control signals back to the default. */
1384 signal(SIGINT, SIG_DFL);
1385 signal(SIGQUIT, SIG_DFL);
1386 signal(SIGTSTP, SIG_DFL);
1387 signal(SIGTTIN, SIG_DFL);
1388 signal(SIGTTOU, SIG_DFL);
1389 signal(SIGCHLD, SIG_DFL);
1393 if (outpipe[1]!=-1) {
1403 dup2(nextout, 2); /* Really? */
1408 /* explicit redirects override pipes */
1409 setup_redirects(child,NULL);
1413 if (outpipe[1]!=-1) {
1417 /* put our child in the process group whose leader is the
1418 first process in this pipe */
1419 setpgid(child->pid, newjob->progs[0].pid);
1425 /* If there isn't another process, nextin is garbage
1426 but it doesn't matter */
1427 nextin = pipefds[0];
1430 newjob->pgrp = newjob->progs[0].pid;
1432 insert_job(newjob, inbg);
1437 static int busy_loop(FILE * input)
1440 char *next_command = NULL;
1445 #ifdef CONFIG_LASH_JOB_CONTROL
1447 /* save current owner of TTY so we can restore it on exit */
1448 parent_pgrp = tcgetpgrp(shell_terminal);
1450 newjob.job_list = &job_list;
1451 newjob.job_context = DEFAULT_CONTEXT;
1453 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1457 /* no job is in the foreground */
1459 /* see if any background processes have exited */
1460 checkjobs(&job_list);
1462 if (!next_command) {
1463 if (get_command(input, command))
1465 next_command = command;
1468 if (! expand_arguments(next_command)) {
1470 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1471 next_command = NULL;
1475 if (!parse_command(&next_command, &newjob, &inbg) &&
1477 int pipefds[2] = {-1,-1};
1478 debug_printf( "job=%p fed to run_command by busy_loop()'\n",
1480 run_command(&newjob, inbg, pipefds);
1484 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1485 next_command = NULL;
1488 /* a job is running in the foreground; wait for it */
1490 while (!job_list.fg->progs[i].pid ||
1491 job_list.fg->progs[i].is_stopped == 1) i++;
1493 if (waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED)<0) {
1494 if (errno != ECHILD) {
1495 bb_perror_msg_and_die("waitpid(%d)",job_list.fg->progs[i].pid);
1499 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1500 /* the child exited */
1501 job_list.fg->running_progs--;
1502 job_list.fg->progs[i].pid = 0;
1504 last_return_code=WEXITSTATUS(status);
1506 if (!job_list.fg->running_progs) {
1508 remove_job(&job_list, job_list.fg);
1512 #ifdef CONFIG_LASH_JOB_CONTROL
1514 /* the child was stopped */
1515 job_list.fg->stopped_progs++;
1516 job_list.fg->progs[i].is_stopped = 1;
1518 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1519 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1520 "Stopped", job_list.fg->text);
1526 /* move the shell to the foreground */
1527 /* suppress messages when run from /linuxrc mag@sysgo.de */
1528 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
1529 bb_perror_msg("tcsetpgrp");
1536 #ifdef CONFIG_LASH_JOB_CONTROL
1537 /* return controlling TTY back to parent process group before exiting */
1538 if (tcsetpgrp(shell_terminal, parent_pgrp) && errno != ENOTTY)
1539 bb_perror_msg("tcsetpgrp");
1542 /* return exit status if called with "-c" */
1543 if (input == NULL && WIFEXITED(status))
1544 return WEXITSTATUS(status);
1549 #ifdef CONFIG_FEATURE_CLEAN_UP
1550 static void free_memory(void)
1552 if (cwd && cwd!=bb_msg_unknown) {
1555 if (local_pending_command)
1556 free(local_pending_command);
1558 if (job_list.fg && !job_list.fg->running_progs) {
1559 remove_job(&job_list, job_list.fg);
1564 #ifdef CONFIG_LASH_JOB_CONTROL
1565 /* Make sure we have a controlling tty. If we get started under a job
1566 * aware app (like bash for example), make sure we are now in charge so
1567 * we don't fight over who gets the foreground */
1568 static void setup_job_control(void)
1573 /* Loop until we are in the foreground. */
1574 while ((status = tcgetpgrp (shell_terminal)) >= 0) {
1575 if (status == (shell_pgrp = getpgrp ())) {
1578 kill (- shell_pgrp, SIGTTIN);
1581 /* Ignore interactive and job-control signals. */
1582 signal(SIGINT, SIG_IGN);
1583 signal(SIGQUIT, SIG_IGN);
1584 signal(SIGTSTP, SIG_IGN);
1585 signal(SIGTTIN, SIG_IGN);
1586 signal(SIGTTOU, SIG_IGN);
1587 signal(SIGCHLD, SIG_IGN);
1589 /* Put ourselves in our own process group. */
1591 shell_pgrp = getpid ();
1592 setpgid (shell_pgrp, shell_pgrp);
1594 /* Grab control of the terminal. */
1595 tcsetpgrp(shell_terminal, shell_pgrp);
1598 static inline void setup_job_control(void)
1603 int lash_main(int argc_l, char **argv_l)
1605 int opt, interactive=FALSE;
1606 FILE *input = stdin;
1610 /* These variables need re-initializing when recursing */
1612 local_pending_command = NULL;
1613 close_me_head = NULL;
1614 job_list.head = NULL;
1618 if (argv[0] && argv[0][0] == '-') {
1620 prof_input = fopen("/etc/profile", "r");
1622 int tmp_fd = fileno(prof_input);
1624 /* Now run the file */
1625 busy_loop(prof_input);
1627 mark_closed(tmp_fd);
1631 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1635 if (local_pending_command != 0)
1636 bb_error_msg_and_die("multiple -c arguments");
1637 local_pending_command = bb_xstrdup(argv[optind]);
1648 /* A shell is interactive if the `-i' flag was given, or if all of
1649 * the following conditions are met:
1651 * no arguments remaining or the -s flag given
1652 * standard input is a terminal
1653 * standard output is a terminal
1654 * Refer to Posix.2, the description of the `sh' utility. */
1655 if (argv[optind]==NULL && input==stdin &&
1656 isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
1659 setup_job_control();
1660 if (interactive==TRUE) {
1661 //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1662 /* Looks like they want an interactive shell */
1663 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1664 printf( "\n\n%s Built-in shell (lash)\n", BB_BANNER);
1665 printf( "Enter 'help' for a list of built-in commands.\n\n");
1667 } else if (local_pending_command==NULL) {
1668 //printf( "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1669 input = bb_xfopen(argv[optind], "r");
1670 mark_open(fileno(input)); /* be lazy, never mark this closed */
1673 /* initialize the cwd -- this is never freed...*/
1676 cwd = bb_msg_unknown;
1678 #ifdef CONFIG_FEATURE_CLEAN_UP
1679 atexit(free_memory);
1682 #ifdef CONFIG_FEATURE_COMMAND_EDITING
1683 cmdedit_set_initial_prompt();
1688 return (busy_loop(input));