diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-04-23 00:26:07 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2009-04-23 04:44:46 +1000 |
commit | 580765e16aca68132babc09a02b4ea6c220c1988 (patch) | |
tree | 9ca6ea68145b108064c6a4c97899bb1ade075428 /shell | |
parent | e0ef52d2fabdb4772aaa87a417d841fe58d04e0d (diff) | |
download | busybox-w32-580765e16aca68132babc09a02b4ea6c220c1988.tar.gz busybox-w32-580765e16aca68132babc09a02b4ea6c220c1988.tar.bz2 busybox-w32-580765e16aca68132babc09a02b4ea6c220c1988.zip |
shell/ash: replace shellexec() with shellspawn()
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 5 | ||||
-rw-r--r-- | shell/ash_mingw.c | 148 | ||||
-rw-r--r-- | shell/ash_mingw.h | 3 |
3 files changed, 156 insertions, 0 deletions
diff --git a/shell/ash.c b/shell/ash.c index 284f49303..7c97e72e2 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -8453,6 +8453,10 @@ evalcommand(union node *cmd, int flags) | |||
8453 | /* Execute the command. */ | 8453 | /* Execute the command. */ |
8454 | switch (cmdentry.cmdtype) { | 8454 | switch (cmdentry.cmdtype) { |
8455 | default: | 8455 | default: |
8456 | #ifdef __MINGW32__ | ||
8457 | shellspawn((const char**)argv, path, cmdentry.u.index, varlist.list); | ||
8458 | break; | ||
8459 | #else | ||
8456 | /* Fork off a child process if necessary. */ | 8460 | /* Fork off a child process if necessary. */ |
8457 | if (!(flags & EV_EXIT) || trap[0]) { | 8461 | if (!(flags & EV_EXIT) || trap[0]) { |
8458 | INT_OFF; | 8462 | INT_OFF; |
@@ -8467,6 +8471,7 @@ evalcommand(union node *cmd, int flags) | |||
8467 | listsetvar(varlist.list, VEXPORT|VSTACK); | 8471 | listsetvar(varlist.list, VEXPORT|VSTACK); |
8468 | shellexec(argv, path, cmdentry.u.index); | 8472 | shellexec(argv, path, cmdentry.u.index); |
8469 | /* NOTREACHED */ | 8473 | /* NOTREACHED */ |
8474 | #endif | ||
8470 | 8475 | ||
8471 | case CMDBUILTIN: | 8476 | case CMDBUILTIN: |
8472 | cmdenviron = varlist.list; | 8477 | cmdenviron = varlist.list; |
diff --git a/shell/ash_mingw.c b/shell/ash_mingw.c index a412b7210..c36973164 100644 --- a/shell/ash_mingw.c +++ b/shell/ash_mingw.c | |||
@@ -893,3 +893,151 @@ subshell_run() | |||
893 | 893 | ||
894 | die("subshell ended unexpectedly"); | 894 | die("subshell ended unexpectedly"); |
895 | } | 895 | } |
896 | |||
897 | static int | ||
898 | tryspawn(const char *cmd, const char **argv, const char * const*envp) | ||
899 | { | ||
900 | struct child_process cp; | ||
901 | |||
902 | memset(&cp, 0, sizeof(cp)); | ||
903 | |||
904 | cp.env = envp; | ||
905 | #if ENABLE_FEATURE_SH_STANDALONE | ||
906 | if (strchr(cmd, '/') == NULL) { | ||
907 | const struct bb_applet *a; | ||
908 | |||
909 | a = find_applet_by_name(cmd); | ||
910 | if (a) { | ||
911 | const char **new_argv; | ||
912 | const char **argp; | ||
913 | int retval; | ||
914 | |||
915 | for (argp = argv;*argp;argp++); | ||
916 | new_argv = xmalloc(sizeof(const char *)*(argp - argv + 2)); | ||
917 | new_argv[0] = CONFIG_BUSYBOX_EXEC_PATH; | ||
918 | memcpy(&new_argv[1], &argv[0], (argp - argv + 1)*sizeof(const char*)); | ||
919 | cp.argv = new_argv; | ||
920 | trace_argv_printf(new_argv, "git-box: applet:"); | ||
921 | retval = set_exitstatus(run_command(&cp), new_argv, NULL); | ||
922 | free(new_argv); | ||
923 | return retval; | ||
924 | } | ||
925 | } | ||
926 | #endif | ||
927 | |||
928 | /* FIXME | ||
929 | * Need to copy vartab atab cmdtable localvars to the subshell | ||
930 | */ | ||
931 | cp.argv = argv; | ||
932 | trace_argv_printf(argv, "git-box: spawn:"); | ||
933 | return set_exitstatus(run_command(&cp), argv, NULL); | ||
934 | } | ||
935 | |||
936 | static const char * const* | ||
937 | shellspawn_getenv(const struct strlist *newvars) | ||
938 | { | ||
939 | struct var **vpp; | ||
940 | struct var *vp; | ||
941 | const struct strlist *vlp; | ||
942 | char **ep; | ||
943 | int mask; | ||
944 | int on = VEXPORT; | ||
945 | int off = VUNSET; | ||
946 | |||
947 | STARTSTACKSTR(ep); | ||
948 | vpp = vartab; | ||
949 | mask = on | off; | ||
950 | do { | ||
951 | for (vp = *vpp; vp; vp = vp->next) { | ||
952 | if ((vp->flags & mask) == on) { | ||
953 | if (ep == stackstrend()) | ||
954 | ep = growstackstr(); | ||
955 | for (vlp = newvars;vlp;vlp = vlp->next) | ||
956 | if (varequal(vlp->text, vp->text)) | ||
957 | break; | ||
958 | if (!vlp) | ||
959 | *ep++ = (char *) vp->text; | ||
960 | } | ||
961 | } | ||
962 | } while (++vpp < vartab + VTABSIZE); | ||
963 | for (vlp = newvars;vlp;vlp = vlp->next) { | ||
964 | if (ep == stackstrend()) | ||
965 | ep = growstackstr(); | ||
966 | *ep++ = vlp->text; | ||
967 | } | ||
968 | if (ep == stackstrend()) | ||
969 | ep = growstackstr(); | ||
970 | *ep++ = NULL; | ||
971 | return grabstackstr(ep); | ||
972 | } | ||
973 | |||
974 | static int | ||
975 | shellspawn(const char **argv, const char *path, int idx, struct strlist *varlist) | ||
976 | { | ||
977 | char *cmdname; | ||
978 | int e; | ||
979 | const char* const* envp; | ||
980 | |||
981 | /*clearredir(1);*/ | ||
982 | /*listsetvar(varlist.list, VEXPORT|VSTACK);*/ | ||
983 | /*envp = listvars(VEXPORT, VUNSET, 0);*/ | ||
984 | envp = shellspawn_getenv(varlist); | ||
985 | if (strchr(argv[0], '/') | ||
986 | #if ENABLE_FEATURE_SH_STANDALONE | ||
987 | || find_applet_by_name(argv[0]) | ||
988 | #endif | ||
989 | ) { | ||
990 | e = tryspawn(argv[0], argv, envp); | ||
991 | } else { | ||
992 | e = ENOENT; | ||
993 | while ((cmdname = padvance(&path, argv[0])) != NULL) { | ||
994 | if (--idx < 0 && pathopt == NULL) { | ||
995 | e = tryspawn(cmdname, argv, envp); | ||
996 | if (e != -1) break; | ||
997 | } | ||
998 | stunalloc(cmdname); | ||
999 | } | ||
1000 | } | ||
1001 | |||
1002 | if (e == -1) { | ||
1003 | e = errno; | ||
1004 | switch (e) { | ||
1005 | case EACCES: | ||
1006 | exitstatus = 126; | ||
1007 | break; | ||
1008 | case ENOENT: | ||
1009 | exitstatus = 127; | ||
1010 | break; | ||
1011 | default: | ||
1012 | exitstatus = 2; | ||
1013 | break; | ||
1014 | } | ||
1015 | ash_msg_and_raise(EXEXEC, "%s: %s", argv[0], errmsg(e, "not found")); | ||
1016 | } | ||
1017 | return e; | ||
1018 | } | ||
1019 | |||
1020 | static int set_exitstatus(int val, const char **argv,int *out) | ||
1021 | { | ||
1022 | if (!out) | ||
1023 | out = &exitstatus; | ||
1024 | switch (val) { | ||
1025 | case -ERR_RUN_COMMAND_WAITPID_WRONG_PID: | ||
1026 | if (argv) | ||
1027 | ash_msg_and_raise_error("%s: Waitpid on wrong PID",argv[0]); | ||
1028 | else | ||
1029 | ash_msg_and_raise_error("Waitpid on wrong PID"); | ||
1030 | break; | ||
1031 | |||
1032 | case -ERR_RUN_COMMAND_WAITPID_SIGNAL: | ||
1033 | case -ERR_RUN_COMMAND_WAITPID_NOEXIT: | ||
1034 | *out = -val + 128; | ||
1035 | return 0; | ||
1036 | |||
1037 | default: | ||
1038 | *out = -val; | ||
1039 | return 0; | ||
1040 | } | ||
1041 | return -1; | ||
1042 | } | ||
1043 | |||
diff --git a/shell/ash_mingw.h b/shell/ash_mingw.h index 658c7dae2..b7c53e036 100644 --- a/shell/ash_mingw.h +++ b/shell/ash_mingw.h | |||
@@ -12,6 +12,9 @@ static void forkshell_transfer_done(struct forkshell *fs); | |||
12 | static void forkshell_cleanup(struct forkshell *fs); | 12 | static void forkshell_cleanup(struct forkshell *fs); |
13 | static int forkshell(const char *fp, union node *n, int flags); | 13 | static int forkshell(const char *fp, union node *n, int flags); |
14 | static void subshell_run(); | 14 | static void subshell_run(); |
15 | struct strlist; | ||
16 | static int set_exitstatus(int retval, const char **argv, int *out); | ||
17 | static int shellspawn(const char **argv, const char *path, int idx, struct strlist *varlist); | ||
15 | 18 | ||
16 | static int subash_fd = -1; | 19 | static int subash_fd = -1; |
17 | static char subash_entry[16]; | 20 | static char subash_entry[16]; |