//#define BB_FEATURE_SH_BACKTICKS
//#define BB_FEATURE_SH_IF_EXPRESSIONS
-//#define BB_FEATURE_SH_ENVIRONMENT
+#define BB_FEATURE_SH_ENVIRONMENT
//#define DEBUG_SHELL
-#include "internal.h"
+#include "busybox.h"
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* function prototypes for builtins */
static int builtin_cd(struct job *cmd, struct jobSet *junk);
static int builtin_env(struct job *dummy, struct jobSet *junk);
+static int builtin_exec(struct job *cmd, struct jobSet *junk);
static int builtin_exit(struct job *cmd, struct jobSet *junk);
static int builtin_fg_bg(struct job *cmd, struct jobSet *jobList);
static int builtin_help(struct job *cmd, struct jobSet *junk);
static struct builtInCommand bltins[] = {
{"bg", "Resume a job in the background", builtin_fg_bg},
{"cd", "Change working directory", builtin_cd},
+ {"exec", "Exec command, replacing this shell with the exec'd process", builtin_exec},
{"exit", "Exit from shell()", builtin_exit},
{"fg", "Bring job into the foreground", builtin_fg_bg},
{"jobs", "Lists the active jobs", builtin_jobs},
return (0);
}
+/* built-in 'exec' handler */
+static int builtin_exec(struct job *cmd, struct jobSet *junk)
+{
+ if (cmd->progs[0].argv[1])
+ {
+ cmd->progs[0].argv++;
+ execvp(cmd->progs[0].argv[0], cmd->progs[0].argv);
+ fatalError("Exec to %s failed: %s\n", cmd->progs[0].argv[0],
+ strerror(errno));
+ }
+ return TRUE;
+}
+
/* built-in 'exit' handler */
static int builtin_exit(struct job *cmd, struct jobSet *junk)
{
mode = O_RDONLY;
break;
case REDIRECT_OVERWRITE:
- mode = O_RDWR | O_CREAT | O_TRUNC;
+ mode = O_WRONLY | O_CREAT | O_TRUNC;
break;
case REDIRECT_APPEND:
- mode = O_RDWR | O_CREAT | O_APPEND;
+ mode = O_WRONLY | O_CREAT | O_APPEND;
break;
}
#endif
}
- rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->globResult);
- if (rc == GLOB_NOSPACE) {
- errorMsg("out of space during glob operation\n");
- return;
- } else if (rc == GLOB_NOMATCH ||
+ if (strpbrk(prog->argv[argc_l - 1],"*[]?")!= NULL){
+ rc = glob(prog->argv[argc_l - 1], flags, NULL, &prog->globResult);
+ if (rc == GLOB_NOSPACE) {
+ errorMsg("out of space during glob operation\n");
+ return;
+ } else if (rc == GLOB_NOMATCH ||
(!rc && (prog->globResult.gl_pathc - i) == 1 &&
strcmp(prog->argv[argc_l - 1],
prog->globResult.gl_pathv[i]) == 0)) {
- /* we need to remove whatever \ quoting is still present */
- src = dst = prog->argv[argc_l - 1];
- while (*src) {
- if (*src != '\\')
- *dst++ = *src;
- src++;
+ /* we need to remove whatever \ quoting is still present */
+ src = dst = prog->argv[argc_l - 1];
+ while (*src) {
+ if (*src != '\\')
+ *dst++ = *src;
+ src++;
+ }
+ *dst = '\0';
+ } else if (!rc) {
+ argcAlloced += (prog->globResult.gl_pathc - i);
+ prog->argv = xrealloc(prog->argv, argcAlloced * sizeof(*prog->argv));
+ memcpy(prog->argv + (argc_l - 1), prog->globResult.gl_pathv + i,
+ sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
+ argc_l += (prog->globResult.gl_pathc - i - 1);
}
- *dst = '\0';
- } else if (!rc) {
- argcAlloced += (prog->globResult.gl_pathc - i);
- prog->argv = xrealloc(prog->argv, argcAlloced * sizeof(*prog->argv));
- memcpy(prog->argv + (argc_l - 1), prog->globResult.gl_pathv + i,
- sizeof(*(prog->argv)) * (prog->globResult.gl_pathc - i));
- argc_l += (prog->globResult.gl_pathc - i - 1);
+ }else{
+ src = dst = prog->argv[argc_l - 1];
+ while (*src) {
+ if (*src != '\\')
+ *dst++ = *src;
+ src++;
+ }
+ *dst = '\0';
+ prog->globResult.gl_pathc=0;
+ if (flags==0)
+ prog->globResult.gl_pathv=NULL;
}
-
*argcAllocedPtr = argcAlloced;
*argcPtr = argc_l;
}
}
*commandPtr = returnCommand;
-
+
return 0;
}
int pipefds[2]; /* pipefd[0] is for reading */
struct builtInCommand *x;
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
- const struct BB_applet *a = applets;
+ struct BB_applet search_applet, *applet;
#endif
-
nextin = 0, nextout = 1;
for (i = 0; i < newJob->numProgs; i++) {
if ((i + 1) < newJob->numProgs) {
}
}
#ifdef BB_FEATURE_SH_STANDALONE_SHELL
- /* Check if the command matches any busybox internal commands here */
- while (a->name != 0) {
- if (strcmp(get_last_path_component(newJob->progs[i].argv[0]), a->name) == 0) {
- int argc_l;
- char** argv=newJob->progs[i].argv;
- for(argc_l=0;*argv!=NULL; argv++, argc_l++);
- applet_name=a->name;
- optind = 1;
- exit((*(a->main)) (argc_l, newJob->progs[i].argv));
- }
- a++;
+ /* Check if the command matches any busybox internal
+ * commands ("applets") here. Following discussions from
+ * November 2000 on busybox@opensource.lineo.com, don't use
+ * get_last_path_component(). This way explicit (with
+ * slashes) filenames will never be interpreted as an
+ * applet, just like with builtins. This way the user can
+ * override an applet with an explicit filename reference.
+ * The only downside to this change is that an explicit
+ * /bin/foo invocation fill fork and exec /bin/foo, even if
+ * /bin/foo is a symlink to busybox.
+ */
+ search_applet.name = newJob->progs[i].argv[0];
+
+#ifdef BB_FEATURE_SH_BUILTINS_ALWAYS_WIN
+ /* If you enable BB_FEATURE_SH_BUILTINS_ALWAYS_WIN, then
+ * if you run /bin/cat, it will use BusyBox cat even if
+ * /bin/cat exists on the filesystem and is _not_ busybox.
+ * Some systems want this, others do not. Choose wisely. :-)
+ */
+ search_applet.name = get_last_path_component(search_applet.name);
+#endif
+
+ /* Do a binary search to find the applet entry given the name. */
+ applet = bsearch(&search_applet, applets, NUM_APPLETS,
+ sizeof(struct BB_applet), applet_name_compare);
+ if (applet != NULL) {
+ int argc_l;
+ char** argv=newJob->progs[i].argv;
+ for(argc_l=0;*argv!=NULL; argv++, argc_l++);
+ applet_name=applet->name;
+ optind = 1;
+ exit((*(applet->main)) (argc_l, newJob->progs[i].argv));
}
#endif
execvp(newJob->progs[i].argv[0], newJob->progs[i].argv);
fatalError("%s: %s\n", newJob->progs[i].argv[0],
- strerror(errno));
+ strerror(errno));
}
if (outPipe[1]!=-1) {
close(outPipe[1]);
fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n");
} else if (local_pending_command==NULL) {
//fprintf(stdout, "optind=%d argv[optind]='%s'\n", optind, argv[optind]);
- input = fopen(argv[optind], "r");
- if (!input) {
- fatalError("%s: %s\n", argv[optind], strerror(errno));
- }
+ input = xfopen(argv[optind], "r");
}
/* initialize the cwd -- this is never freed...*/