1 /* vi: set sw=4 ts=4: */
3 * lash -- the BusyBox Lame-Ass SHell
5 * Copyright (C) 2000 by Lineo, inc.
6 * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
8 * Based in part on ladsh.c by Michael K. Johnson and Erik W. Troan, which is
9 * under the following liberal license: "We have placed this source code in the
10 * public domain. Use it in any project, free or commercial."
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 //This works pretty well now, and is not on by default.
30 #define BB_FEATURE_SH_ENVIRONMENT
32 //Backtick support has some problems, use at your own risk!
33 //#define BB_FEATURE_SH_BACKTICKS
35 //If, then, else, etc. support.. This should now behave basically
36 //like any other Bourne shell...
37 //#define BB_FEATURE_SH_IF_EXPRESSIONS
39 /* This is currently a little broken... */
40 //#define HANDLE_CONTINUATION_CHARS
42 //For debugging/development on the shell only...
55 #include <sys/ioctl.h>
61 #define MAX_LINE 256 /* size of input buffer for cwd data */
62 #define MAX_READ 128 /* size of input buffer for `read' builtin */
63 #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
64 extern size_t NUM_APPLETS;
67 enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
71 static const unsigned int DEFAULT_CONTEXT=0x1;
72 static const unsigned int IF_TRUE_CONTEXT=0x2;
73 static const unsigned int IF_FALSE_CONTEXT=0x4;
74 static const unsigned int THEN_EXP_CONTEXT=0x8;
75 static const unsigned int ELSE_EXP_CONTEXT=0x10;
76 unsigned int shell_context = 0;
81 struct job *head; /* head of list of running jobs */
82 struct job *fg; /* current foreground job */
86 enum redir_type type; /* type of redirection */
87 int fd; /* file descriptor being redirected */
88 char *filename; /* file to redirect fd to */
92 pid_t pid; /* 0 if exited */
93 char **argv; /* program name and arguments */
94 int num_redirects; /* elements in redirection array */
95 struct redir_struct *redirects; /* I/O redirects */
96 glob_t glob_result; /* result of parameter globbing */
97 int free_glob; /* should we globfree(&glob_result)? */
98 int is_stopped; /* is the program currently running? */
99 struct job *family; /* pointer back to the child's parent job */
103 int jobid; /* job number */
104 int num_progs; /* total number of programs in job */
105 int running_progs; /* number of programs running */
106 char *text; /* name of job */
107 char *cmdbuf; /* buffer various argv's point into */
108 pid_t pgrp; /* process group ID for the job */
109 struct child_prog *progs; /* array of programs in job */
110 struct job *next; /* to track background commands */
111 int stopped_progs; /* number of programs alive, but stopped */
112 unsigned int job_context; /* bitmask defining current context */
113 struct jobset *job_list;
116 struct built_in_command {
117 char *cmd; /* name */
118 char *descr; /* description */
119 int (*function) (struct child_prog *); /* function ptr */
122 /* function prototypes for builtins */
123 static int builtin_cd(struct child_prog *cmd);
124 static int builtin_env(struct child_prog *dummy);
125 static int builtin_exec(struct child_prog *cmd);
126 static int builtin_exit(struct child_prog *cmd);
127 static int builtin_fg_bg(struct child_prog *cmd);
128 static int builtin_help(struct child_prog *cmd);
129 static int builtin_jobs(struct child_prog *dummy);
130 static int builtin_pwd(struct child_prog *dummy);
131 static int builtin_export(struct child_prog *cmd);
132 static int builtin_source(struct child_prog *cmd);
133 static int builtin_unset(struct child_prog *cmd);
134 static int builtin_read(struct child_prog *cmd);
135 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
136 static int builtin_if(struct child_prog *cmd);
137 static int builtin_then(struct child_prog *cmd);
138 static int builtin_else(struct child_prog *cmd);
139 static int builtin_fi(struct child_prog *cmd);
143 /* function prototypes for shell stuff */
144 static void checkjobs(struct jobset *job_list);
145 static int get_command(FILE * source, char *command);
146 static int parse_command(char **command_ptr, struct job *job, int *inbg);
147 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
148 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
149 static int run_command_predicate(char *cmd);
150 static int busy_loop(FILE * input);
153 /* Table of built-in functions (these are non-forking builtins, meaning they
154 * can change global variables in the parent shell process but they will not
155 * work with pipes and redirects; 'unset foo | whatever' will not work) */
156 static struct built_in_command bltins[] = {
157 {"bg", "Resume a job in the background", builtin_fg_bg},
158 {"cd", "Change working directory", builtin_cd},
159 {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
160 {"exit", "Exit from shell()", builtin_exit},
161 {"fg", "Bring job into the foreground", builtin_fg_bg},
162 {"jobs", "Lists the active jobs", builtin_jobs},
163 {"export", "Set environment variable", builtin_export},
164 {"unset", "Unset environment variable", builtin_unset},
165 {"read", "Input environment variable", builtin_read},
166 {".", "Source-in and run commands in a file", builtin_source},
167 /* to do: add ulimit */
168 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
169 {"if", NULL, builtin_if},
170 {"then", NULL, builtin_then},
171 {"else", NULL, builtin_else},
172 {"fi", NULL, builtin_fi},
177 /* Table of forking built-in functions (things that fork cannot change global
178 * variables in the parent process, such as the current working directory) */
179 static struct built_in_command bltins_forking[] = {
180 {"env", "Print all environment variables", builtin_env},
181 {"pwd", "Print current directory", builtin_pwd},
182 {"help", "List shell built-in commands", builtin_help},
186 static char prompt[3];
188 static char *local_pending_command = NULL;
189 static char *prompt_str = NULL;
190 static struct jobset job_list = { NULL, NULL };
193 #ifdef BB_FEATURE_SH_ENVIRONMENT
194 static int last_bg_pid=-1;
195 static int last_return_code=-1;
196 static int show_x_trace=FALSE;
198 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
199 static char syntax_err[]="syntax error near unexpected token";
203 static inline void debug_printf(const char *format, ...)
206 va_start(args, format);
207 vfprintf(stderr, format, args);
211 static inline void debug_printf(const char *format, ...) { }
214 #ifdef BB_FEATURE_SH_COMMAND_EDITING
215 static inline void win_changed(int junk)
217 struct winsize win = { 0, 0, 0, 0 };
218 ioctl(0, TIOCGWINSZ, &win);
219 if (win.ws_col > 0) {
220 cmdedit_setwidth( win.ws_col - 1);
224 static inline void win_changed(int junk) {}
228 Most builtins need access to the struct child_prog that has
229 their arguments, previously coded as cmd->progs[0]. That coding
230 can exhibit a bug, if the builtin is not the first command in
231 a pipeline: "echo foo | exec sort" will attempt to exec foo.
233 builtin previous use notes
234 ------ ----------------- ---------
237 exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins
239 fg_bg cmd->progs[0], job_list->head, job_list->fg
243 export cmd->progs[0] passes cmd, job_list to builtin_env(), which ignores them
247 if cmd->job_context, cmd->text
248 then cmd->job_context, cmd->text
249 else cmd->job_context, cmd->text
252 The use of cmd->text by if/then/else/fi is hopelessly hacky.
253 Would it work to increment cmd->progs[0]->argv and recurse,
254 somewhat like builtin_exec does?
256 I added "struct job *family;" to struct child_prog,
257 and switched API to builtin_foo(struct child_prog *child);
258 So cmd->text becomes child->family->text
259 cmd->job_context becomes child->family->job_context
260 cmd->progs[0] becomes *child
261 job_list becomes child->family->job_list
264 /* built-in 'cd <path>' handler */
265 static int builtin_cd(struct child_prog *child)
269 if (child->argv[1] == NULL)
270 newdir = getenv("HOME");
272 newdir = child->argv[1];
274 printf("cd: %s: %s\n", newdir, strerror(errno));
277 getcwd(cwd, sizeof(char)*MAX_LINE);
282 /* built-in 'env' handler */
283 static int builtin_env(struct child_prog *dummy)
287 for (e = environ; *e; e++) {
288 fprintf(stdout, "%s\n", *e);
293 /* built-in 'exec' handler */
294 static int builtin_exec(struct child_prog *child)
296 if (child->argv[1] == NULL)
297 return EXIT_SUCCESS; /* Really? */
303 /* built-in 'exit' handler */
304 static int builtin_exit(struct child_prog *child)
306 if (child->argv[1] == NULL)
309 exit (atoi(child->argv[1]));
312 /* built-in 'fg' and 'bg' handler */
313 static int builtin_fg_bg(struct child_prog *child)
316 struct job *job=NULL;
319 if (!child->argv[1] || child->argv[2]) {
320 error_msg("%s: exactly one argument is expected\n",
324 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
325 error_msg("%s: bad argument '%s'\n",
326 child->argv[0], child->argv[1]);
329 for (job = child->family->job_list->head; job; job = job->next) {
330 if (job->jobid == jobNum) {
336 error_msg("%s: unknown job %d\n",
337 child->argv[0], jobNum);
341 if (*child->argv[0] == 'f') {
342 /* Make this job the foreground job */
343 /* suppress messages when run from /linuxrc mag@sysgo.de */
344 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
346 child->family->job_list->fg = job;
349 /* Restart the processes in the job */
350 for (i = 0; i < job->num_progs; i++)
351 job->progs[i].is_stopped = 0;
353 kill(-job->pgrp, SIGCONT);
355 job->stopped_progs = 0;
360 /* built-in 'help' handler */
361 static int builtin_help(struct child_prog *dummy)
363 struct built_in_command *x;
365 printf("\nBuilt-in commands:\n");
366 printf("-------------------\n");
367 for (x = bltins; x->cmd; x++) {
370 printf("%s\t%s\n", x->cmd, x->descr);
372 for (x = bltins_forking; x->cmd; x++) {
375 printf("%s\t%s\n", x->cmd, x->descr);
381 /* built-in 'jobs' handler */
382 static int builtin_jobs(struct child_prog *child)
387 for (job = child->family->job_list->head; job; job = job->next) {
388 if (job->running_progs == job->stopped_progs)
389 status_string = "Stopped";
391 status_string = "Running";
393 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
399 /* built-in 'pwd' handler */
400 static int builtin_pwd(struct child_prog *dummy)
402 getcwd(cwd, MAX_LINE);
403 fprintf(stdout, "%s\n", cwd);
407 /* built-in 'export VAR=value' handler */
408 static int builtin_export(struct child_prog *child)
412 if (child->argv[1] == NULL) {
413 return (builtin_env(child));
415 res = putenv(child->argv[1]);
417 fprintf(stderr, "export: %s\n", strerror(errno));
421 /* built-in 'read VAR' handler */
422 static int builtin_read(struct child_prog *child)
424 int res = 0, len, newlen;
426 char string[MAX_READ];
428 if (child->argv[1]) {
429 /* argument (VAR) given: put "VAR=" into buffer */
430 strcpy(string, child->argv[1]);
431 len = strlen(string);
434 fgets(&string[len], sizeof(string) - len, stdin); /* read string */
435 newlen = strlen(string);
437 string[--newlen] = '\0'; /* chomp trailing newline */
439 ** string should now contain "VAR=<value>"
440 ** copy it (putenv() won't do that, so we must make sure
441 ** the string resides in a static buffer!)
444 if((s = strdup(string)))
447 fprintf(stderr, "read: %s\n", strerror(errno));
450 fgets(string, sizeof(string), stdin);
455 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
456 /* Built-in handler for 'if' commands */
457 static int builtin_if(struct child_prog *child)
459 struct job *cmd = child->family;
461 char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
463 /* Now run the 'if' command */
464 debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
465 status = run_command_predicate(charptr1);
466 debug_printf( "if test returned ");
468 debug_printf( "TRUE\n");
469 cmd->job_context |= IF_TRUE_CONTEXT;
471 debug_printf( "FALSE\n");
472 cmd->job_context |= IF_FALSE_CONTEXT;
474 debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
480 /* Built-in handler for 'then' (part of the 'if' command) */
481 static int builtin_then(struct child_prog *child)
483 struct job *cmd = child->family;
484 char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
486 debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
487 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
488 shell_context = 0; /* Reset the shell's context on an error */
489 error_msg("%s `then'\n", syntax_err);
493 cmd->job_context |= THEN_EXP_CONTEXT;
494 debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
496 /* If the if result was FALSE, skip the 'then' stuff */
497 if (cmd->job_context & IF_FALSE_CONTEXT) {
501 /* Seems the if result was TRUE, so run the 'then' command */
502 debug_printf( "'then' now running '%s'\n", charptr1);
504 return(run_command_predicate(charptr1));
507 /* Built-in handler for 'else' (part of the 'if' command) */
508 static int builtin_else(struct child_prog *child)
510 struct job *cmd = child->family;
511 char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
513 debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
515 if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
516 shell_context = 0; /* Reset the shell's context on an error */
517 error_msg("%s `else'\n", syntax_err);
520 /* If the if result was TRUE, skip the 'else' stuff */
521 if (cmd->job_context & IF_TRUE_CONTEXT) {
525 cmd->job_context |= ELSE_EXP_CONTEXT;
526 debug_printf("job=%p builtin_else set job context to %x\n", child->family, cmd->job_context);
528 /* Now run the 'else' command */
529 debug_printf( "'else' now running '%s'\n", charptr1);
530 return(run_command_predicate(charptr1));
533 /* Built-in handler for 'fi' (part of the 'if' command) */
534 static int builtin_fi(struct child_prog *child)
536 struct job *cmd = child->family;
537 debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
538 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
539 shell_context = 0; /* Reset the shell's context on an error */
540 error_msg("%s `fi'\n", syntax_err);
543 /* Clear out the if and then context bits */
544 cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
545 debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
551 /* Built-in '.' handler (read-in and execute commands from file) */
552 static int builtin_source(struct child_prog *child)
557 if (child->argv[1] == NULL)
560 input = fopen(child->argv[1], "r");
562 fprintf(stdout, "Couldn't open file '%s'\n", child->argv[1]);
566 /* Now run the file */
567 status = busy_loop(input);
572 /* built-in 'unset VAR' handler */
573 static int builtin_unset(struct child_prog *child)
575 if (child->argv[1] == NULL) {
576 fprintf(stdout, "unset: parameter required.\n");
579 unsetenv(child->argv[1]);
583 /* currently used by if/then/else.
584 * Needlessly (?) forks and reparses the command line.
585 * But pseudo_exec on the pre-parsed args doesn't have the
586 * "fork, stick around until the child exits, and find it's return code"
587 * functionality. The fork is not needed if the predicate is
588 * non-forking builtin, and maybe not even if it's a forking builtin.
589 * applets pretty clearly need the fork.
591 static int run_command_predicate(char *cmd)
594 local_pending_command = xmalloc(n+1);
595 strncpy(local_pending_command, cmd, n);
596 local_pending_command[n]='\0';
597 return( busy_loop(NULL));
600 /* free up all memory from a job */
601 static void free_job(struct job *cmd)
605 for (i = 0; i < cmd->num_progs; i++) {
606 free(cmd->progs[i].argv);
607 if (cmd->progs[i].redirects)
608 free(cmd->progs[i].redirects);
609 if (cmd->progs[i].free_glob)
610 globfree(&cmd->progs[i].glob_result);
616 memset(cmd, 0, sizeof(struct job));
619 /* remove a job from the job_list */
620 static void remove_job(struct jobset *job_list, struct job *job)
625 if (job == job_list->head) {
626 job_list->head = job->next;
628 prevjob = job_list->head;
629 while (prevjob->next != job)
630 prevjob = prevjob->next;
631 prevjob->next = job->next;
637 /* Checks to see if any background processes have exited -- if they
638 have, figure out why and see if a job has completed */
639 static void checkjobs(struct jobset *job_list)
646 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
647 for (job = job_list->head; job; job = job->next) {
649 while (prognum < job->num_progs &&
650 job->progs[prognum].pid != childpid) prognum++;
651 if (prognum < job->num_progs)
655 /* This happens on backticked commands */
659 if (WIFEXITED(status) || WIFSIGNALED(status)) {
661 job->running_progs--;
662 job->progs[prognum].pid = 0;
664 if (!job->running_progs) {
665 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
666 remove_job(job_list, job);
670 job->stopped_progs++;
671 job->progs[prognum].is_stopped = 1;
673 if (job->stopped_progs == job->num_progs) {
674 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
680 if (childpid == -1 && errno != ECHILD)
684 static int setup_redirects(struct child_prog *prog)
689 struct redir_struct *redir = prog->redirects;
691 for (i = 0; i < prog->num_redirects; i++, redir++) {
692 switch (redir->type) {
696 case REDIRECT_OVERWRITE:
697 mode = O_WRONLY | O_CREAT | O_TRUNC;
699 case REDIRECT_APPEND:
700 mode = O_WRONLY | O_CREAT | O_APPEND;
704 openfd = open(redir->filename, mode, 0666);
706 /* this could get lost if stderr has been redirected, but
707 bash and ash both lose it as well (though zsh doesn't!) */
708 error_msg("error opening %s: %s\n", redir->filename,
713 if (openfd != redir->fd) {
714 dup2(openfd, redir->fd);
723 static int get_command(FILE * source, char *command)
725 char user[9],buf[255],*s;
727 if (source == NULL) {
728 if (local_pending_command) {
729 /* a command specified (-c option): return it & mark it done */
730 strcpy(command, local_pending_command);
731 free(local_pending_command);
732 local_pending_command = NULL;
738 if (shell_context == 0) {
739 /* get User Name and setup prompt */
740 strcpy(prompt,( geteuid() != 0 ) ? "$ ":"# ");
741 my_getpwuid(user, geteuid());
744 gethostname(buf, 255);
745 s = strchr(buf, '.');
753 if (source == stdin) {
754 #ifdef BB_FEATURE_SH_COMMAND_EDITING
758 ** enable command line editing only while a command line
759 ** is actually being read; otherwise, we'll end up bequeathing
760 ** atexit() handlers and other unwanted stuff to our
761 ** child processes (rob@sysgo.de)
764 signal(SIGWINCH, win_changed);
765 debug_printf( "in get_command() -- job_context=%d\n", shell_context);
767 if (shell_context == 0) {
768 len=fprintf(stdout, "[%s@%s %s]%s", user, buf,
769 get_last_path_component(cwd), prompt);
771 len=fprintf(stdout, "%s", prompt);
774 prompt_str=(char*)xmalloc(sizeof(char)*(len+1));
775 if (shell_context == 0) {
776 sprintf(prompt_str, "[%s@%s %s]%s", user, buf,
777 get_last_path_component(cwd), prompt);
779 sprintf(prompt_str, "%s", prompt);
781 cmdedit_read_input(prompt_str, command);
784 signal(SIGWINCH, SIG_DFL);
790 while ((i>0) && (*(cwd+i)!='/') ) i--;
791 if (*(cwd+i)=='/') i++;
794 fprintf(stdout, "[%s@%s %s]%s",user, buf, (cwd+i), prompt);
799 if (!fgets(command, BUFSIZ - 2, source)) {
805 /* remove trailing newline */
806 command[strlen(command) - 1] = '\0';
811 #ifdef BB_FEATURE_SH_ENVIRONMENT
812 static char* itoa(register int i)
814 static char a[7]; /* Max 7 ints */
815 register char *b = a + sizeof(a) - 1;
823 *--b = '0' + (i % 10);
833 static void expand_argument(struct child_prog *prog, int *argcPtr,
834 int *argv_alloced_ptr)
836 int argc_l = *argcPtr;
837 int argv_alloced = *argv_alloced_ptr;
841 char *src, *dst, *var;
843 if (argc_l > 1) { /* cmd->glob_result is already initialized */
845 i = prog->glob_result.gl_pathc;
851 /* do shell variable substitution */
852 if(*prog->argv[argc_l - 1] == '$') {
853 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
854 prog->argv[argc_l - 1] = var;
856 #ifdef BB_FEATURE_SH_ENVIRONMENT
858 switch(*(prog->argv[argc_l - 1] + 1)) {
860 prog->argv[argc_l - 1] = itoa(last_return_code);
863 prog->argv[argc_l - 1] = itoa(getpid());
866 prog->argv[argc_l - 1] = itoa(argc-1);
870 *(prog->argv[argc_l - 1])='\0';
872 prog->argv[argc_l - 1] = itoa(last_bg_pid);
874 case '0':case '1':case '2':case '3':case '4':
875 case '5':case '6':case '7':case '8':case '9':
877 int index=*(prog->argv[argc_l - 1] + 1)-48;
879 *(prog->argv[argc_l - 1])='\0';
881 prog->argv[argc_l - 1] = argv[index];
890 if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
891 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
892 if (rc == GLOB_NOSPACE) {
893 error_msg("out of space during glob operation\n");
895 } else if (rc == GLOB_NOMATCH ||
896 (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
897 strcmp(prog->argv[argc_l - 1],
898 prog->glob_result.gl_pathv[i]) == 0)) {
899 /* we need to remove whatever \ quoting is still present */
900 src = dst = prog->argv[argc_l - 1];
904 *dst++ = process_escape_sequence(&src);
912 argv_alloced += (prog->glob_result.gl_pathc - i);
913 prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
914 memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
915 sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
916 argc_l += (prog->glob_result.gl_pathc - i - 1);
919 src = dst = prog->argv[argc_l - 1];
923 *dst++ = process_escape_sequence(&src);
931 prog->glob_result.gl_pathc=0;
933 prog->glob_result.gl_pathv=NULL;
935 *argv_alloced_ptr = argv_alloced;
939 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
940 line). If a valid command is found, command_ptr is set to point to
941 the beginning of the next command (if the original command had more
942 then one job associated with it) or NULL if no more commands are
944 static int parse_command(char **command_ptr, struct job *job, int *inbg)
947 char *return_command = NULL;
948 char *src, *buf, *chptr;
955 struct child_prog *prog;
957 /* skip leading white space */
958 while (**command_ptr && isspace(**command_ptr))
961 /* this handles empty lines or leading '#' characters */
962 if (!**command_ptr || (**command_ptr == '#')) {
969 job->progs = xmalloc(sizeof(*job->progs));
971 /* We set the argv elements to point inside of this string. The
972 memory is freed by free_job(). Allocate twice the original
973 length in case we need to quote every single character.
975 Getting clean memory relieves us of the task of NULL
976 terminating things and makes the rest of this look a bit
977 cleaner (though it is, admittedly, a tad less efficient) */
978 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
982 prog->num_redirects = 0;
983 prog->redirects = NULL;
985 prog->is_stopped = 0;
989 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
990 prog->argv[0] = job->cmdbuf;
994 while (*src && !done) {
1001 error_msg("character expected after \\\n");
1006 /* in shell, "\'" should yield \' */
1007 if (*src != quote) {
1011 } else if (*src == '*' || *src == '?' || *src == '[' ||
1012 *src == ']') *buf++ = '\\';
1014 } else if (isspace(*src)) {
1015 if (*prog->argv[argc_l]) {
1017 /* +1 here leaves room for the NULL which ends argv */
1018 if ((argc_l + 1) == argv_alloced) {
1020 prog->argv = xrealloc(prog->argv,
1021 sizeof(*prog->argv) *
1024 expand_argument(prog, &argc_l, &argv_alloced);
1025 prog->argv[argc_l] = buf;
1034 case '#': /* comment */
1041 case '>': /* redirects */
1043 i = prog->num_redirects++;
1044 prog->redirects = xrealloc(prog->redirects,
1045 sizeof(*prog->redirects) *
1048 prog->redirects[i].fd = -1;
1049 if (buf != prog->argv[argc_l]) {
1050 /* the stuff before this character may be the file number
1052 prog->redirects[i].fd =
1053 strtol(prog->argv[argc_l], &chptr, 10);
1055 if (*chptr && *prog->argv[argc_l]) {
1057 expand_argument(prog, &argc_l, &argv_alloced);
1058 prog->argv[argc_l] = buf;
1062 if (prog->redirects[i].fd == -1) {
1064 prog->redirects[i].fd = 1;
1066 prog->redirects[i].fd = 0;
1069 if (*src++ == '>') {
1071 prog->redirects[i].type =
1072 REDIRECT_APPEND, src++;
1074 prog->redirects[i].type = REDIRECT_OVERWRITE;
1076 prog->redirects[i].type = REDIRECT_INPUT;
1079 /* This isn't POSIX sh compliant. Oh well. */
1081 while (isspace(*chptr))
1085 error_msg("file name expected after %c\n", *src);
1091 prog->redirects[i].filename = buf;
1092 while (*chptr && !isspace(*chptr))
1095 src = chptr - 1; /* we src++ later */
1096 prog->argv[argc_l] = ++buf;
1099 case '|': /* pipe */
1100 /* finish this command */
1101 if (*prog->argv[argc_l])
1104 error_msg("empty command in pipe\n");
1109 prog->argv[argc_l] = NULL;
1111 /* and start the next */
1113 job->progs = xrealloc(job->progs,
1114 sizeof(*job->progs) * job->num_progs);
1115 prog = job->progs + (job->num_progs - 1);
1116 prog->num_redirects = 0;
1117 prog->redirects = NULL;
1118 prog->free_glob = 0;
1119 prog->is_stopped = 0;
1124 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1125 prog->argv[0] = ++buf;
1128 while (*src && isspace(*src))
1132 error_msg("empty command in pipe\n");
1137 src--; /* we'll ++ it at the end of the loop */
1141 case '&': /* background */
1143 case ';': /* multiple commands */
1145 return_command = *command_ptr + (src - *command_ptr) + 1;
1148 #ifdef BB_FEATURE_SH_BACKTICKS
1150 /* Exec a backtick-ed command */
1152 char* charptr1=NULL, *charptr2;
1155 struct jobset njob_list = { NULL, NULL };
1159 ptr=strchr(++src, '`');
1161 fprintf(stderr, "Unmatched '`' in command\n");
1166 /* Make some space to hold just the backticked command */
1167 charptr1 = charptr2 = xmalloc(1+ptr-src);
1168 memcpy(charptr1, src, ptr-src);
1169 charptr1[ptr-src] = '\0';
1170 newjob = xmalloc(sizeof(struct job));
1171 newjob->job_list = &njob_list;
1172 /* Now parse and run the backticked command */
1173 if (!parse_command(&charptr1, newjob, inbg)
1174 && newjob->num_progs) {
1176 run_command(newjob, 0, pipefd);
1178 checkjobs(job->job_list);
1179 free_job(newjob); /* doesn't actually free newjob,
1180 looks like a memory leak */
1183 /* Make a copy of any stuff left over in the command
1184 * line after the second backtick */
1185 charptr2 = xmalloc(strlen(ptr)+1);
1186 memcpy(charptr2, ptr+1, strlen(ptr));
1189 /* Copy the output from the backtick-ed command into the
1190 * command line, making extra room as needed */
1192 charptr1 = xmalloc(BUFSIZ);
1193 while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1194 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1195 if (newsize > BUFSIZ) {
1196 *command_ptr=xrealloc(*command_ptr, newsize);
1198 memcpy(src, charptr1, size);
1206 /* Now paste into the *command_ptr all the stuff
1207 * leftover after the second backtick */
1208 memcpy(src, charptr2, strlen(charptr2)+1);
1211 /* Now recursively call parse_command to deal with the new
1212 * and improved version of the command line with the backtick
1213 * results expanded in place... */
1215 struct jobset *jl=job->job_list;
1219 return(parse_command(command_ptr, job, inbg));
1222 #endif // BB_FEATURE_SH_BACKTICKS
1227 /* This is currently a little broken... */
1228 #ifdef HANDLE_CONTINUATION_CHARS
1229 /* They fed us a continuation char, so continue reading stuff
1230 * on the next line, then tack that onto the end of the current
1234 printf("erik: found a continue char at EOL...\n");
1235 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1236 if (get_command(input, command)) {
1237 error_msg("character expected after \\\n");
1242 newsize = strlen(*command_ptr) + strlen(command) + 2;
1243 if (newsize > BUFSIZ) {
1244 printf("erik: doing realloc\n");
1245 *command_ptr=xrealloc(*command_ptr, newsize);
1247 printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1248 memcpy(--src, command, strlen(command));
1249 printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1253 error_msg("character expected after \\\n");
1259 if (*src == '*' || *src == '[' || *src == ']'
1260 || *src == '?') *buf++ = '\\';
1269 if (*prog->argv[argc_l]) {
1271 expand_argument(prog, &argc_l, &argv_alloced);
1277 prog->argv[argc_l] = NULL;
1279 if (!return_command) {
1280 job->text = xmalloc(strlen(*command_ptr) + 1);
1281 strcpy(job->text, *command_ptr);
1283 /* This leaves any trailing spaces, which is a bit sloppy */
1284 count = return_command - *command_ptr;
1285 job->text = xmalloc(count + 1);
1286 strncpy(job->text, *command_ptr, count);
1287 job->text[count] = '\0';
1290 *command_ptr = return_command;
1295 /* Run the child_prog, no matter what kind of command it uses.
1297 static int pseudo_exec(struct child_prog *child)
1299 struct built_in_command *x;
1300 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1301 struct BB_applet search_applet, *applet;
1304 /* Check if the command matches any of the forking builtins.
1305 * XXX It would probably be wise to check for non-forking builtins
1306 * here as well, since in some context the non-forking path
1307 * is disabled or bypassed. See comment in run_command.
1309 for (x = bltins_forking; x->cmd; x++) {
1310 if (strcmp(child->argv[0], x->cmd) == 0) {
1312 exit (x->function(child));
1315 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1316 /* Check if the command matches any busybox internal
1317 * commands ("applets") here. Following discussions from
1318 * November 2000 on busybox@opensource.lineo.com, don't use
1319 * get_last_path_component(). This way explicit (with
1320 * slashes) filenames will never be interpreted as an
1321 * applet, just like with builtins. This way the user can
1322 * override an applet with an explicit filename reference.
1323 * The only downside to this change is that an explicit
1324 * /bin/foo invocation will fork and exec /bin/foo, even if
1325 * /bin/foo is a symlink to busybox.
1327 search_applet.name = child->argv[0];
1329 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1330 /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1331 * if you run /bin/cat, it will use BusyBox cat even if
1332 * /bin/cat exists on the filesystem and is _not_ busybox.
1333 * Some systems want this, others do not. Choose wisely. :-)
1335 search_applet.name = get_last_path_component(search_applet.name);
1338 /* Do a binary search to find the applet entry given the name. */
1339 applet = bsearch(&search_applet, applets, NUM_APPLETS,
1340 sizeof(struct BB_applet), applet_name_compare);
1341 if (applet != NULL) {
1343 char** argv=child->argv;
1344 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1345 applet_name=applet->name;
1347 exit((*(applet->main)) (argc_l, child->argv));
1351 execvp(child->argv[0], child->argv);
1352 error_msg_and_die("%s: %s\n", child->argv[0],
1356 static void insert_job(struct job *newjob, int inbg)
1359 struct jobset *job_list=newjob->job_list;
1361 /* find the ID for thejob to use */
1363 for (thejob = job_list->head; thejob; thejob = thejob->next)
1364 if (thejob->jobid >= newjob->jobid)
1365 newjob->jobid = thejob->jobid + 1;
1367 /* add thejob to the list of running jobs */
1368 if (!job_list->head) {
1369 thejob = job_list->head = xmalloc(sizeof(*thejob));
1371 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1372 thejob->next = xmalloc(sizeof(*thejob));
1373 thejob = thejob->next;
1376 *thejob = *newjob; /* physically copy the struct job */
1377 thejob->next = NULL;
1378 thejob->running_progs = thejob->num_progs;
1379 thejob->stopped_progs = 0;
1382 /* we don't wait for background thejobs to return -- append it
1383 to the list of backgrounded thejobs and leave it alone */
1384 printf("[%d] %d\n", thejob->jobid,
1385 newjob->progs[newjob->num_progs - 1].pid);
1386 #ifdef BB_FEATURE_SH_ENVIRONMENT
1387 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1390 newjob->job_list->fg = thejob;
1392 /* move the new process group into the foreground */
1393 /* suppress messages when run from /linuxrc mag@sysgo.de */
1394 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1395 perror("tcsetpgrp");
1399 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1401 /* struct job *thejob; */
1403 int nextin, nextout;
1404 int pipefds[2]; /* pipefd[0] is for reading */
1405 struct built_in_command *x;
1406 struct child_prog *child;
1408 nextin = 0, nextout = 1;
1409 for (i = 0; i < newjob->num_progs; i++) {
1410 child = & (newjob->progs[i]);
1412 if ((i + 1) < newjob->num_progs) {
1413 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1414 nextout = pipefds[1];
1416 if (outpipe[1]!=-1) {
1417 nextout = outpipe[1];
1423 #ifdef BB_FEATURE_SH_ENVIRONMENT
1424 if (show_x_trace==TRUE) {
1427 for (j = 0; child->argv[j]; j++) {
1429 fputs(child->argv[j], stderr);
1431 fputc('\n', stderr);
1435 /* Check if the command matches any non-forking builtins.
1436 * XXX should probably skip this test, and fork anyway, if
1437 * there redirects of some kind demand forking to work right.
1438 * pseudo_exec would then need to handle the non-forking command
1439 * in a forked context.
1441 for (x = bltins; x->cmd; x++) {
1442 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1443 return(x->function(child));
1447 if (!(child->pid = fork())) {
1448 signal(SIGTTOU, SIG_DFL);
1450 if (outpipe[1]!=-1) {
1460 dup2(nextout, 2); /* Really? */
1465 /* explicit redirects override pipes */
1466 setup_redirects(child);
1470 if (outpipe[1]!=-1) {
1474 /* put our child in the process group whose leader is the
1475 first process in this pipe */
1476 setpgid(child->pid, newjob->progs[0].pid);
1482 /* If there isn't another process, nextin is garbage
1483 but it doesn't matter */
1484 nextin = pipefds[0];
1487 newjob->pgrp = newjob->progs[0].pid;
1489 insert_job(newjob, inbg);
1494 static int busy_loop(FILE * input)
1497 char *next_command = NULL;
1503 newjob.job_list = &job_list;
1504 newjob.job_context = DEFAULT_CONTEXT;
1506 /* save current owner of TTY so we can restore it on exit */
1507 parent_pgrp = tcgetpgrp(0);
1509 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1511 /* don't pay any attention to this signal; it just confuses
1512 things and isn't really meant for shells anyway */
1513 signal(SIGTTOU, SIG_IGN);
1517 /* no job is in the foreground */
1519 /* see if any background processes have exited */
1520 checkjobs(&job_list);
1522 if (!next_command) {
1523 if (get_command(input, command))
1525 next_command = command;
1528 if (!parse_command(&next_command, &newjob, &inbg) &&
1530 int pipefds[2] = {-1,-1};
1531 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1532 run_command(&newjob, inbg, pipefds);
1536 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1537 next_command = NULL;
1540 /* a job is running in the foreground; wait for it */
1542 while (!job_list.fg->progs[i].pid ||
1543 job_list.fg->progs[i].is_stopped == 1) i++;
1545 waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1547 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1548 /* the child exited */
1549 job_list.fg->running_progs--;
1550 job_list.fg->progs[i].pid = 0;
1552 #ifdef BB_FEATURE_SH_ENVIRONMENT
1553 last_return_code=WEXITSTATUS(status);
1555 debug_printf("'%s' exited -- return code %d\n",
1556 job_list.fg->text, last_return_code);
1557 if (!job_list.fg->running_progs) {
1559 remove_job(&job_list, job_list.fg);
1563 /* the child was stopped */
1564 job_list.fg->stopped_progs++;
1565 job_list.fg->progs[i].is_stopped = 1;
1567 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1568 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1569 "Stopped", job_list.fg->text);
1575 /* move the shell to the foreground */
1576 /* suppress messages when run from /linuxrc mag@sysgo.de */
1577 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1578 perror("tcsetpgrp");
1584 /* return controlling TTY back to parent process group before exiting */
1585 if (tcsetpgrp(0, parent_pgrp))
1586 perror("tcsetpgrp");
1588 /* return exit status if called with "-c" */
1589 if (input == NULL && WIFEXITED(status))
1590 return WEXITSTATUS(status);
1596 #ifdef BB_FEATURE_CLEAN_UP
1597 void free_memory(void)
1603 if (local_pending_command)
1604 free(local_pending_command);
1606 if (job_list.fg && !job_list.fg->running_progs) {
1607 remove_job(&job_list, job_list.fg);
1613 int shell_main(int argc_l, char **argv_l)
1615 int opt, interactive=FALSE;
1616 FILE *input = stdin;
1621 if (argv[0] && argv[0][0] == '-') {
1623 input = fopen("/etc/profile", "r");
1625 fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1627 /* Now run the file */
1633 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1637 if (local_pending_command != 0)
1638 error_msg_and_die("multiple -c arguments\n");
1639 local_pending_command = xstrdup(argv[optind]);
1643 #ifdef BB_FEATURE_SH_ENVIRONMENT
1645 show_x_trace = TRUE;
1655 /* A shell is interactive if the `-i' flag was given, or if all of
1656 * the following conditions are met:
1658 * no arguments remaining or the -s flag given
1659 * standard input is a terminal
1660 * standard output is a terminal
1661 * Refer to Posix.2, the description of the `sh' utility. */
1662 if (argv[optind]==NULL && input==stdin &&
1663 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1666 if (interactive==TRUE) {
1667 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1668 /* Looks like they want an interactive shell */
1669 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1670 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1671 } else if (local_pending_command==NULL) {
1672 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1673 input = xfopen(argv[optind], "r");
1676 /* initialize the cwd -- this is never freed...*/
1677 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1678 getcwd(cwd, sizeof(char)*MAX_LINE);
1680 #ifdef BB_FEATURE_CLEAN_UP
1681 atexit(free_memory);
1685 return (busy_loop(input));