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 now 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);
140 /* function prototypes for shell stuff */
141 static int run_command_predicate(char *cmd);
145 /* function prototypes for shell stuff */
146 static void checkjobs(struct jobset *job_list);
147 static int get_command(FILE * source, char *command);
148 static int parse_command(char **command_ptr, struct job *job, int *inbg);
149 static int run_command(struct job *newjob, int inbg, int outpipe[2]);
150 static int pseudo_exec(struct child_prog *cmd) __attribute__ ((noreturn));
151 static int busy_loop(FILE * input);
154 /* Table of built-in functions (these are non-forking builtins, meaning they
155 * can change global variables in the parent shell process but they will not
156 * work with pipes and redirects; 'unset foo | whatever' will not work) */
157 static struct built_in_command bltins[] = {
158 {"bg", "Resume a job in the background", builtin_fg_bg},
159 {"cd", "Change working directory", builtin_cd},
160 {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
161 {"exit", "Exit from shell()", builtin_exit},
162 {"fg", "Bring job into the foreground", builtin_fg_bg},
163 {"jobs", "Lists the active jobs", builtin_jobs},
164 {"export", "Set environment variable", builtin_export},
165 {"unset", "Unset environment variable", builtin_unset},
166 {"read", "Input environment variable", builtin_read},
167 {".", "Source-in and run commands in a file", builtin_source},
168 /* to do: add ulimit */
169 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
170 {"if", NULL, builtin_if},
171 {"then", NULL, builtin_then},
172 {"else", NULL, builtin_else},
173 {"fi", NULL, builtin_fi},
178 /* Table of forking built-in functions (things that fork cannot change global
179 * variables in the parent process, such as the current working directory) */
180 static struct built_in_command bltins_forking[] = {
181 {"env", "Print all environment variables", builtin_env},
182 {"pwd", "Print current directory", builtin_pwd},
183 {"help", "List shell built-in commands", builtin_help},
188 static char *local_pending_command = NULL;
189 static struct jobset job_list = { NULL, NULL };
192 #ifdef BB_FEATURE_SH_ENVIRONMENT
193 static int last_bg_pid=-1;
194 static int last_return_code=-1;
195 static int show_x_trace=FALSE;
197 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
198 static char syntax_err[]="syntax error near unexpected token";
202 static inline void debug_printf(const char *format, ...)
205 va_start(args, format);
206 vfprintf(stderr, format, args);
210 static inline void debug_printf(const char *format, ...) { }
214 Most builtins need access to the struct child_prog that has
215 their arguments, previously coded as cmd->progs[0]. That coding
216 can exhibit a bug, if the builtin is not the first command in
217 a pipeline: "echo foo | exec sort" will attempt to exec foo.
219 builtin previous use notes
220 ------ ----------------- ---------
223 exec cmd->progs[0] squashed bug: didn't look for applets or forking builtins
225 fg_bg cmd->progs[0], job_list->head, job_list->fg
229 export cmd->progs[0] passes cmd, job_list to builtin_env(), which ignores them
233 if cmd->job_context, cmd->text
234 then cmd->job_context, cmd->text
235 else cmd->job_context, cmd->text
238 The use of cmd->text by if/then/else/fi is hopelessly hacky.
239 Would it work to increment cmd->progs[0]->argv and recurse,
240 somewhat like builtin_exec does?
242 I added "struct job *family;" to struct child_prog,
243 and switched API to builtin_foo(struct child_prog *child);
244 So cmd->text becomes child->family->text
245 cmd->job_context becomes child->family->job_context
246 cmd->progs[0] becomes *child
247 job_list becomes child->family->job_list
250 /* built-in 'cd <path>' handler */
251 static int builtin_cd(struct child_prog *child)
255 if (child->argv[1] == NULL)
256 newdir = getenv("HOME");
258 newdir = child->argv[1];
260 printf("cd: %s: %s\n", newdir, strerror(errno));
263 getcwd(cwd, sizeof(char)*MAX_LINE);
268 /* built-in 'env' handler */
269 static int builtin_env(struct child_prog *dummy)
273 for (e = environ; *e; e++) {
274 fprintf(stdout, "%s\n", *e);
279 /* built-in 'exec' handler */
280 static int builtin_exec(struct child_prog *child)
282 if (child->argv[1] == NULL)
283 return EXIT_SUCCESS; /* Really? */
289 /* built-in 'exit' handler */
290 static int builtin_exit(struct child_prog *child)
292 if (child->argv[1] == NULL)
295 exit (atoi(child->argv[1]));
298 /* built-in 'fg' and 'bg' handler */
299 static int builtin_fg_bg(struct child_prog *child)
302 struct job *job=NULL;
304 if (!child->argv[1] || child->argv[2]) {
305 error_msg("%s: exactly one argument is expected\n",
310 if (sscanf(child->argv[1], "%%%d", &jobNum) != 1) {
311 error_msg("%s: bad argument '%s'\n",
312 child->argv[0], child->argv[1]);
316 for (job = child->family->job_list->head; job; job = job->next) {
317 if (job->jobid == jobNum) {
323 error_msg("%s: unknown job %d\n",
324 child->argv[0], jobNum);
328 if (*child->argv[0] == 'f') {
329 /* Make this job the foreground job */
330 /* suppress messages when run from /linuxrc mag@sysgo.de */
331 if (tcsetpgrp(0, job->pgrp) && errno != ENOTTY)
332 perror_msg("tcsetpgrp");
333 child->family->job_list->fg = job;
336 /* Restart the processes in the job */
337 for (i = 0; i < job->num_progs; i++)
338 job->progs[i].is_stopped = 0;
340 kill(-job->pgrp, SIGCONT);
342 job->stopped_progs = 0;
347 /* built-in 'help' handler */
348 static int builtin_help(struct child_prog *dummy)
350 struct built_in_command *x;
352 printf("\nBuilt-in commands:\n");
353 printf("-------------------\n");
354 for (x = bltins; x->cmd; x++) {
357 printf("%s\t%s\n", x->cmd, x->descr);
359 for (x = bltins_forking; x->cmd; x++) {
362 printf("%s\t%s\n", x->cmd, x->descr);
368 /* built-in 'jobs' handler */
369 static int builtin_jobs(struct child_prog *child)
374 for (job = child->family->job_list->head; job; job = job->next) {
375 if (job->running_progs == job->stopped_progs)
376 status_string = "Stopped";
378 status_string = "Running";
380 printf(JOB_STATUS_FORMAT, job->jobid, status_string, job->text);
386 /* built-in 'pwd' handler */
387 static int builtin_pwd(struct child_prog *dummy)
389 getcwd(cwd, MAX_LINE);
390 fprintf(stdout, "%s\n", cwd);
394 /* built-in 'export VAR=value' handler */
395 static int builtin_export(struct child_prog *child)
399 if (child->argv[1] == NULL) {
400 return (builtin_env(child));
402 res = putenv(child->argv[1]);
404 fprintf(stderr, "export: %s\n", strerror(errno));
408 /* built-in 'read VAR' handler */
409 static int builtin_read(struct child_prog *child)
411 int res = 0, len, newlen;
413 char string[MAX_READ];
415 if (child->argv[1]) {
416 /* argument (VAR) given: put "VAR=" into buffer */
417 strcpy(string, child->argv[1]);
418 len = strlen(string);
421 fgets(&string[len], sizeof(string) - len, stdin); /* read string */
422 newlen = strlen(string);
424 string[--newlen] = '\0'; /* chomp trailing newline */
426 ** string should now contain "VAR=<value>"
427 ** copy it (putenv() won't do that, so we must make sure
428 ** the string resides in a static buffer!)
431 if((s = strdup(string)))
434 fprintf(stderr, "read: %s\n", strerror(errno));
437 fgets(string, sizeof(string), stdin);
442 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
443 /* Built-in handler for 'if' commands */
444 static int builtin_if(struct child_prog *child)
446 struct job *cmd = child->family;
448 char* charptr1=cmd->text+3; /* skip over the leading 'if ' */
450 /* Now run the 'if' command */
451 debug_printf( "job=%p entering builtin_if ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
452 status = run_command_predicate(charptr1);
453 debug_printf( "if test returned ");
455 debug_printf( "TRUE\n");
456 cmd->job_context |= IF_TRUE_CONTEXT;
458 debug_printf( "FALSE\n");
459 cmd->job_context |= IF_FALSE_CONTEXT;
461 debug_printf("job=%p builtin_if set job context to %x\n", cmd, cmd->job_context);
467 /* Built-in handler for 'then' (part of the 'if' command) */
468 static int builtin_then(struct child_prog *child)
470 struct job *cmd = child->family;
471 char* charptr1=cmd->text+5; /* skip over the leading 'then ' */
473 debug_printf( "job=%p entering builtin_then ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
474 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
475 shell_context = 0; /* Reset the shell's context on an error */
476 error_msg("%s `then'\n", syntax_err);
480 cmd->job_context |= THEN_EXP_CONTEXT;
481 debug_printf("job=%p builtin_then set job context to %x\n", cmd, cmd->job_context);
483 /* If the if result was FALSE, skip the 'then' stuff */
484 if (cmd->job_context & IF_FALSE_CONTEXT) {
488 /* Seems the if result was TRUE, so run the 'then' command */
489 debug_printf( "'then' now running '%s'\n", charptr1);
491 return(run_command_predicate(charptr1));
494 /* Built-in handler for 'else' (part of the 'if' command) */
495 static int builtin_else(struct child_prog *child)
497 struct job *cmd = child->family;
498 char* charptr1=cmd->text+5; /* skip over the leading 'else ' */
500 debug_printf( "job=%p entering builtin_else ('%s')-- context=%d\n", cmd, charptr1, cmd->job_context);
502 if (! (cmd->job_context & THEN_EXP_CONTEXT)) {
503 shell_context = 0; /* Reset the shell's context on an error */
504 error_msg("%s `else'\n", syntax_err);
507 /* If the if result was TRUE, skip the 'else' stuff */
508 if (cmd->job_context & IF_TRUE_CONTEXT) {
512 cmd->job_context |= ELSE_EXP_CONTEXT;
513 debug_printf("job=%p builtin_else set job context to %x\n", cmd, cmd->job_context);
515 /* Now run the 'else' command */
516 debug_printf( "'else' now running '%s'\n", charptr1);
517 return(run_command_predicate(charptr1));
520 /* Built-in handler for 'fi' (part of the 'if' command) */
521 static int builtin_fi(struct child_prog *child)
523 struct job *cmd = child->family;
524 debug_printf( "job=%p entering builtin_fi ('%s')-- context=%d\n", cmd, "", cmd->job_context);
525 if (! (cmd->job_context & (IF_TRUE_CONTEXT|IF_FALSE_CONTEXT))) {
526 shell_context = 0; /* Reset the shell's context on an error */
527 error_msg("%s `fi'\n", syntax_err);
530 /* Clear out the if and then context bits */
531 cmd->job_context &= ~(IF_TRUE_CONTEXT|IF_FALSE_CONTEXT|THEN_EXP_CONTEXT|ELSE_EXP_CONTEXT);
532 debug_printf("job=%p builtin_fi set job context to %x\n", cmd, cmd->job_context);
538 /* Built-in '.' handler (read-in and execute commands from file) */
539 static int builtin_source(struct child_prog *child)
544 if (child->argv[1] == NULL)
547 input = fopen(child->argv[1], "r");
549 fprintf(stdout, "Couldn't open file '%s'\n", child->argv[1]);
553 /* Now run the file */
554 status = busy_loop(input);
559 /* built-in 'unset VAR' handler */
560 static int builtin_unset(struct child_prog *child)
562 if (child->argv[1] == NULL) {
563 fprintf(stdout, "unset: parameter required.\n");
566 unsetenv(child->argv[1]);
570 #ifdef BB_FEATURE_SH_IF_EXPRESSIONS
571 /* currently used by if/then/else.
573 * Reparsing the command line for this purpose is gross,
574 * incorrect, and fundamentally unfixable; in particular,
575 * think about what happens with command substitution.
576 * We really need to pull out the run, wait, return status
577 * functionality out of busy_loop so we can child->argv++
578 * and use that, without going back through parse_command.
580 static int run_command_predicate(char *cmd)
583 local_pending_command = xmalloc(n+1);
584 strncpy(local_pending_command, cmd, n);
585 local_pending_command[n]='\0';
586 return( busy_loop(NULL));
590 /* free up all memory from a job */
591 static void free_job(struct job *cmd)
595 for (i = 0; i < cmd->num_progs; i++) {
596 free(cmd->progs[i].argv);
597 if (cmd->progs[i].redirects)
598 free(cmd->progs[i].redirects);
599 if (cmd->progs[i].free_glob)
600 globfree(&cmd->progs[i].glob_result);
606 memset(cmd, 0, sizeof(struct job));
609 /* remove a job from the job_list */
610 static void remove_job(struct jobset *job_list, struct job *job)
615 if (job == job_list->head) {
616 job_list->head = job->next;
618 prevjob = job_list->head;
619 while (prevjob->next != job)
620 prevjob = prevjob->next;
621 prevjob->next = job->next;
627 /* Checks to see if any background processes have exited -- if they
628 have, figure out why and see if a job has completed */
629 static void checkjobs(struct jobset *job_list)
636 while ((childpid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
637 for (job = job_list->head; job; job = job->next) {
639 while (prognum < job->num_progs &&
640 job->progs[prognum].pid != childpid) prognum++;
641 if (prognum < job->num_progs)
645 /* This happens on backticked commands */
649 if (WIFEXITED(status) || WIFSIGNALED(status)) {
651 job->running_progs--;
652 job->progs[prognum].pid = 0;
654 if (!job->running_progs) {
655 printf(JOB_STATUS_FORMAT, job->jobid, "Done", job->text);
656 remove_job(job_list, job);
660 job->stopped_progs++;
661 job->progs[prognum].is_stopped = 1;
663 if (job->stopped_progs == job->num_progs) {
664 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
670 if (childpid == -1 && errno != ECHILD)
671 perror_msg("waitpid");
674 /* squirrel != NULL means we squirrel away copies of stdin, stdout,
675 * and stderr if they are redirected. */
676 static int setup_redirects(struct child_prog *prog, int squirrel[])
681 struct redir_struct *redir = prog->redirects;
683 for (i = 0; i < prog->num_redirects; i++, redir++) {
684 switch (redir->type) {
688 case REDIRECT_OVERWRITE:
689 mode = O_WRONLY | O_CREAT | O_TRUNC;
691 case REDIRECT_APPEND:
692 mode = O_WRONLY | O_CREAT | O_APPEND;
696 openfd = open(redir->filename, mode, 0666);
698 /* this could get lost if stderr has been redirected, but
699 bash and ash both lose it as well (though zsh doesn't!) */
700 error_msg("error opening %s: %s\n", redir->filename,
705 if (openfd != redir->fd) {
706 if (squirrel && redir->fd < 3) {
707 squirrel[redir->fd] = dup(redir->fd);
709 dup2(openfd, redir->fd);
717 static void restore_redirects(int squirrel[])
720 for (i=0; i<3; i++) {
723 /* No error checking. I sure wouldn't know what
724 * to do with an error if I found one! */
731 static char* setup_prompt_string(int state)
733 char user[9],buf[255],*s;
735 char prompt_str[BUFSIZ];
737 /* Set up the prompt */
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, '.');
754 snprintf(prompt_str, BUFSIZ-1, "[%s@%s %s]%s", user, buf,
755 get_last_path_component(cwd), prompt);
757 sprintf(prompt_str, "%s", prompt);
759 return(strdup(prompt_str)); /* Must free this memory */
762 static int get_command(FILE * source, char *command)
766 if (source == NULL) {
767 if (local_pending_command) {
768 /* a command specified (-c option): return it & mark it done */
769 strcpy(command, local_pending_command);
770 free(local_pending_command);
771 local_pending_command = NULL;
777 prompt_str = setup_prompt_string(shell_context);
779 if (source == stdin) {
780 #ifdef BB_FEATURE_SH_COMMAND_EDITING
782 ** enable command line editing only while a command line
783 ** is actually being read; otherwise, we'll end up bequeathing
784 ** atexit() handlers and other unwanted stuff to our
785 ** child processes (rob@sysgo.de)
788 cmdedit_read_input(prompt_str, command);
793 fprintf(stdout, "%s", prompt_str);
797 if (!fgets(command, BUFSIZ - 2, source)) {
803 /* remove trailing newline */
804 command[strlen(command) - 1] = '\0';
809 #ifdef BB_FEATURE_SH_ENVIRONMENT
810 static char* itoa(register int i)
812 static char a[7]; /* Max 7 ints */
813 register char *b = a + sizeof(a) - 1;
821 *--b = '0' + (i % 10);
831 static void expand_argument(struct child_prog *prog, int *argcPtr,
832 int *argv_alloced_ptr)
834 int argc_l = *argcPtr;
835 int argv_alloced = *argv_alloced_ptr;
839 char *src, *dst, *var;
841 if (argc_l > 1) { /* cmd->glob_result is already initialized */
843 i = prog->glob_result.gl_pathc;
849 /* do shell variable substitution */
850 if(*prog->argv[argc_l - 1] == '$') {
851 if ((var = getenv(prog->argv[argc_l - 1] + 1))) {
852 prog->argv[argc_l - 1] = var;
854 #ifdef BB_FEATURE_SH_ENVIRONMENT
856 switch(*(prog->argv[argc_l - 1] + 1)) {
858 prog->argv[argc_l - 1] = itoa(last_return_code);
861 prog->argv[argc_l - 1] = itoa(getpid());
864 prog->argv[argc_l - 1] = itoa(argc-1);
868 *(prog->argv[argc_l - 1])='\0';
870 prog->argv[argc_l - 1] = itoa(last_bg_pid);
872 case '0':case '1':case '2':case '3':case '4':
873 case '5':case '6':case '7':case '8':case '9':
875 int index=*(prog->argv[argc_l - 1] + 1)-48;
877 *(prog->argv[argc_l - 1])='\0';
879 prog->argv[argc_l - 1] = argv[index];
888 if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
889 rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->glob_result);
890 if (rc == GLOB_NOSPACE) {
891 error_msg("out of space during glob operation\n");
893 } else if (rc == GLOB_NOMATCH ||
894 (!rc && (prog->glob_result.gl_pathc - i) == 1 &&
895 strcmp(prog->argv[argc_l - 1],
896 prog->glob_result.gl_pathv[i]) == 0)) {
897 /* we need to remove whatever \ quoting is still present */
898 src = dst = prog->argv[argc_l - 1];
902 *dst++ = process_escape_sequence(&src);
910 argv_alloced += (prog->glob_result.gl_pathc - i);
911 prog->argv = xrealloc(prog->argv, argv_alloced * sizeof(*prog->argv));
912 memcpy(prog->argv + (argc_l - 1), prog->glob_result.gl_pathv + i,
913 sizeof(*(prog->argv)) * (prog->glob_result.gl_pathc - i));
914 argc_l += (prog->glob_result.gl_pathc - i - 1);
917 src = dst = prog->argv[argc_l - 1];
921 *dst++ = process_escape_sequence(&src);
929 prog->glob_result.gl_pathc=0;
931 prog->glob_result.gl_pathv=NULL;
933 *argv_alloced_ptr = argv_alloced;
937 /* Return cmd->num_progs as 0 if no command is present (e.g. an empty
938 line). If a valid command is found, command_ptr is set to point to
939 the beginning of the next command (if the original command had more
940 then one job associated with it) or NULL if no more commands are
942 static int parse_command(char **command_ptr, struct job *job, int *inbg)
945 char *return_command = NULL;
946 char *src, *buf, *chptr;
953 struct child_prog *prog;
955 /* skip leading white space */
956 while (**command_ptr && isspace(**command_ptr))
959 /* this handles empty lines or leading '#' characters */
960 if (!**command_ptr || (**command_ptr == '#')) {
967 job->progs = xmalloc(sizeof(*job->progs));
969 /* We set the argv elements to point inside of this string. The
970 memory is freed by free_job(). Allocate twice the original
971 length in case we need to quote every single character.
973 Getting clean memory relieves us of the task of NULL
974 terminating things and makes the rest of this look a bit
975 cleaner (though it is, admittedly, a tad less efficient) */
976 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
980 prog->num_redirects = 0;
981 prog->redirects = NULL;
983 prog->is_stopped = 0;
987 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
988 prog->argv[0] = job->cmdbuf;
992 while (*src && !done) {
999 error_msg("character expected after \\\n");
1004 /* in shell, "\'" should yield \' */
1005 if (*src != quote) {
1009 } else if (*src == '*' || *src == '?' || *src == '[' ||
1010 *src == ']') *buf++ = '\\';
1012 } else if (isspace(*src)) {
1013 if (*prog->argv[argc_l]) {
1015 /* +1 here leaves room for the NULL which ends argv */
1016 if ((argc_l + 1) == argv_alloced) {
1018 prog->argv = xrealloc(prog->argv,
1019 sizeof(*prog->argv) *
1022 expand_argument(prog, &argc_l, &argv_alloced);
1023 prog->argv[argc_l] = buf;
1032 case '#': /* comment */
1039 case '>': /* redirects */
1041 i = prog->num_redirects++;
1042 prog->redirects = xrealloc(prog->redirects,
1043 sizeof(*prog->redirects) *
1046 prog->redirects[i].fd = -1;
1047 if (buf != prog->argv[argc_l]) {
1048 /* the stuff before this character may be the file number
1050 prog->redirects[i].fd =
1051 strtol(prog->argv[argc_l], &chptr, 10);
1053 if (*chptr && *prog->argv[argc_l]) {
1055 expand_argument(prog, &argc_l, &argv_alloced);
1056 prog->argv[argc_l] = buf;
1060 if (prog->redirects[i].fd == -1) {
1062 prog->redirects[i].fd = 1;
1064 prog->redirects[i].fd = 0;
1067 if (*src++ == '>') {
1069 prog->redirects[i].type =
1070 REDIRECT_APPEND, src++;
1072 prog->redirects[i].type = REDIRECT_OVERWRITE;
1074 prog->redirects[i].type = REDIRECT_INPUT;
1077 /* This isn't POSIX sh compliant. Oh well. */
1079 while (isspace(*chptr))
1083 error_msg("file name expected after %c\n", *src);
1089 prog->redirects[i].filename = buf;
1090 while (*chptr && !isspace(*chptr))
1093 src = chptr - 1; /* we src++ later */
1094 prog->argv[argc_l] = ++buf;
1097 case '|': /* pipe */
1098 /* finish this command */
1099 if (*prog->argv[argc_l])
1102 error_msg("empty command in pipe\n");
1107 prog->argv[argc_l] = NULL;
1109 /* and start the next */
1111 job->progs = xrealloc(job->progs,
1112 sizeof(*job->progs) * job->num_progs);
1113 prog = job->progs + (job->num_progs - 1);
1114 prog->num_redirects = 0;
1115 prog->redirects = NULL;
1116 prog->free_glob = 0;
1117 prog->is_stopped = 0;
1122 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
1123 prog->argv[0] = ++buf;
1126 while (*src && isspace(*src))
1130 error_msg("empty command in pipe\n");
1135 src--; /* we'll ++ it at the end of the loop */
1139 case '&': /* background */
1141 case ';': /* multiple commands */
1143 return_command = *command_ptr + (src - *command_ptr) + 1;
1146 #ifdef BB_FEATURE_SH_BACKTICKS
1148 /* Exec a backtick-ed command */
1150 char* charptr1=NULL, *charptr2;
1153 struct jobset njob_list = { NULL, NULL };
1157 ptr=strchr(++src, '`');
1159 fprintf(stderr, "Unmatched '`' in command\n");
1164 /* Make some space to hold just the backticked command */
1165 charptr1 = charptr2 = xmalloc(1+ptr-src);
1166 memcpy(charptr1, src, ptr-src);
1167 charptr1[ptr-src] = '\0';
1168 newjob = xmalloc(sizeof(struct job));
1169 newjob->job_list = &njob_list;
1170 /* Now parse and run the backticked command */
1171 if (!parse_command(&charptr1, newjob, inbg)
1172 && newjob->num_progs) {
1174 run_command(newjob, 0, pipefd);
1176 checkjobs(job->job_list);
1177 free_job(newjob); /* doesn't actually free newjob,
1178 looks like a memory leak */
1181 /* Make a copy of any stuff left over in the command
1182 * line after the second backtick */
1183 charptr2 = xmalloc(strlen(ptr)+1);
1184 memcpy(charptr2, ptr+1, strlen(ptr));
1187 /* Copy the output from the backtick-ed command into the
1188 * command line, making extra room as needed */
1190 charptr1 = xmalloc(BUFSIZ);
1191 while ( (size=full_read(pipefd[0], charptr1, BUFSIZ-1)) >0) {
1192 int newsize=src - *command_ptr + size + 1 + strlen(charptr2);
1193 if (newsize > BUFSIZ) {
1194 *command_ptr=xrealloc(*command_ptr, newsize);
1196 memcpy(src, charptr1, size);
1204 /* Now paste into the *command_ptr all the stuff
1205 * leftover after the second backtick */
1206 memcpy(src, charptr2, strlen(charptr2)+1);
1209 /* Now recursively call parse_command to deal with the new
1210 * and improved version of the command line with the backtick
1211 * results expanded in place... */
1213 struct jobset *jl=job->job_list;
1217 return(parse_command(command_ptr, job, inbg));
1220 #endif // BB_FEATURE_SH_BACKTICKS
1225 /* This is currently a little broken... */
1226 #ifdef HANDLE_CONTINUATION_CHARS
1227 /* They fed us a continuation char, so continue reading stuff
1228 * on the next line, then tack that onto the end of the current
1232 printf("erik: found a continue char at EOL...\n");
1233 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1234 if (get_command(input, command)) {
1235 error_msg("character expected after \\\n");
1240 newsize = strlen(*command_ptr) + strlen(command) + 2;
1241 if (newsize > BUFSIZ) {
1242 printf("erik: doing realloc\n");
1243 *command_ptr=xrealloc(*command_ptr, newsize);
1245 printf("erik: A: *command_ptr='%s'\n", *command_ptr);
1246 memcpy(--src, command, strlen(command));
1247 printf("erik: B: *command_ptr='%s'\n", *command_ptr);
1251 error_msg("character expected after \\\n");
1257 if (*src == '*' || *src == '[' || *src == ']'
1258 || *src == '?') *buf++ = '\\';
1267 if (*prog->argv[argc_l]) {
1269 expand_argument(prog, &argc_l, &argv_alloced);
1275 prog->argv[argc_l] = NULL;
1277 if (!return_command) {
1278 job->text = xmalloc(strlen(*command_ptr) + 1);
1279 strcpy(job->text, *command_ptr);
1281 /* This leaves any trailing spaces, which is a bit sloppy */
1282 count = return_command - *command_ptr;
1283 job->text = xmalloc(count + 1);
1284 strncpy(job->text, *command_ptr, count);
1285 job->text[count] = '\0';
1288 *command_ptr = return_command;
1293 /* Run the child_prog, no matter what kind of command it uses.
1295 static int pseudo_exec(struct child_prog *child)
1297 struct built_in_command *x;
1298 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1299 struct BB_applet search_applet, *applet;
1302 /* Check if the command matches any of the non-forking builtins.
1303 * Depending on context, this might be redundant. But it's
1304 * easier to waste a few CPU cycles than it is to figure out
1305 * if this is one of those cases.
1307 for (x = bltins; x->cmd; x++) {
1308 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1309 exit(x->function(child));
1313 /* Check if the command matches any of the forking builtins. */
1314 for (x = bltins_forking; x->cmd; x++) {
1315 if (strcmp(child->argv[0], x->cmd) == 0) {
1317 exit (x->function(child));
1320 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
1321 /* Check if the command matches any busybox internal
1322 * commands ("applets") here. Following discussions from
1323 * November 2000 on busybox@opensource.lineo.com, don't use
1324 * get_last_path_component(). This way explicit (with
1325 * slashes) filenames will never be interpreted as an
1326 * applet, just like with builtins. This way the user can
1327 * override an applet with an explicit filename reference.
1328 * The only downside to this change is that an explicit
1329 * /bin/foo invocation will fork and exec /bin/foo, even if
1330 * /bin/foo is a symlink to busybox.
1332 search_applet.name = child->argv[0];
1334 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
1335 /* If you enable BB_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1336 * if you run /bin/cat, it will use BusyBox cat even if
1337 * /bin/cat exists on the filesystem and is _not_ busybox.
1338 * Some systems want this, others do not. Choose wisely. :-)
1340 search_applet.name = get_last_path_component(search_applet.name);
1343 /* Do a binary search to find the applet entry given the name. */
1344 applet = bsearch(&search_applet, applets, NUM_APPLETS,
1345 sizeof(struct BB_applet), applet_name_compare);
1346 if (applet != NULL) {
1348 char** argv=child->argv;
1349 for(argc_l=0;*argv!=NULL; argv++, argc_l++);
1350 applet_name=applet->name;
1352 exit((*(applet->main)) (argc_l, child->argv));
1356 execvp(child->argv[0], child->argv);
1357 error_msg_and_die("%s: %s\n", child->argv[0],
1361 static void insert_job(struct job *newjob, int inbg)
1364 struct jobset *job_list=newjob->job_list;
1366 /* find the ID for thejob to use */
1368 for (thejob = job_list->head; thejob; thejob = thejob->next)
1369 if (thejob->jobid >= newjob->jobid)
1370 newjob->jobid = thejob->jobid + 1;
1372 /* add thejob to the list of running jobs */
1373 if (!job_list->head) {
1374 thejob = job_list->head = xmalloc(sizeof(*thejob));
1376 for (thejob = job_list->head; thejob->next; thejob = thejob->next) /* nothing */;
1377 thejob->next = xmalloc(sizeof(*thejob));
1378 thejob = thejob->next;
1381 *thejob = *newjob; /* physically copy the struct job */
1382 thejob->next = NULL;
1383 thejob->running_progs = thejob->num_progs;
1384 thejob->stopped_progs = 0;
1387 /* we don't wait for background thejobs to return -- append it
1388 to the list of backgrounded thejobs and leave it alone */
1389 printf("[%d] %d\n", thejob->jobid,
1390 newjob->progs[newjob->num_progs - 1].pid);
1391 #ifdef BB_FEATURE_SH_ENVIRONMENT
1392 last_bg_pid=newjob->progs[newjob->num_progs - 1].pid;
1395 newjob->job_list->fg = thejob;
1397 /* move the new process group into the foreground */
1398 /* suppress messages when run from /linuxrc mag@sysgo.de */
1399 if (tcsetpgrp(0, newjob->pgrp) && errno != ENOTTY)
1400 perror_msg("tcsetpgrp");
1404 static int run_command(struct job *newjob, int inbg, int outpipe[2])
1406 /* struct job *thejob; */
1408 int nextin, nextout;
1409 int pipefds[2]; /* pipefd[0] is for reading */
1410 struct built_in_command *x;
1411 struct child_prog *child;
1413 nextin = 0, nextout = 1;
1414 for (i = 0; i < newjob->num_progs; i++) {
1415 child = & (newjob->progs[i]);
1417 if ((i + 1) < newjob->num_progs) {
1418 if (pipe(pipefds)<0) perror_msg_and_die("pipe");
1419 nextout = pipefds[1];
1421 if (outpipe[1]!=-1) {
1422 nextout = outpipe[1];
1428 #ifdef BB_FEATURE_SH_ENVIRONMENT
1429 if (show_x_trace==TRUE) {
1432 for (j = 0; child->argv[j]; j++) {
1434 fputs(child->argv[j], stderr);
1436 fputc('\n', stderr);
1440 /* Check if the command matches any non-forking builtins,
1441 * but only if this is a simple command.
1442 * Non-forking builtins within pipes have to fork anyway,
1443 * and are handled in pseudo_exec. "echo foo | read bar"
1444 * is doomed to failure, and doesn't work on bash, either.
1446 if (newjob->num_progs == 1) {
1447 for (x = bltins; x->cmd; x++) {
1448 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1449 int squirrel[] = {-1, -1, -1};
1451 setup_redirects(child, squirrel);
1452 rcode = x->function(child);
1453 restore_redirects(squirrel);
1459 if (!(child->pid = fork())) {
1460 signal(SIGTTOU, SIG_DFL);
1462 if (outpipe[1]!=-1) {
1472 dup2(nextout, 2); /* Really? */
1477 /* explicit redirects override pipes */
1478 setup_redirects(child,NULL);
1482 if (outpipe[1]!=-1) {
1486 /* put our child in the process group whose leader is the
1487 first process in this pipe */
1488 setpgid(child->pid, newjob->progs[0].pid);
1494 /* If there isn't another process, nextin is garbage
1495 but it doesn't matter */
1496 nextin = pipefds[0];
1499 newjob->pgrp = newjob->progs[0].pid;
1501 insert_job(newjob, inbg);
1506 static int busy_loop(FILE * input)
1509 char *next_command = NULL;
1515 newjob.job_list = &job_list;
1516 newjob.job_context = DEFAULT_CONTEXT;
1518 /* save current owner of TTY so we can restore it on exit */
1519 parent_pgrp = tcgetpgrp(0);
1521 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1523 /* don't pay any attention to this signal; it just confuses
1524 things and isn't really meant for shells anyway */
1525 signal(SIGTTOU, SIG_IGN);
1529 /* no job is in the foreground */
1531 /* see if any background processes have exited */
1532 checkjobs(&job_list);
1534 if (!next_command) {
1535 if (get_command(input, command))
1537 next_command = command;
1540 if (!parse_command(&next_command, &newjob, &inbg) &&
1542 int pipefds[2] = {-1,-1};
1543 debug_printf( "job=%p being fed to run_command by busy_loop()'\n", &newjob);
1544 run_command(&newjob, inbg, pipefds);
1548 command = (char *) xcalloc(BUFSIZ, sizeof(char));
1549 next_command = NULL;
1552 /* a job is running in the foreground; wait for it */
1554 while (!job_list.fg->progs[i].pid ||
1555 job_list.fg->progs[i].is_stopped == 1) i++;
1557 waitpid(job_list.fg->progs[i].pid, &status, WUNTRACED);
1559 if (WIFEXITED(status) || WIFSIGNALED(status)) {
1560 /* the child exited */
1561 job_list.fg->running_progs--;
1562 job_list.fg->progs[i].pid = 0;
1564 #ifdef BB_FEATURE_SH_ENVIRONMENT
1565 last_return_code=WEXITSTATUS(status);
1567 debug_printf("'%s' exited -- return code %d\n",
1568 job_list.fg->text, last_return_code);
1569 if (!job_list.fg->running_progs) {
1571 remove_job(&job_list, job_list.fg);
1575 /* the child was stopped */
1576 job_list.fg->stopped_progs++;
1577 job_list.fg->progs[i].is_stopped = 1;
1579 if (job_list.fg->stopped_progs == job_list.fg->running_progs) {
1580 printf("\n" JOB_STATUS_FORMAT, job_list.fg->jobid,
1581 "Stopped", job_list.fg->text);
1587 /* move the shell to the foreground */
1588 /* suppress messages when run from /linuxrc mag@sysgo.de */
1589 if (tcsetpgrp(0, getpid()) && errno != ENOTTY)
1590 perror_msg("tcsetpgrp");
1596 /* return controlling TTY back to parent process group before exiting */
1597 if (tcsetpgrp(0, parent_pgrp))
1598 perror_msg("tcsetpgrp");
1600 /* return exit status if called with "-c" */
1601 if (input == NULL && WIFEXITED(status))
1602 return WEXITSTATUS(status);
1608 #ifdef BB_FEATURE_CLEAN_UP
1609 void free_memory(void)
1615 if (local_pending_command)
1616 free(local_pending_command);
1618 if (job_list.fg && !job_list.fg->running_progs) {
1619 remove_job(&job_list, job_list.fg);
1625 int shell_main(int argc_l, char **argv_l)
1627 int opt, interactive=FALSE;
1628 FILE *input = stdin;
1633 if (argv[0] && argv[0][0] == '-') {
1635 input = fopen("/etc/profile", "r");
1637 fprintf(stdout, "Couldn't open file '/etc/profile'\n");
1639 /* Now run the file */
1645 while ((opt = getopt(argc_l, argv_l, "cxi")) > 0) {
1649 if (local_pending_command != 0)
1650 error_msg_and_die("multiple -c arguments\n");
1651 local_pending_command = xstrdup(argv[optind]);
1655 #ifdef BB_FEATURE_SH_ENVIRONMENT
1657 show_x_trace = TRUE;
1667 /* A shell is interactive if the `-i' flag was given, or if all of
1668 * the following conditions are met:
1670 * no arguments remaining or the -s flag given
1671 * standard input is a terminal
1672 * standard output is a terminal
1673 * Refer to Posix.2, the description of the `sh' utility. */
1674 if (argv[optind]==NULL && input==stdin &&
1675 isatty(fileno(stdin)) && isatty(fileno(stdout))) {
1678 if (interactive==TRUE) {
1679 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1680 /* Looks like they want an interactive shell */
1681 fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell (lash)\n", BB_VER, BB_BT);
1682 fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
1683 } else if (local_pending_command==NULL) {
1684 //fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
1685 input = xfopen(argv[optind], "r");
1688 /* initialize the cwd -- this is never freed...*/
1689 cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1);
1690 getcwd(cwd, sizeof(char)*MAX_LINE);
1692 #ifdef BB_FEATURE_CLEAN_UP
1693 atexit(free_memory);
1696 return (busy_loop(input));