diff options
author | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:06:35 +1000 |
---|---|---|
committer | Nguyễn Thái Ngọc Duy <pclouds@gmail.com> | 2010-09-14 11:06:35 +1000 |
commit | 87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4 (patch) | |
tree | c91a4a9a048f3cc2bdae47fa61a02db7a108170d | |
parent | ba3cea41689d211093d914212de048cc06d976ce (diff) | |
parent | 9375ca983262075d8420fd0d88d00a088916fc10 (diff) | |
download | busybox-w32-87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4.tar.gz busybox-w32-87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4.tar.bz2 busybox-w32-87911f4fcd86f7abc0aefba8e9cbec2ac9d127e4.zip |
Merge branch 'ash'
-rw-r--r-- | libbb/Kbuild | 2 | ||||
-rw-r--r-- | libbb/lineedit.c | 10 | ||||
-rw-r--r-- | scripts/defconfig.mingw32 | 6 | ||||
-rw-r--r-- | shell/ash.c | 1088 | ||||
-rw-r--r-- | win32/termios.c | 27 |
5 files changed, 1114 insertions, 19 deletions
diff --git a/libbb/Kbuild b/libbb/Kbuild index eb3cd5039..a8a1da1f9 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild | |||
@@ -74,7 +74,6 @@ lib-y += procps.o | |||
74 | lib-y += progress.o | 74 | lib-y += progress.o |
75 | lib-y += ptr_to_globals.o | 75 | lib-y += ptr_to_globals.o |
76 | lib-y += read.o | 76 | lib-y += read.o |
77 | lib-y += read_key.o | ||
78 | lib-y += recursive_action.o | 77 | lib-y += recursive_action.o |
79 | lib-y += remove_file.o | 78 | lib-y += remove_file.o |
80 | lib-y += run_shell.o | 79 | lib-y += run_shell.o |
@@ -115,6 +114,7 @@ lib-$(CONFIG_PLATFORM_POSIX) += kernel_version.o | |||
115 | lib-$(CONFIG_PLATFORM_POSIX) += login.o | 114 | lib-$(CONFIG_PLATFORM_POSIX) += login.o |
116 | lib-$(CONFIG_PLATFORM_POSIX) += makedev.o | 115 | lib-$(CONFIG_PLATFORM_POSIX) += makedev.o |
117 | lib-$(CONFIG_PLATFORM_POSIX) += match_fstype.o | 116 | lib-$(CONFIG_PLATFORM_POSIX) += match_fstype.o |
117 | lib-$(CONFIG_PLATFORM_POSIX) += read_key.o | ||
118 | lib-$(CONFIG_PLATFORM_POSIX) += safe_gethostname.o | 118 | lib-$(CONFIG_PLATFORM_POSIX) += safe_gethostname.o |
119 | lib-$(CONFIG_PLATFORM_POSIX) += signals.o | 119 | lib-$(CONFIG_PLATFORM_POSIX) += signals.o |
120 | lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o | 120 | lib-$(CONFIG_PLATFORM_POSIX) += udp_io.o |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index dc90846f9..9a04c38bf 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -564,7 +564,11 @@ static int path_parse(char ***p, int flags) | |||
564 | tmp = (char*)pth; | 564 | tmp = (char*)pth; |
565 | npth = 1; /* path component count */ | 565 | npth = 1; /* path component count */ |
566 | while (1) { | 566 | while (1) { |
567 | #if ENABLE_PLATFORM_MINGW32 | ||
568 | tmp = next_path_sep(tmp); | ||
569 | #else | ||
567 | tmp = strchr(tmp, ':'); | 570 | tmp = strchr(tmp, ':'); |
571 | #endif | ||
568 | if (!tmp) | 572 | if (!tmp) |
569 | break; | 573 | break; |
570 | if (*++tmp == '\0') | 574 | if (*++tmp == '\0') |
@@ -576,7 +580,11 @@ static int path_parse(char ***p, int flags) | |||
576 | res[0] = tmp = xstrdup(pth); | 580 | res[0] = tmp = xstrdup(pth); |
577 | npth = 1; | 581 | npth = 1; |
578 | while (1) { | 582 | while (1) { |
583 | #if ENABLE_PLATFORM_MINGW32 | ||
584 | tmp = next_path_sep(tmp); | ||
585 | #else | ||
579 | tmp = strchr(tmp, ':'); | 586 | tmp = strchr(tmp, ':'); |
587 | #endif | ||
580 | if (!tmp) | 588 | if (!tmp) |
581 | break; | 589 | break; |
582 | *tmp++ = '\0'; /* ':' -> '\0' */ | 590 | *tmp++ = '\0'; /* ':' -> '\0' */ |
@@ -1781,6 +1789,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1781 | 1789 | ||
1782 | INIT_S(); | 1790 | INIT_S(); |
1783 | 1791 | ||
1792 | #if !ENABLE_PLATFORM_MINGW32 | ||
1784 | if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 | 1793 | if (tcgetattr(STDIN_FILENO, &initial_settings) < 0 |
1785 | || !(initial_settings.c_lflag & ECHO) | 1794 | || !(initial_settings.c_lflag & ECHO) |
1786 | ) { | 1795 | ) { |
@@ -1794,6 +1803,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
1794 | DEINIT_S(); | 1803 | DEINIT_S(); |
1795 | return len; | 1804 | return len; |
1796 | } | 1805 | } |
1806 | #endif | ||
1797 | 1807 | ||
1798 | init_unicode(); | 1808 | init_unicode(); |
1799 | 1809 | ||
diff --git a/scripts/defconfig.mingw32 b/scripts/defconfig.mingw32 index 37968bbde..356a08226 100644 --- a/scripts/defconfig.mingw32 +++ b/scripts/defconfig.mingw32 | |||
@@ -92,12 +92,12 @@ CONFIG_MD5_SIZE_VS_SPEED=2 | |||
92 | # CONFIG_FEATURE_FAST_TOP is not set | 92 | # CONFIG_FEATURE_FAST_TOP is not set |
93 | # CONFIG_FEATURE_ETC_NETWORKS is not set | 93 | # CONFIG_FEATURE_ETC_NETWORKS is not set |
94 | # CONFIG_FEATURE_CYGWIN_TTY is not set | 94 | # CONFIG_FEATURE_CYGWIN_TTY is not set |
95 | # CONFIG_FEATURE_EDITING is not set | 95 | CONFIG_FEATURE_EDITING=y |
96 | CONFIG_FEATURE_EDITING_MAX_LEN=0 | 96 | CONFIG_FEATURE_EDITING_MAX_LEN=1024 |
97 | # CONFIG_FEATURE_EDITING_VI is not set | 97 | # CONFIG_FEATURE_EDITING_VI is not set |
98 | CONFIG_FEATURE_EDITING_HISTORY=0 | 98 | CONFIG_FEATURE_EDITING_HISTORY=0 |
99 | # CONFIG_FEATURE_EDITING_SAVEHISTORY is not set | 99 | # CONFIG_FEATURE_EDITING_SAVEHISTORY is not set |
100 | # CONFIG_FEATURE_TAB_COMPLETION is not set | 100 | CONFIG_FEATURE_TAB_COMPLETION=y |
101 | # CONFIG_FEATURE_USERNAME_COMPLETION is not set | 101 | # CONFIG_FEATURE_USERNAME_COMPLETION is not set |
102 | # CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set | 102 | # CONFIG_FEATURE_EDITING_FANCY_PROMPT is not set |
103 | # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set | 103 | # CONFIG_FEATURE_EDITING_ASK_TERMINAL is not set |
diff --git a/shell/ash.c b/shell/ash.c index ab935e72a..5d8415a79 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -17,6 +17,18 @@ | |||
17 | */ | 17 | */ |
18 | 18 | ||
19 | /* | 19 | /* |
20 | * MinGW notes | ||
21 | * | ||
22 | * - Environment variables from Windows will all be turned to uppercase. | ||
23 | * - PATH accepts both ; and : as separator, but can't be mixed | ||
24 | * - command without ".exe" is still understood as executable (option to turn off?) | ||
25 | * - both / and \ are supported in PATH. Usually you must use / | ||
26 | * - trap/job does not work | ||
27 | * - /dev/null is supported for redirection | ||
28 | * - no $PPID | ||
29 | */ | ||
30 | |||
31 | /* | ||
20 | * The following should be set to reflect the type of system you have: | 32 | * The following should be set to reflect the type of system you have: |
21 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. | 33 | * JOBS -> 1 if you have Berkeley job control, 0 otherwise. |
22 | * define SYSV if you are running under System V. | 34 | * define SYSV if you are running under System V. |
@@ -81,6 +93,41 @@ | |||
81 | # error "Do not even bother, ash will not run on NOMMU machine" | 93 | # error "Do not even bother, ash will not run on NOMMU machine" |
82 | #endif | 94 | #endif |
83 | 95 | ||
96 | #if ENABLE_PLATFORM_MINGW32 | ||
97 | struct forkshell; | ||
98 | union node; | ||
99 | struct strlist; | ||
100 | struct job; | ||
101 | |||
102 | typedef void (*forkpoint_fn)(struct forkshell *fs); | ||
103 | struct forkshell { | ||
104 | /* filled by forkshell_copy() */ | ||
105 | struct globals_var *gvp; | ||
106 | struct globals_misc *gmp; | ||
107 | struct tblentry **cmdtable; | ||
108 | struct localvar *localvars; | ||
109 | /* struct alias **atab; */ | ||
110 | /* struct parsefile *g_parsefile; */ | ||
111 | int fpid; | ||
112 | HANDLE hMapFile; | ||
113 | void *old_base; | ||
114 | int nodeptr_offset; | ||
115 | int size; | ||
116 | |||
117 | forkpoint_fn fp; | ||
118 | /* optional data, used by forkpoint_fn */ | ||
119 | int flags; | ||
120 | int fd[10]; | ||
121 | union node *n; | ||
122 | char **argv; | ||
123 | char *string; | ||
124 | struct strlist *strlist; | ||
125 | pid_t pid; | ||
126 | }; | ||
127 | static void sticky_free(void *p); | ||
128 | #define free(p) sticky_free(p) | ||
129 | static int spawn_forkshell(struct job *jp, struct forkshell *fs, int mode); | ||
130 | #endif | ||
84 | 131 | ||
85 | /* ============ Hash table sizes. Configurable. */ | 132 | /* ============ Hash table sizes. Configurable. */ |
86 | 133 | ||
@@ -774,7 +821,7 @@ static void | |||
774 | opentrace(void) | 821 | opentrace(void) |
775 | { | 822 | { |
776 | char s[100]; | 823 | char s[100]; |
777 | #ifdef O_APPEND | 824 | #if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32 |
778 | int flags; | 825 | int flags; |
779 | #endif | 826 | #endif |
780 | 827 | ||
@@ -799,7 +846,7 @@ opentrace(void) | |||
799 | return; | 846 | return; |
800 | } | 847 | } |
801 | } | 848 | } |
802 | #ifdef O_APPEND | 849 | #if defined(O_APPEND) && !ENABLE_PLATFORM_MINGW32 |
803 | flags = fcntl(fileno(tracefile), F_GETFL); | 850 | flags = fcntl(fileno(tracefile), F_GETFL); |
804 | if (flags >= 0) | 851 | if (flags >= 0) |
805 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); | 852 | fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND); |
@@ -2261,10 +2308,22 @@ path_advance(const char **path, const char *name) | |||
2261 | if (*path == NULL) | 2308 | if (*path == NULL) |
2262 | return NULL; | 2309 | return NULL; |
2263 | start = *path; | 2310 | start = *path; |
2311 | #if ENABLE_PLATFORM_MINGW32 | ||
2312 | p = next_path_sep(start); | ||
2313 | q = strchr(start, '%'); | ||
2314 | if ((p && q && q < p) || (!p && q)) | ||
2315 | p = q; | ||
2316 | if (!p) | ||
2317 | for (p = start; *p; p++) | ||
2318 | continue; | ||
2319 | #else | ||
2264 | for (p = start; *p && *p != ':' && *p != '%'; p++) | 2320 | for (p = start; *p && *p != ':' && *p != '%'; p++) |
2265 | continue; | 2321 | continue; |
2322 | #endif | ||
2266 | len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ | 2323 | len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ |
2267 | while (stackblocksize() < len) | 2324 | |
2325 | /* preserve space for .exe too */ | ||
2326 | while (stackblocksize() < (ENABLE_PLATFORM_MINGW32 ? len+4 : len)) | ||
2268 | growstackblock(); | 2327 | growstackblock(); |
2269 | q = stackblock(); | 2328 | q = stackblock(); |
2270 | if (p != start) { | 2329 | if (p != start) { |
@@ -2380,6 +2439,98 @@ cdopt(void) | |||
2380 | static const char * | 2439 | static const char * |
2381 | updatepwd(const char *dir) | 2440 | updatepwd(const char *dir) |
2382 | { | 2441 | { |
2442 | #if ENABLE_PLATFORM_MINGW32 | ||
2443 | /* | ||
2444 | * Due to Windows drive notion, getting pwd is a completely | ||
2445 | * different thing. Handle it in a separate routine | ||
2446 | */ | ||
2447 | |||
2448 | char *new; | ||
2449 | char *p; | ||
2450 | char *cdcomppath; | ||
2451 | const char *lim; | ||
2452 | /* | ||
2453 | * There are four cases | ||
2454 | * absdrive + abspath: c:/path | ||
2455 | * absdrive + !abspath: c:path | ||
2456 | * !absdrive + abspath: /path | ||
2457 | * !absdrive + !abspath: path | ||
2458 | * | ||
2459 | * Damn DOS! | ||
2460 | * c:path behaviour is "undefined" | ||
2461 | * To properly handle this case, I have to keep track of cwd | ||
2462 | * of every drive, which is too painful to do. | ||
2463 | * So when c:path is given, I assume it's c:${curdir}path | ||
2464 | * with ${curdir} comes from the current drive | ||
2465 | */ | ||
2466 | int absdrive = *dir && dir[1] == ':'; | ||
2467 | int abspath = absdrive ? dir[2] == '/' : *dir == '/'; | ||
2468 | char *drive; | ||
2469 | |||
2470 | cdcomppath = ststrdup(dir); | ||
2471 | STARTSTACKSTR(new); | ||
2472 | if (!absdrive && curdir == nullstr) | ||
2473 | return 0; | ||
2474 | if (!abspath) { | ||
2475 | if (curdir == nullstr) | ||
2476 | return 0; | ||
2477 | new = stack_putstr(curdir, new); | ||
2478 | } | ||
2479 | new = makestrspace(strlen(dir) + 2, new); | ||
2480 | |||
2481 | drive = stackblock(); | ||
2482 | if (absdrive) { | ||
2483 | *drive = *dir; | ||
2484 | cdcomppath += 2; | ||
2485 | dir += 2; | ||
2486 | } else { | ||
2487 | *drive = *curdir; | ||
2488 | } | ||
2489 | drive[1] = ':'; /* in case of absolute drive+path */ | ||
2490 | |||
2491 | if (abspath) | ||
2492 | new = drive + 2; | ||
2493 | lim = drive + 3; | ||
2494 | if (!abspath) { | ||
2495 | if (new[-1] != '/') | ||
2496 | USTPUTC('/', new); | ||
2497 | if (new > lim && *lim == '/') | ||
2498 | lim++; | ||
2499 | } else { | ||
2500 | USTPUTC('/', new); | ||
2501 | cdcomppath ++; | ||
2502 | if (dir[1] == '/' && dir[2] != '/') { | ||
2503 | USTPUTC('/', new); | ||
2504 | cdcomppath++; | ||
2505 | lim++; | ||
2506 | } | ||
2507 | } | ||
2508 | p = strtok(cdcomppath, "/"); | ||
2509 | while (p) { | ||
2510 | switch (*p) { | ||
2511 | case '.': | ||
2512 | if (p[1] == '.' && p[2] == '\0') { | ||
2513 | while (new > lim) { | ||
2514 | STUNPUTC(new); | ||
2515 | if (new[-1] == '/') | ||
2516 | break; | ||
2517 | } | ||
2518 | break; | ||
2519 | } | ||
2520 | if (p[1] == '\0') | ||
2521 | break; | ||
2522 | /* fall through */ | ||
2523 | default: | ||
2524 | new = stack_putstr(p, new); | ||
2525 | USTPUTC('/', new); | ||
2526 | } | ||
2527 | p = strtok(0, "/"); | ||
2528 | } | ||
2529 | if (new > lim) | ||
2530 | STUNPUTC(new); | ||
2531 | *new = 0; | ||
2532 | return stackblock(); | ||
2533 | #else | ||
2383 | char *new; | 2534 | char *new; |
2384 | char *p; | 2535 | char *p; |
2385 | char *cdcomppath; | 2536 | char *cdcomppath; |
@@ -2433,6 +2584,7 @@ updatepwd(const char *dir) | |||
2433 | STUNPUTC(new); | 2584 | STUNPUTC(new); |
2434 | *new = 0; | 2585 | *new = 0; |
2435 | return stackblock(); | 2586 | return stackblock(); |
2587 | #endif | ||
2436 | } | 2588 | } |
2437 | 2589 | ||
2438 | /* | 2590 | /* |
@@ -2527,7 +2679,7 @@ cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
2527 | } | 2679 | } |
2528 | if (!dest) | 2680 | if (!dest) |
2529 | dest = nullstr; | 2681 | dest = nullstr; |
2530 | if (*dest == '/') | 2682 | if (is_absolute_path(dest)) |
2531 | goto step7; | 2683 | goto step7; |
2532 | if (*dest == '.') { | 2684 | if (*dest == '.') { |
2533 | c = dest[1]; | 2685 | c = dest[1]; |
@@ -3301,6 +3453,8 @@ setsignal(int signo) | |||
3301 | char cur_act, new_act; | 3453 | char cur_act, new_act; |
3302 | struct sigaction act; | 3454 | struct sigaction act; |
3303 | 3455 | ||
3456 | if (ENABLE_PLATFORM_MINGW32) | ||
3457 | return; | ||
3304 | t = trap[signo]; | 3458 | t = trap[signo]; |
3305 | new_act = S_DFL; | 3459 | new_act = S_DFL; |
3306 | if (t != NULL) { /* trap for this sig is set */ | 3460 | if (t != NULL) { /* trap for this sig is set */ |
@@ -3608,7 +3762,7 @@ setjobctl(int on) | |||
3608 | if (--fd < 0) | 3762 | if (--fd < 0) |
3609 | goto out; | 3763 | goto out; |
3610 | } | 3764 | } |
3611 | fd = fcntl(fd, F_DUPFD, 10); | 3765 | fd = copyfd(fd, 10); |
3612 | if (ofd >= 0) | 3766 | if (ofd >= 0) |
3613 | close(ofd); | 3767 | close(ofd); |
3614 | if (fd < 0) | 3768 | if (fd < 0) |
@@ -3782,6 +3936,53 @@ sprint_status(char *s, int status, int sigonly) | |||
3782 | return col; | 3936 | return col; |
3783 | } | 3937 | } |
3784 | 3938 | ||
3939 | #if ENABLE_PLATFORM_MINGW32 | ||
3940 | /* | ||
3941 | * Windows does not know about parent-child relationship | ||
3942 | * They don't support waitpid(-1) | ||
3943 | */ | ||
3944 | static pid_t | ||
3945 | waitpid_child(int *status) | ||
3946 | { | ||
3947 | HANDLE *pidlist, *pidp; | ||
3948 | int pid_nr = 0; | ||
3949 | pid_t pid; | ||
3950 | DWORD win_status, idx; | ||
3951 | struct job *jb; | ||
3952 | |||
3953 | #define LOOP(stmt) \ | ||
3954 | for (jb = curjob; jb; jb = jb->prev_job) { \ | ||
3955 | struct procstat *ps, *psend; \ | ||
3956 | if (jb->state == JOBDONE) \ | ||
3957 | continue; \ | ||
3958 | ps = jb->ps; \ | ||
3959 | psend = ps + jb->nprocs; \ | ||
3960 | while (ps < psend) { \ | ||
3961 | if (ps->ps_pid != -1) { \ | ||
3962 | stmt; \ | ||
3963 | } \ | ||
3964 | ps++; \ | ||
3965 | } \ | ||
3966 | } | ||
3967 | |||
3968 | LOOP(pid_nr++); | ||
3969 | pidp = pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); | ||
3970 | LOOP(*pidp++ = (HANDLE)ps->ps_pid); | ||
3971 | #undef LOOP | ||
3972 | |||
3973 | idx = WaitForMultipleObjects(pid_nr, pidlist, FALSE, INFINITE); | ||
3974 | if (idx >= pid_nr) { | ||
3975 | free(pidlist); | ||
3976 | return -1; | ||
3977 | } | ||
3978 | GetExitCodeProcess(pidlist[idx], &win_status); | ||
3979 | pid = (int)pidlist[idx]; | ||
3980 | free(pidlist); | ||
3981 | *status = (int)win_status; | ||
3982 | return pid; | ||
3983 | } | ||
3984 | #endif | ||
3985 | |||
3785 | static int | 3986 | static int |
3786 | dowait(int wait_flags, struct job *job) | 3987 | dowait(int wait_flags, struct job *job) |
3787 | { | 3988 | { |
@@ -3798,7 +3999,11 @@ dowait(int wait_flags, struct job *job) | |||
3798 | * NB: _not_ safe_waitpid, we need to detect EINTR */ | 3999 | * NB: _not_ safe_waitpid, we need to detect EINTR */ |
3799 | if (doing_jobctl) | 4000 | if (doing_jobctl) |
3800 | wait_flags |= WUNTRACED; | 4001 | wait_flags |= WUNTRACED; |
4002 | #if ENABLE_PLATFORM_MINGW32 | ||
4003 | pid = waitpid_child(&status); | ||
4004 | #else | ||
3801 | pid = waitpid(-1, &status, wait_flags); | 4005 | pid = waitpid(-1, &status, wait_flags); |
4006 | #endif | ||
3802 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", | 4007 | TRACE(("wait returns pid=%d, status=0x%x, errno=%d(%s)\n", |
3803 | pid, status, errno, strerror(errno))); | 4008 | pid, status, errno, strerror(errno))); |
3804 | if (pid <= 0) | 4009 | if (pid <= 0) |
@@ -3821,6 +4026,8 @@ dowait(int wait_flags, struct job *job) | |||
3821 | jobno(jp), pid, ps->ps_status, status)); | 4026 | jobno(jp), pid, ps->ps_status, status)); |
3822 | ps->ps_status = status; | 4027 | ps->ps_status = status; |
3823 | thisjob = jp; | 4028 | thisjob = jp; |
4029 | if (ENABLE_PLATFORM_MINGW32) | ||
4030 | ps->ps_pid = -1; | ||
3824 | } | 4031 | } |
3825 | if (ps->ps_status == -1) | 4032 | if (ps->ps_status == -1) |
3826 | state = JOBRUNNING; | 4033 | state = JOBRUNNING; |
@@ -4052,6 +4259,9 @@ waitcmd(int argc UNUSED_PARAM, char **argv) | |||
4052 | int retval; | 4259 | int retval; |
4053 | struct job *jp; | 4260 | struct job *jp; |
4054 | 4261 | ||
4262 | if (ENABLE_PLATFORM_MINGW32) | ||
4263 | return 0; | ||
4264 | |||
4055 | if (pending_sig) | 4265 | if (pending_sig) |
4056 | raise_exception(EXSIG); | 4266 | raise_exception(EXSIG); |
4057 | 4267 | ||
@@ -4655,7 +4865,7 @@ static void | |||
4655 | forkparent(struct job *jp, union node *n, int mode, pid_t pid) | 4865 | forkparent(struct job *jp, union node *n, int mode, pid_t pid) |
4656 | { | 4866 | { |
4657 | TRACE(("In parent shell: child = %d\n", pid)); | 4867 | TRACE(("In parent shell: child = %d\n", pid)); |
4658 | if (!jp) { | 4868 | if (!jp && !ENABLE_PLATFORM_MINGW32) { /* FIXME not quite understand this */ |
4659 | while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) | 4869 | while (jobless && dowait(DOWAIT_NONBLOCK, NULL) > 0) |
4660 | continue; | 4870 | continue; |
4661 | jobless++; | 4871 | jobless++; |
@@ -4695,6 +4905,9 @@ forkshell(struct job *jp, union node *n, int mode) | |||
4695 | int pid; | 4905 | int pid; |
4696 | 4906 | ||
4697 | TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); | 4907 | TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode)); |
4908 | if (ENABLE_PLATFORM_MINGW32) | ||
4909 | return -1; | ||
4910 | |||
4698 | pid = fork(); | 4911 | pid = fork(); |
4699 | if (pid < 0) { | 4912 | if (pid < 0) { |
4700 | TRACE(("Fork failed, errno=%d", errno)); | 4913 | TRACE(("Fork failed, errno=%d", errno)); |
@@ -4891,11 +5104,39 @@ noclobberopen(const char *fname) | |||
4891 | */ | 5104 | */ |
4892 | /* openhere needs this forward reference */ | 5105 | /* openhere needs this forward reference */ |
4893 | static void expandhere(union node *arg, int fd); | 5106 | static void expandhere(union node *arg, int fd); |
5107 | #if ENABLE_PLATFORM_MINGW32 | ||
5108 | static void | ||
5109 | forkshell_openhere(struct forkshell *fs) | ||
5110 | { | ||
5111 | union node *redir = fs->n; | ||
5112 | int pip[2]; | ||
5113 | |||
5114 | pip[0] = fs->fd[0]; | ||
5115 | pip[1] = fs->fd[1]; | ||
5116 | |||
5117 | TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); | ||
5118 | |||
5119 | close(pip[0]); | ||
5120 | ignoresig(SIGINT); //signal(SIGINT, SIG_IGN); | ||
5121 | ignoresig(SIGQUIT); //signal(SIGQUIT, SIG_IGN); | ||
5122 | ignoresig(SIGHUP); //signal(SIGHUP, SIG_IGN); | ||
5123 | ignoresig(SIGTSTP); //signal(SIGTSTP, SIG_IGN); | ||
5124 | signal(SIGPIPE, SIG_DFL); | ||
5125 | if (redir->type == NHERE) { | ||
5126 | size_t len = strlen(redir->nhere.doc->narg.text); | ||
5127 | full_write(pip[1], redir->nhere.doc->narg.text, len); | ||
5128 | } else /* NXHERE */ | ||
5129 | expandhere(redir->nhere.doc, pip[1]); | ||
5130 | _exit(EXIT_SUCCESS); | ||
5131 | } | ||
5132 | #endif | ||
5133 | |||
4894 | static int | 5134 | static int |
4895 | openhere(union node *redir) | 5135 | openhere(union node *redir) |
4896 | { | 5136 | { |
4897 | int pip[2]; | 5137 | int pip[2]; |
4898 | size_t len = 0; | 5138 | size_t len = 0; |
5139 | IF_PLATFORM_MINGW32(struct forkshell fs); | ||
4899 | 5140 | ||
4900 | if (pipe(pip) < 0) | 5141 | if (pipe(pip) < 0) |
4901 | ash_msg_and_raise_error("pipe call failed"); | 5142 | ash_msg_and_raise_error("pipe call failed"); |
@@ -4906,6 +5147,16 @@ openhere(union node *redir) | |||
4906 | goto out; | 5147 | goto out; |
4907 | } | 5148 | } |
4908 | } | 5149 | } |
5150 | #if ENABLE_PLATFORM_MINGW32 | ||
5151 | memset(&fs, 0, sizeof(fs)); | ||
5152 | fs.fp = forkshell_openhere; | ||
5153 | fs.flags = 0; | ||
5154 | fs.n = redir; | ||
5155 | fs.fd[0] = pip[0]; | ||
5156 | fs.fd[1] = pip[1]; | ||
5157 | if (spawn_forkshell(NULL, &fs, FORK_NOJOB) < 0) | ||
5158 | ash_msg_and_raise_error("unable to spawn shell"); | ||
5159 | #endif | ||
4909 | if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { | 5160 | if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) { |
4910 | /* child */ | 5161 | /* child */ |
4911 | close(pip[0]); | 5162 | close(pip[0]); |
@@ -4931,6 +5182,31 @@ openredirect(union node *redir) | |||
4931 | char *fname; | 5182 | char *fname; |
4932 | int f; | 5183 | int f; |
4933 | 5184 | ||
5185 | #if ENABLE_PLATFORM_MINGW32 | ||
5186 | /* Support for /dev/null */ | ||
5187 | switch (redir->nfile.type) { | ||
5188 | case NFROM: | ||
5189 | if (!strcmp(redir->nfile.expfname, "/dev/null")) | ||
5190 | return open("nul",O_RDWR); | ||
5191 | if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { | ||
5192 | ash_msg("Unhandled device %s\n", redir->nfile.expfname); | ||
5193 | return -1; | ||
5194 | } | ||
5195 | break; | ||
5196 | |||
5197 | case NFROMTO: | ||
5198 | case NTO: | ||
5199 | case NCLOBBER: | ||
5200 | case NAPPEND: | ||
5201 | if (!strcmp(redir->nfile.expfname, "/dev/null")) | ||
5202 | return open("nul",O_RDWR); | ||
5203 | if (!strncmp(redir->nfile.expfname, "/dev/", 5)) { | ||
5204 | ash_msg("Unhandled device %s\n", redir->nfile.expfname); | ||
5205 | return -1; | ||
5206 | } | ||
5207 | break; | ||
5208 | } | ||
5209 | #endif | ||
4934 | switch (redir->nfile.type) { | 5210 | switch (redir->nfile.type) { |
4935 | case NFROM: | 5211 | case NFROM: |
4936 | fname = redir->nfile.expfname; | 5212 | fname = redir->nfile.expfname; |
@@ -5013,6 +5289,18 @@ copyfd(int from, int to) | |||
5013 | /*if (from != to)*/ | 5289 | /*if (from != to)*/ |
5014 | newfd = dup2(from, to); | 5290 | newfd = dup2(from, to); |
5015 | } else { | 5291 | } else { |
5292 | if (ENABLE_PLATFORM_MINGW32) { | ||
5293 | char* fds = ckmalloc(to); | ||
5294 | int i,fd; | ||
5295 | memset(fds,0,to); | ||
5296 | while ((fd = dup(from)) < to && fd >= 0) | ||
5297 | fds[fd] = 1; | ||
5298 | for (i = 0;i < to;i ++) | ||
5299 | if (fds[i]) | ||
5300 | close(i); | ||
5301 | free(fds); | ||
5302 | return fd; | ||
5303 | } | ||
5016 | newfd = fcntl(from, F_DUPFD, to); | 5304 | newfd = fcntl(from, F_DUPFD, to); |
5017 | } | 5305 | } |
5018 | if (newfd < 0) { | 5306 | if (newfd < 0) { |
@@ -5157,7 +5445,7 @@ redirect(union node *redir, int flags) | |||
5157 | #endif | 5445 | #endif |
5158 | if (need_to_remember(sv, fd)) { | 5446 | if (need_to_remember(sv, fd)) { |
5159 | /* Copy old descriptor */ | 5447 | /* Copy old descriptor */ |
5160 | i = fcntl(fd, F_DUPFD, 10); | 5448 | i = copyfd(fd, 10); |
5161 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds | 5449 | /* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds |
5162 | * are closed in popredir() in the child, preventing them from leaking | 5450 | * are closed in popredir() in the child, preventing them from leaking |
5163 | * into child. (popredir() also cleans up the mess in case of failures) | 5451 | * into child. (popredir() also cleans up the mess in case of failures) |
@@ -5618,6 +5906,8 @@ exptilde(char *startp, char *p, int flags) | |||
5618 | if (*name == '\0') { | 5906 | if (*name == '\0') { |
5619 | home = lookupvar(homestr); | 5907 | home = lookupvar(homestr); |
5620 | } else { | 5908 | } else { |
5909 | if (ENABLE_PLATFORM_MINGW32) | ||
5910 | goto lose; | ||
5621 | pw = getpwnam(name); | 5911 | pw = getpwnam(name); |
5622 | if (pw == NULL) | 5912 | if (pw == NULL) |
5623 | goto lose; | 5913 | goto lose; |
@@ -5645,6 +5935,7 @@ struct backcmd { /* result of evalbackcmd */ | |||
5645 | int fd; /* file descriptor to read from */ | 5935 | int fd; /* file descriptor to read from */ |
5646 | int nleft; /* number of chars in buffer */ | 5936 | int nleft; /* number of chars in buffer */ |
5647 | char *buf; /* buffer */ | 5937 | char *buf; /* buffer */ |
5938 | IF_PLATFORM_MINGW32(struct forkshell fs); | ||
5648 | struct job *jp; /* job structure for command */ | 5939 | struct job *jp; /* job structure for command */ |
5649 | }; | 5940 | }; |
5650 | 5941 | ||
@@ -5653,6 +5944,25 @@ static uint8_t back_exitstatus; /* exit status of backquoted command */ | |||
5653 | #define EV_EXIT 01 /* exit after evaluating tree */ | 5944 | #define EV_EXIT 01 /* exit after evaluating tree */ |
5654 | static void evaltree(union node *, int); | 5945 | static void evaltree(union node *, int); |
5655 | 5946 | ||
5947 | #if ENABLE_PLATFORM_MINGW32 | ||
5948 | static void | ||
5949 | forkshell_evalbackcmd(struct forkshell *fs) | ||
5950 | { | ||
5951 | union node *n = fs->n; | ||
5952 | int pip[2] = {fs->fd[0], fs->fd[1]}; | ||
5953 | |||
5954 | FORCE_INT_ON; | ||
5955 | close(pip[0]); | ||
5956 | if (pip[1] != 1) { | ||
5957 | /*close(1);*/ | ||
5958 | copyfd(pip[1], 1 | COPYFD_EXACT); | ||
5959 | close(pip[1]); | ||
5960 | } | ||
5961 | eflag = 0; | ||
5962 | evaltree(n, EV_EXIT); /* actually evaltreenr... */ | ||
5963 | /* NOTREACHED */ | ||
5964 | } | ||
5965 | #endif | ||
5656 | static void FAST_FUNC | 5966 | static void FAST_FUNC |
5657 | evalbackcmd(union node *n, struct backcmd *result) | 5967 | evalbackcmd(union node *n, struct backcmd *result) |
5658 | { | 5968 | { |
@@ -5661,6 +5971,7 @@ evalbackcmd(union node *n, struct backcmd *result) | |||
5661 | result->fd = -1; | 5971 | result->fd = -1; |
5662 | result->buf = NULL; | 5972 | result->buf = NULL; |
5663 | result->nleft = 0; | 5973 | result->nleft = 0; |
5974 | IF_PLATFORM_MINGW32(memset(&result->fs, 0, sizeof(result->fs))); | ||
5664 | result->jp = NULL; | 5975 | result->jp = NULL; |
5665 | if (n == NULL) | 5976 | if (n == NULL) |
5666 | goto out; | 5977 | goto out; |
@@ -5675,6 +5986,14 @@ evalbackcmd(union node *n, struct backcmd *result) | |||
5675 | if (pipe(pip) < 0) | 5986 | if (pipe(pip) < 0) |
5676 | ash_msg_and_raise_error("pipe call failed"); | 5987 | ash_msg_and_raise_error("pipe call failed"); |
5677 | jp = makejob(/*n,*/ 1); | 5988 | jp = makejob(/*n,*/ 1); |
5989 | #if ENABLE_PLATFORM_MINGW32 | ||
5990 | result->fs.fp = forkshell_evalbackcmd; | ||
5991 | result->fs.n = n; | ||
5992 | result->fs.fd[0] = pip[0]; | ||
5993 | result->fs.fd[1] = pip[1]; | ||
5994 | if (spawn_forkshell(jp, &result->fs, FORK_NOJOB) < 0) | ||
5995 | ash_msg_and_raise_error("unable to spawn shell"); | ||
5996 | #endif | ||
5678 | if (forkshell(jp, n, FORK_NOJOB) == 0) { | 5997 | if (forkshell(jp, n, FORK_NOJOB) == 0) { |
5679 | FORCE_INT_ON; | 5998 | FORCE_INT_ON; |
5680 | close(pip[0]); | 5999 | close(pip[0]); |
@@ -7290,7 +7609,7 @@ shellexec(char **argv, const char *path, int idx) | |||
7290 | 7609 | ||
7291 | clearredir(/*drop:*/ 1); | 7610 | clearredir(/*drop:*/ 1); |
7292 | envp = listvars(VEXPORT, VUNSET, 0); | 7611 | envp = listvars(VEXPORT, VUNSET, 0); |
7293 | if (strchr(argv[0], '/') != NULL | 7612 | if ((strchr(argv[0], '/') || (ENABLE_PLATFORM_MINGW32 && strchr(argv[0], '\\'))) |
7294 | #if ENABLE_FEATURE_SH_STANDALONE | 7613 | #if ENABLE_FEATURE_SH_STANDALONE |
7295 | || (applet_no = find_applet_by_name(argv[0])) >= 0 | 7614 | || (applet_no = find_applet_by_name(argv[0])) >= 0 |
7296 | #endif | 7615 | #endif |
@@ -7807,6 +8126,10 @@ static int funcblocksize; /* size of structures in function */ | |||
7807 | static int funcstringsize; /* size of strings in node */ | 8126 | static int funcstringsize; /* size of strings in node */ |
7808 | static void *funcblock; /* block to allocate function from */ | 8127 | static void *funcblock; /* block to allocate function from */ |
7809 | static char *funcstring; /* block to allocate strings from */ | 8128 | static char *funcstring; /* block to allocate strings from */ |
8129 | #if ENABLE_PLATFORM_MINGW32 | ||
8130 | static int nodeptrsize; | ||
8131 | static int *nodeptr; | ||
8132 | #endif | ||
7810 | 8133 | ||
7811 | /* flags in argument to evaltree */ | 8134 | /* flags in argument to evaltree */ |
7812 | #define EV_EXIT 01 /* exit after evaluating tree */ | 8135 | #define EV_EXIT 01 /* exit after evaluating tree */ |
@@ -7852,6 +8175,7 @@ sizenodelist(struct nodelist *lp) | |||
7852 | { | 8175 | { |
7853 | while (lp) { | 8176 | while (lp) { |
7854 | funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); | 8177 | funcblocksize += SHELL_ALIGN(sizeof(struct nodelist)); |
8178 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7855 | calcsize(lp->n); | 8179 | calcsize(lp->n); |
7856 | lp = lp->next; | 8180 | lp = lp->next; |
7857 | } | 8181 | } |
@@ -7868,15 +8192,18 @@ calcsize(union node *n) | |||
7868 | calcsize(n->ncmd.redirect); | 8192 | calcsize(n->ncmd.redirect); |
7869 | calcsize(n->ncmd.args); | 8193 | calcsize(n->ncmd.args); |
7870 | calcsize(n->ncmd.assign); | 8194 | calcsize(n->ncmd.assign); |
8195 | IF_PLATFORM_MINGW32(nodeptrsize += 3); | ||
7871 | break; | 8196 | break; |
7872 | case NPIPE: | 8197 | case NPIPE: |
7873 | sizenodelist(n->npipe.cmdlist); | 8198 | sizenodelist(n->npipe.cmdlist); |
8199 | IF_PLATFORM_MINGW32(nodeptrsize++); | ||
7874 | break; | 8200 | break; |
7875 | case NREDIR: | 8201 | case NREDIR: |
7876 | case NBACKGND: | 8202 | case NBACKGND: |
7877 | case NSUBSHELL: | 8203 | case NSUBSHELL: |
7878 | calcsize(n->nredir.redirect); | 8204 | calcsize(n->nredir.redirect); |
7879 | calcsize(n->nredir.n); | 8205 | calcsize(n->nredir.n); |
8206 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7880 | break; | 8207 | break; |
7881 | case NAND: | 8208 | case NAND: |
7882 | case NOR: | 8209 | case NOR: |
@@ -7885,31 +8212,37 @@ calcsize(union node *n) | |||
7885 | case NUNTIL: | 8212 | case NUNTIL: |
7886 | calcsize(n->nbinary.ch2); | 8213 | calcsize(n->nbinary.ch2); |
7887 | calcsize(n->nbinary.ch1); | 8214 | calcsize(n->nbinary.ch1); |
8215 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7888 | break; | 8216 | break; |
7889 | case NIF: | 8217 | case NIF: |
7890 | calcsize(n->nif.elsepart); | 8218 | calcsize(n->nif.elsepart); |
7891 | calcsize(n->nif.ifpart); | 8219 | calcsize(n->nif.ifpart); |
7892 | calcsize(n->nif.test); | 8220 | calcsize(n->nif.test); |
8221 | IF_PLATFORM_MINGW32(nodeptrsize += 3); | ||
7893 | break; | 8222 | break; |
7894 | case NFOR: | 8223 | case NFOR: |
7895 | funcstringsize += strlen(n->nfor.var) + 1; | 8224 | funcstringsize += strlen(n->nfor.var) + 1; |
7896 | calcsize(n->nfor.body); | 8225 | calcsize(n->nfor.body); |
7897 | calcsize(n->nfor.args); | 8226 | calcsize(n->nfor.args); |
8227 | IF_PLATFORM_MINGW32(nodeptrsize += 3); | ||
7898 | break; | 8228 | break; |
7899 | case NCASE: | 8229 | case NCASE: |
7900 | calcsize(n->ncase.cases); | 8230 | calcsize(n->ncase.cases); |
7901 | calcsize(n->ncase.expr); | 8231 | calcsize(n->ncase.expr); |
8232 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7902 | break; | 8233 | break; |
7903 | case NCLIST: | 8234 | case NCLIST: |
7904 | calcsize(n->nclist.body); | 8235 | calcsize(n->nclist.body); |
7905 | calcsize(n->nclist.pattern); | 8236 | calcsize(n->nclist.pattern); |
7906 | calcsize(n->nclist.next); | 8237 | calcsize(n->nclist.next); |
8238 | IF_PLATFORM_MINGW32(nodeptrsize += 3); | ||
7907 | break; | 8239 | break; |
7908 | case NDEFUN: | 8240 | case NDEFUN: |
7909 | case NARG: | 8241 | case NARG: |
7910 | sizenodelist(n->narg.backquote); | 8242 | sizenodelist(n->narg.backquote); |
7911 | funcstringsize += strlen(n->narg.text) + 1; | 8243 | funcstringsize += strlen(n->narg.text) + 1; |
7912 | calcsize(n->narg.next); | 8244 | calcsize(n->narg.next); |
8245 | IF_PLATFORM_MINGW32(nodeptrsize += 3); | ||
7913 | break; | 8246 | break; |
7914 | case NTO: | 8247 | case NTO: |
7915 | #if ENABLE_ASH_BASH_COMPAT | 8248 | #if ENABLE_ASH_BASH_COMPAT |
@@ -7921,28 +8254,34 @@ calcsize(union node *n) | |||
7921 | case NAPPEND: | 8254 | case NAPPEND: |
7922 | calcsize(n->nfile.fname); | 8255 | calcsize(n->nfile.fname); |
7923 | calcsize(n->nfile.next); | 8256 | calcsize(n->nfile.next); |
8257 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7924 | break; | 8258 | break; |
7925 | case NTOFD: | 8259 | case NTOFD: |
7926 | case NFROMFD: | 8260 | case NFROMFD: |
7927 | calcsize(n->ndup.vname); | 8261 | calcsize(n->ndup.vname); |
7928 | calcsize(n->ndup.next); | 8262 | calcsize(n->ndup.next); |
8263 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7929 | break; | 8264 | break; |
7930 | case NHERE: | 8265 | case NHERE: |
7931 | case NXHERE: | 8266 | case NXHERE: |
7932 | calcsize(n->nhere.doc); | 8267 | calcsize(n->nhere.doc); |
7933 | calcsize(n->nhere.next); | 8268 | calcsize(n->nhere.next); |
8269 | IF_PLATFORM_MINGW32(nodeptrsize += 2); | ||
7934 | break; | 8270 | break; |
7935 | case NNOT: | 8271 | case NNOT: |
7936 | calcsize(n->nnot.com); | 8272 | calcsize(n->nnot.com); |
8273 | IF_PLATFORM_MINGW32(nodeptrsize++); | ||
7937 | break; | 8274 | break; |
7938 | }; | 8275 | }; |
7939 | } | 8276 | } |
7940 | 8277 | ||
7941 | static char * | 8278 | static char * |
7942 | nodeckstrdup(char *s) | 8279 | nodeckstrdup(const char *s) |
7943 | { | 8280 | { |
7944 | char *rtn = funcstring; | 8281 | char *rtn = funcstring; |
7945 | 8282 | ||
8283 | if (!s) | ||
8284 | return NULL; | ||
7946 | strcpy(funcstring, s); | 8285 | strcpy(funcstring, s); |
7947 | funcstring += strlen(s) + 1; | 8286 | funcstring += strlen(s) + 1; |
7948 | return rtn; | 8287 | return rtn; |
@@ -7950,6 +8289,18 @@ nodeckstrdup(char *s) | |||
7950 | 8289 | ||
7951 | static union node *copynode(union node *); | 8290 | static union node *copynode(union node *); |
7952 | 8291 | ||
8292 | #if ENABLE_PLATFORM_MINGW32 | ||
8293 | # define SAVE_PTR(dst) {if (nodeptr) *nodeptr++ = (int)&(dst);} | ||
8294 | # define SAVE_PTR2(dst1,dst2) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);}} | ||
8295 | # define SAVE_PTR3(dst1,dst2,dst3) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);}} | ||
8296 | # define SAVE_PTR4(dst1,dst2,dst3,dst4) {if (nodeptr) { *nodeptr++ = (int)&(dst1);*nodeptr++ = (int)&(dst2);*nodeptr++ = (int)&(dst3);*nodeptr++ = (int)&(dst4);}} | ||
8297 | #else | ||
8298 | # define SAVE_PTR(dst) | ||
8299 | # define SAVE_PTR2(dst,dst2) | ||
8300 | # define SAVE_PTR3(dst,dst2,dst3) | ||
8301 | # define SAVE_PTR4(dst,dst2,dst3,dst4) | ||
8302 | #endif | ||
8303 | |||
7953 | static struct nodelist * | 8304 | static struct nodelist * |
7954 | copynodelist(struct nodelist *lp) | 8305 | copynodelist(struct nodelist *lp) |
7955 | { | 8306 | { |
@@ -7961,6 +8312,7 @@ copynodelist(struct nodelist *lp) | |||
7961 | *lpp = funcblock; | 8312 | *lpp = funcblock; |
7962 | funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); | 8313 | funcblock = (char *) funcblock + SHELL_ALIGN(sizeof(struct nodelist)); |
7963 | (*lpp)->n = copynode(lp->n); | 8314 | (*lpp)->n = copynode(lp->n); |
8315 | SAVE_PTR2((*lpp)->n, (*lpp)->next); | ||
7964 | lp = lp->next; | 8316 | lp = lp->next; |
7965 | lpp = &(*lpp)->next; | 8317 | lpp = &(*lpp)->next; |
7966 | } | 8318 | } |
@@ -7983,16 +8335,19 @@ copynode(union node *n) | |||
7983 | new->ncmd.redirect = copynode(n->ncmd.redirect); | 8335 | new->ncmd.redirect = copynode(n->ncmd.redirect); |
7984 | new->ncmd.args = copynode(n->ncmd.args); | 8336 | new->ncmd.args = copynode(n->ncmd.args); |
7985 | new->ncmd.assign = copynode(n->ncmd.assign); | 8337 | new->ncmd.assign = copynode(n->ncmd.assign); |
8338 | SAVE_PTR3(new->ncmd.redirect,new->ncmd.args, new->ncmd.assign); | ||
7986 | break; | 8339 | break; |
7987 | case NPIPE: | 8340 | case NPIPE: |
7988 | new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); | 8341 | new->npipe.cmdlist = copynodelist(n->npipe.cmdlist); |
7989 | new->npipe.pipe_backgnd = n->npipe.pipe_backgnd; | 8342 | new->npipe.pipe_backgnd = n->npipe.pipe_backgnd; |
8343 | SAVE_PTR(new->npipe.cmdlist); | ||
7990 | break; | 8344 | break; |
7991 | case NREDIR: | 8345 | case NREDIR: |
7992 | case NBACKGND: | 8346 | case NBACKGND: |
7993 | case NSUBSHELL: | 8347 | case NSUBSHELL: |
7994 | new->nredir.redirect = copynode(n->nredir.redirect); | 8348 | new->nredir.redirect = copynode(n->nredir.redirect); |
7995 | new->nredir.n = copynode(n->nredir.n); | 8349 | new->nredir.n = copynode(n->nredir.n); |
8350 | SAVE_PTR2(new->nredir.redirect,new->nredir.n); | ||
7996 | break; | 8351 | break; |
7997 | case NAND: | 8352 | case NAND: |
7998 | case NOR: | 8353 | case NOR: |
@@ -8001,31 +8356,37 @@ copynode(union node *n) | |||
8001 | case NUNTIL: | 8356 | case NUNTIL: |
8002 | new->nbinary.ch2 = copynode(n->nbinary.ch2); | 8357 | new->nbinary.ch2 = copynode(n->nbinary.ch2); |
8003 | new->nbinary.ch1 = copynode(n->nbinary.ch1); | 8358 | new->nbinary.ch1 = copynode(n->nbinary.ch1); |
8359 | SAVE_PTR2(new->nbinary.ch1,new->nbinary.ch2); | ||
8004 | break; | 8360 | break; |
8005 | case NIF: | 8361 | case NIF: |
8006 | new->nif.elsepart = copynode(n->nif.elsepart); | 8362 | new->nif.elsepart = copynode(n->nif.elsepart); |
8007 | new->nif.ifpart = copynode(n->nif.ifpart); | 8363 | new->nif.ifpart = copynode(n->nif.ifpart); |
8008 | new->nif.test = copynode(n->nif.test); | 8364 | new->nif.test = copynode(n->nif.test); |
8365 | SAVE_PTR3(new->nif.elsepart,new->nif.ifpart,new->nif.test); | ||
8009 | break; | 8366 | break; |
8010 | case NFOR: | 8367 | case NFOR: |
8011 | new->nfor.var = nodeckstrdup(n->nfor.var); | 8368 | new->nfor.var = nodeckstrdup(n->nfor.var); |
8012 | new->nfor.body = copynode(n->nfor.body); | 8369 | new->nfor.body = copynode(n->nfor.body); |
8013 | new->nfor.args = copynode(n->nfor.args); | 8370 | new->nfor.args = copynode(n->nfor.args); |
8371 | SAVE_PTR3(new->nfor.var,new->nfor.body,new->nfor.args); | ||
8014 | break; | 8372 | break; |
8015 | case NCASE: | 8373 | case NCASE: |
8016 | new->ncase.cases = copynode(n->ncase.cases); | 8374 | new->ncase.cases = copynode(n->ncase.cases); |
8017 | new->ncase.expr = copynode(n->ncase.expr); | 8375 | new->ncase.expr = copynode(n->ncase.expr); |
8376 | SAVE_PTR2(new->ncase.cases,new->ncase.expr); | ||
8018 | break; | 8377 | break; |
8019 | case NCLIST: | 8378 | case NCLIST: |
8020 | new->nclist.body = copynode(n->nclist.body); | 8379 | new->nclist.body = copynode(n->nclist.body); |
8021 | new->nclist.pattern = copynode(n->nclist.pattern); | 8380 | new->nclist.pattern = copynode(n->nclist.pattern); |
8022 | new->nclist.next = copynode(n->nclist.next); | 8381 | new->nclist.next = copynode(n->nclist.next); |
8382 | SAVE_PTR3(new->nclist.body,new->nclist.pattern,new->nclist.next); | ||
8023 | break; | 8383 | break; |
8024 | case NDEFUN: | 8384 | case NDEFUN: |
8025 | case NARG: | 8385 | case NARG: |
8026 | new->narg.backquote = copynodelist(n->narg.backquote); | 8386 | new->narg.backquote = copynodelist(n->narg.backquote); |
8027 | new->narg.text = nodeckstrdup(n->narg.text); | 8387 | new->narg.text = nodeckstrdup(n->narg.text); |
8028 | new->narg.next = copynode(n->narg.next); | 8388 | new->narg.next = copynode(n->narg.next); |
8389 | SAVE_PTR3(new->narg.backquote,new->narg.text,new->narg.next); | ||
8029 | break; | 8390 | break; |
8030 | case NTO: | 8391 | case NTO: |
8031 | #if ENABLE_ASH_BASH_COMPAT | 8392 | #if ENABLE_ASH_BASH_COMPAT |
@@ -8038,6 +8399,7 @@ copynode(union node *n) | |||
8038 | new->nfile.fname = copynode(n->nfile.fname); | 8399 | new->nfile.fname = copynode(n->nfile.fname); |
8039 | new->nfile.fd = n->nfile.fd; | 8400 | new->nfile.fd = n->nfile.fd; |
8040 | new->nfile.next = copynode(n->nfile.next); | 8401 | new->nfile.next = copynode(n->nfile.next); |
8402 | SAVE_PTR2(new->nfile.fname,new->nfile.next); | ||
8041 | break; | 8403 | break; |
8042 | case NTOFD: | 8404 | case NTOFD: |
8043 | case NFROMFD: | 8405 | case NFROMFD: |
@@ -8045,15 +8407,18 @@ copynode(union node *n) | |||
8045 | new->ndup.dupfd = n->ndup.dupfd; | 8407 | new->ndup.dupfd = n->ndup.dupfd; |
8046 | new->ndup.fd = n->ndup.fd; | 8408 | new->ndup.fd = n->ndup.fd; |
8047 | new->ndup.next = copynode(n->ndup.next); | 8409 | new->ndup.next = copynode(n->ndup.next); |
8410 | SAVE_PTR2(new->ndup.vname,new->ndup.next); | ||
8048 | break; | 8411 | break; |
8049 | case NHERE: | 8412 | case NHERE: |
8050 | case NXHERE: | 8413 | case NXHERE: |
8051 | new->nhere.doc = copynode(n->nhere.doc); | 8414 | new->nhere.doc = copynode(n->nhere.doc); |
8052 | new->nhere.fd = n->nhere.fd; | 8415 | new->nhere.fd = n->nhere.fd; |
8053 | new->nhere.next = copynode(n->nhere.next); | 8416 | new->nhere.next = copynode(n->nhere.next); |
8417 | SAVE_PTR2(new->nhere.doc,new->nhere.next); | ||
8054 | break; | 8418 | break; |
8055 | case NNOT: | 8419 | case NNOT: |
8056 | new->nnot.com = copynode(n->nnot.com); | 8420 | new->nnot.com = copynode(n->nnot.com); |
8421 | SAVE_PTR(new->nnot.com); | ||
8057 | break; | 8422 | break; |
8058 | }; | 8423 | }; |
8059 | new->type = n->type; | 8424 | new->type = n->type; |
@@ -8076,6 +8441,7 @@ copyfunc(union node *n) | |||
8076 | f = ckmalloc(blocksize + funcstringsize); | 8441 | f = ckmalloc(blocksize + funcstringsize); |
8077 | funcblock = (char *) f + offsetof(struct funcnode, n); | 8442 | funcblock = (char *) f + offsetof(struct funcnode, n); |
8078 | funcstring = (char *) f + blocksize; | 8443 | funcstring = (char *) f + blocksize; |
8444 | IF_PLATFORM_MINGW32(nodeptr = NULL); | ||
8079 | copynode(n); | 8445 | copynode(n); |
8080 | f->count = 0; | 8446 | f->count = 0; |
8081 | return f; | 8447 | return f; |
@@ -8428,9 +8794,26 @@ evalcase(union node *n, int flags) | |||
8428 | /* | 8794 | /* |
8429 | * Kick off a subshell to evaluate a tree. | 8795 | * Kick off a subshell to evaluate a tree. |
8430 | */ | 8796 | */ |
8797 | #if ENABLE_PLATFORM_MINGW32 | ||
8798 | static void | ||
8799 | forkshell_evalsubshell(struct forkshell *fs) | ||
8800 | { | ||
8801 | union node *n = fs->n; | ||
8802 | int flags = fs->flags; | ||
8803 | |||
8804 | TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); | ||
8805 | INT_ON; | ||
8806 | flags |= EV_EXIT; | ||
8807 | expredir(n->nredir.redirect); | ||
8808 | redirect(n->nredir.redirect, 0); | ||
8809 | evaltreenr(n->nredir.n, flags); | ||
8810 | /* never returns */ | ||
8811 | } | ||
8812 | #endif | ||
8431 | static void | 8813 | static void |
8432 | evalsubshell(union node *n, int flags) | 8814 | evalsubshell(union node *n, int flags) |
8433 | { | 8815 | { |
8816 | IF_PLATFORM_MINGW32(struct forkshell fs); | ||
8434 | struct job *jp; | 8817 | struct job *jp; |
8435 | int backgnd = (n->type == NBACKGND); | 8818 | int backgnd = (n->type == NBACKGND); |
8436 | int status; | 8819 | int status; |
@@ -8440,6 +8823,14 @@ evalsubshell(union node *n, int flags) | |||
8440 | goto nofork; | 8823 | goto nofork; |
8441 | INT_OFF; | 8824 | INT_OFF; |
8442 | jp = makejob(/*n,*/ 1); | 8825 | jp = makejob(/*n,*/ 1); |
8826 | #if ENABLE_PLATFORM_MINGW32 | ||
8827 | memset(&fs, 0, sizeof(fs)); | ||
8828 | fs.fp = forkshell_evalsubshell; | ||
8829 | fs.n = n; | ||
8830 | fs.flags = flags; | ||
8831 | if (spawn_forkshell(jp, &fs, backgnd) < 0) | ||
8832 | ash_msg_and_raise_error("unable to spawn shell"); | ||
8833 | #endif | ||
8443 | if (forkshell(jp, n, backgnd) == 0) { | 8834 | if (forkshell(jp, n, backgnd) == 0) { |
8444 | INT_ON; | 8835 | INT_ON; |
8445 | flags |= EV_EXIT; | 8836 | flags |= EV_EXIT; |
@@ -8515,9 +8906,35 @@ expredir(union node *n) | |||
8515 | * of the shell, which make the last process in a pipeline the parent | 8906 | * of the shell, which make the last process in a pipeline the parent |
8516 | * of all the rest.) | 8907 | * of all the rest.) |
8517 | */ | 8908 | */ |
8909 | #if ENABLE_PLATFORM_MINGW32 | ||
8910 | static void | ||
8911 | forkshell_evalpipe(struct forkshell *fs) | ||
8912 | { | ||
8913 | union node *n = fs->n; | ||
8914 | int flags = fs->flags; | ||
8915 | int prevfd = fs->fd[2]; | ||
8916 | int pip[2] = {fs->fd[0], fs->fd[1]}; | ||
8917 | |||
8918 | TRACE(("ash: subshell: %s\n",__PRETTY_FUNCTION__)); | ||
8919 | INT_ON; | ||
8920 | if (pip[1] >= 0) { | ||
8921 | close(pip[0]); | ||
8922 | } | ||
8923 | if (prevfd > 0) { | ||
8924 | dup2(prevfd, 0); | ||
8925 | close(prevfd); | ||
8926 | } | ||
8927 | if (pip[1] > 1) { | ||
8928 | dup2(pip[1], 1); | ||
8929 | close(pip[1]); | ||
8930 | } | ||
8931 | evaltreenr(n, flags); | ||
8932 | } | ||
8933 | #endif | ||
8518 | static void | 8934 | static void |
8519 | evalpipe(union node *n, int flags) | 8935 | evalpipe(union node *n, int flags) |
8520 | { | 8936 | { |
8937 | IF_PLATFORM_MINGW32(struct forkshell fs); | ||
8521 | struct job *jp; | 8938 | struct job *jp; |
8522 | struct nodelist *lp; | 8939 | struct nodelist *lp; |
8523 | int pipelen; | 8940 | int pipelen; |
@@ -8541,6 +8958,17 @@ evalpipe(union node *n, int flags) | |||
8541 | ash_msg_and_raise_error("pipe call failed"); | 8958 | ash_msg_and_raise_error("pipe call failed"); |
8542 | } | 8959 | } |
8543 | } | 8960 | } |
8961 | #if ENABLE_PLATFORM_MINGW32 | ||
8962 | memset(&fs, 0, sizeof(fs)); | ||
8963 | fs.fp = forkshell_evalpipe; | ||
8964 | fs.flags = flags; | ||
8965 | fs.n = lp->n; | ||
8966 | fs.fd[0] = pip[0]; | ||
8967 | fs.fd[1] = pip[1]; | ||
8968 | fs.fd[2] = prevfd; | ||
8969 | if (spawn_forkshell(jp, &fs, n->npipe.pipe_backgnd) < 0) | ||
8970 | ash_msg_and_raise_error("unable to spawn shell"); | ||
8971 | #endif | ||
8544 | if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { | 8972 | if (forkshell(jp, lp->n, n->npipe.pipe_backgnd) == 0) { |
8545 | INT_ON; | 8973 | INT_ON; |
8546 | if (pip[1] >= 0) { | 8974 | if (pip[1] >= 0) { |
@@ -9007,6 +9435,20 @@ bltincmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
9007 | * as POSIX mandates */ | 9435 | * as POSIX mandates */ |
9008 | return back_exitstatus; | 9436 | return back_exitstatus; |
9009 | } | 9437 | } |
9438 | |||
9439 | #if ENABLE_PLATFORM_MINGW32 | ||
9440 | static void | ||
9441 | forkshell_shellexec(struct forkshell *fs) | ||
9442 | { | ||
9443 | int idx = fs->fd[0]; | ||
9444 | struct strlist *varlist = fs->strlist; | ||
9445 | char **argv = fs->argv; | ||
9446 | char *path = fs->string; | ||
9447 | |||
9448 | listsetvar(varlist, VEXPORT|VSTACK); | ||
9449 | shellexec(argv, path, idx); | ||
9450 | } | ||
9451 | #endif | ||
9010 | static void | 9452 | static void |
9011 | evalcommand(union node *cmd, int flags) | 9453 | evalcommand(union node *cmd, int flags) |
9012 | { | 9454 | { |
@@ -9183,6 +9625,26 @@ evalcommand(union node *cmd, int flags) | |||
9183 | } | 9625 | } |
9184 | } | 9626 | } |
9185 | #endif | 9627 | #endif |
9628 | #if ENABLE_PLATFORM_MINGW32 | ||
9629 | if (!(flags & EV_EXIT) || trap[0]) { | ||
9630 | struct forkshell fs; | ||
9631 | |||
9632 | memset(&fs, 0, sizeof(fs)); | ||
9633 | fs.fp = forkshell_shellexec; | ||
9634 | fs.argv = argv; | ||
9635 | fs.string = (char*)path; | ||
9636 | fs.fd[0] = cmdentry.u.index; | ||
9637 | fs.strlist = varlist.list; | ||
9638 | jp = makejob(/*cmd,*/ 1); | ||
9639 | if (spawn_forkshell(jp, &fs, FORK_FG) < 0) | ||
9640 | ash_msg_and_raise_error("unable to spawn shell"); | ||
9641 | exitstatus = waitforjob(jp); | ||
9642 | INT_ON; | ||
9643 | TRACE(("forked child exited with %d\n", exitstatus)); | ||
9644 | break; | ||
9645 | } | ||
9646 | /* goes through to shellexec() */ | ||
9647 | #endif | ||
9186 | /* Fork off a child process if necessary. */ | 9648 | /* Fork off a child process if necessary. */ |
9187 | if (!(flags & EV_EXIT) || trap[0]) { | 9649 | if (!(flags & EV_EXIT) || trap[0]) { |
9188 | INT_OFF; | 9650 | INT_OFF; |
@@ -9563,7 +10025,7 @@ preadbuffer(void) | |||
9563 | more--; | 10025 | more--; |
9564 | 10026 | ||
9565 | c = *q; | 10027 | c = *q; |
9566 | if (c == '\0') { | 10028 | if (c == '\0' || (ENABLE_PLATFORM_MINGW32 && c == '\r')) { |
9567 | memmove(q, q + 1, more); | 10029 | memmove(q, q + 1, more); |
9568 | } else { | 10030 | } else { |
9569 | q++; | 10031 | q++; |
@@ -11990,7 +12452,7 @@ find_dot_file(char *name) | |||
11990 | struct stat statb; | 12452 | struct stat statb; |
11991 | 12453 | ||
11992 | /* don't try this for absolute or relative paths */ | 12454 | /* don't try this for absolute or relative paths */ |
11993 | if (strchr(name, '/')) | 12455 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) |
11994 | return name; | 12456 | return name; |
11995 | 12457 | ||
11996 | /* IIRC standards do not say whether . is to be searched. | 12458 | /* IIRC standards do not say whether . is to be searched. |
@@ -12093,10 +12555,11 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
12093 | struct stat statb; | 12555 | struct stat statb; |
12094 | int e; | 12556 | int e; |
12095 | int updatetbl; | 12557 | int updatetbl; |
12558 | IF_PLATFORM_MINGW32(int len); | ||
12096 | struct builtincmd *bcmd; | 12559 | struct builtincmd *bcmd; |
12097 | 12560 | ||
12098 | /* If name contains a slash, don't use PATH or hash table */ | 12561 | /* If name contains a slash, don't use PATH or hash table */ |
12099 | if (strchr(name, '/') != NULL) { | 12562 | if (strchr(name, '/') || (ENABLE_PLATFORM_MINGW32 && strchr(name, '\\'))) { |
12100 | entry->u.index = -1; | 12563 | entry->u.index = -1; |
12101 | if (act & DO_ABS) { | 12564 | if (act & DO_ABS) { |
12102 | while (stat(name, &statb) < 0) { | 12565 | while (stat(name, &statb) < 0) { |
@@ -12203,12 +12666,39 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
12203 | } | 12666 | } |
12204 | } | 12667 | } |
12205 | /* if rehash, don't redo absolute path names */ | 12668 | /* if rehash, don't redo absolute path names */ |
12206 | if (fullname[0] == '/' && idx <= prev) { | 12669 | if (is_absolute_path(fullname) && idx <= prev) { |
12207 | if (idx < prev) | 12670 | if (idx < prev) |
12208 | continue; | 12671 | continue; |
12209 | TRACE(("searchexec \"%s\": no change\n", name)); | 12672 | TRACE(("searchexec \"%s\": no change\n", name)); |
12210 | goto success; | 12673 | goto success; |
12211 | } | 12674 | } |
12675 | #if ENABLE_PLATFORM_MINGW32 | ||
12676 | len = strlen(fullname); | ||
12677 | if (len > 4 && | ||
12678 | (!strcasecmp(fullname+len-4, ".exe") || | ||
12679 | !strcasecmp(fullname+len-4, ".com"))) { | ||
12680 | if (stat(fullname, &statb) < 0) { | ||
12681 | if (errno != ENOENT && errno != ENOTDIR) | ||
12682 | e = errno; | ||
12683 | goto loop; | ||
12684 | } | ||
12685 | } | ||
12686 | else { | ||
12687 | /* path_advance() has reserved space for .exe */ | ||
12688 | memcpy(fullname+len, ".exe", 5); | ||
12689 | if (stat(fullname, &statb) < 0) { | ||
12690 | if (errno != ENOENT && errno != ENOTDIR) | ||
12691 | e = errno; | ||
12692 | memcpy(fullname+len, ".com", 5); | ||
12693 | if (stat(fullname, &statb) < 0) { | ||
12694 | if (errno != ENOENT && errno != ENOTDIR) | ||
12695 | e = errno; | ||
12696 | goto loop; | ||
12697 | } | ||
12698 | } | ||
12699 | fullname[len] = '\0'; | ||
12700 | } | ||
12701 | #else | ||
12212 | while (stat(fullname, &statb) < 0) { | 12702 | while (stat(fullname, &statb) < 0) { |
12213 | #ifdef SYSV | 12703 | #ifdef SYSV |
12214 | if (errno == EINTR) | 12704 | if (errno == EINTR) |
@@ -12218,6 +12708,7 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path) | |||
12218 | e = errno; | 12708 | e = errno; |
12219 | goto loop; | 12709 | goto loop; |
12220 | } | 12710 | } |
12711 | #endif | ||
12221 | e = EACCES; /* if we fail, this will be the error */ | 12712 | e = EACCES; /* if we fail, this will be the error */ |
12222 | if (!S_ISREG(statb.st_mode)) | 12713 | if (!S_ISREG(statb.st_mode)) |
12223 | continue; | 12714 | continue; |
@@ -12744,13 +13235,41 @@ init(void) | |||
12744 | struct stat st1, st2; | 13235 | struct stat st1, st2; |
12745 | 13236 | ||
12746 | initvar(); | 13237 | initvar(); |
13238 | |||
13239 | #if ENABLE_PLATFORM_MINGW32 | ||
13240 | /* | ||
13241 | * case insensitive env names from Windows world | ||
13242 | * | ||
13243 | * Some standard env names such as PATH is named Path and so on | ||
13244 | * ash itself is case sensitive, so "Path" will confuse it, as | ||
13245 | * MSVC getenv() is case insensitive. | ||
13246 | * | ||
13247 | * We may end up having both Path and PATH. Then Path will be chosen | ||
13248 | * because it appears first. | ||
13249 | */ | ||
13250 | for (envp = environ; envp && *envp; envp++) | ||
13251 | if (!strncasecmp(*envp, "PATH=", 5) && | ||
13252 | strncmp(*envp, "PATH=", 5)) | ||
13253 | break; | ||
13254 | if (envp && *envp) { | ||
13255 | char *start, *end; | ||
13256 | for (envp = environ; envp && *envp; envp++) { | ||
13257 | end = strchr(*envp, '='); | ||
13258 | if (!end) | ||
13259 | continue; | ||
13260 | for (start = *envp;start < end;start++) | ||
13261 | *start = toupper(*start); | ||
13262 | } | ||
13263 | } | ||
13264 | #endif | ||
12747 | for (envp = environ; envp && *envp; envp++) { | 13265 | for (envp = environ; envp && *envp; envp++) { |
12748 | if (strchr(*envp, '=')) { | 13266 | if (strchr(*envp, '=')) { |
12749 | setvareq(*envp, VEXPORT|VTEXTFIXED); | 13267 | setvareq(*envp, VEXPORT|VTEXTFIXED); |
12750 | } | 13268 | } |
12751 | } | 13269 | } |
12752 | 13270 | ||
12753 | setvar("PPID", utoa(getppid()), 0); | 13271 | if (!ENABLE_PLATFORM_MINGW32) |
13272 | setvar("PPID", utoa(getppid()), 0); | ||
12754 | 13273 | ||
12755 | p = lookupvar("PWD"); | 13274 | p = lookupvar("PWD"); |
12756 | if (p) | 13275 | if (p) |
@@ -12866,6 +13385,20 @@ static short profile_buf[16384]; | |||
12866 | extern int etext(); | 13385 | extern int etext(); |
12867 | #endif | 13386 | #endif |
12868 | 13387 | ||
13388 | #if ENABLE_PLATFORM_MINGW32 | ||
13389 | static const forkpoint_fn forkpoints[] = { | ||
13390 | forkshell_openhere, | ||
13391 | forkshell_evalbackcmd, | ||
13392 | forkshell_evalsubshell, | ||
13393 | forkshell_evalpipe, | ||
13394 | forkshell_shellexec, | ||
13395 | NULL | ||
13396 | }; | ||
13397 | |||
13398 | static struct forkshell* forkshell_prepare(struct forkshell *fs); | ||
13399 | static void forkshell_init(const char *idstr); | ||
13400 | #endif | ||
13401 | |||
12869 | /* | 13402 | /* |
12870 | * Main routine. We initialize things, parse the arguments, execute | 13403 | * Main routine. We initialize things, parse the arguments, execute |
12871 | * profiles if we're a login shell, and then call cmdloop to execute | 13404 | * profiles if we're a login shell, and then call cmdloop to execute |
@@ -12933,6 +13466,15 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
12933 | 13466 | ||
12934 | init(); | 13467 | init(); |
12935 | setstackmark(&smark); | 13468 | setstackmark(&smark); |
13469 | |||
13470 | #if ENABLE_PLATFORM_MINGW32 | ||
13471 | if (argc == 3 && !strcmp(argv[1], "--forkshell")) { | ||
13472 | forkshell_init(argv[2]); | ||
13473 | |||
13474 | /* NOTREACHED */ | ||
13475 | bb_error_msg_and_die("subshell ended unexpectedly"); | ||
13476 | } | ||
13477 | #endif | ||
12936 | procargs(argv); | 13478 | procargs(argv); |
12937 | 13479 | ||
12938 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY | 13480 | #if ENABLE_FEATURE_EDITING_SAVEHISTORY |
@@ -13007,6 +13549,524 @@ int ash_main(int argc UNUSED_PARAM, char **argv) | |||
13007 | /* NOTREACHED */ | 13549 | /* NOTREACHED */ |
13008 | } | 13550 | } |
13009 | 13551 | ||
13552 | /* FIXME: should consider running forkparent() and forkchild() */ | ||
13553 | static int | ||
13554 | spawn_forkshell(struct job *jp, struct forkshell *fs, int mode) | ||
13555 | { | ||
13556 | const char *argv[] = { "sh", "--forkshell", NULL, NULL }; | ||
13557 | char buf[16]; | ||
13558 | |||
13559 | struct forkshell *new; | ||
13560 | new = forkshell_prepare(fs); | ||
13561 | sprintf(buf, "%x", (unsigned int)new->hMapFile); | ||
13562 | argv[2] = buf; | ||
13563 | fs->pid = mingw_spawn_applet(P_NOWAIT, "sh", argv, | ||
13564 | (const char *const *)environ); | ||
13565 | CloseHandle(new->hMapFile); | ||
13566 | UnmapViewOfFile(new); | ||
13567 | if (fs->pid == -1) { | ||
13568 | free(jp); | ||
13569 | return -1; | ||
13570 | } | ||
13571 | forkparent(jp, fs->node, mode, fs->pid); | ||
13572 | return fs->pid; | ||
13573 | } | ||
13574 | |||
13575 | /* | ||
13576 | * forkshell_prepare() and friends | ||
13577 | * | ||
13578 | * The sequence is as follows: | ||
13579 | * - funcblocksize, funcstringsize, nodeptrsize are initialized | ||
13580 | * - forkshell_size(fs) is called to calculate the exact memory needed | ||
13581 | * - a new struct is allocated | ||
13582 | * - funcblock, funcstring, nodeptr are initialized from the new block | ||
13583 | * - forkshell_copy(fs) is called to copy recursively everything over | ||
13584 | * it will record all pointers along the way, to nodeptr | ||
13585 | * | ||
13586 | * When this memory is mapped elsewhere, pointer fixup will be needed | ||
13587 | */ | ||
13588 | #define SLIST_SIZE_BEGIN(name,type) \ | ||
13589 | static void \ | ||
13590 | name(type *p) \ | ||
13591 | { \ | ||
13592 | while (p) { \ | ||
13593 | funcblocksize += sizeof(type); | ||
13594 | /* do something here with p */ | ||
13595 | #define SLIST_SIZE_END() \ | ||
13596 | nodeptrsize++; \ | ||
13597 | p = p->next; \ | ||
13598 | } \ | ||
13599 | } | ||
13600 | |||
13601 | #define SLIST_COPY_BEGIN(name,type) \ | ||
13602 | static type * \ | ||
13603 | name(type *vp) \ | ||
13604 | { \ | ||
13605 | type *start; \ | ||
13606 | type **vpp; \ | ||
13607 | vpp = &start; \ | ||
13608 | while (vp) { \ | ||
13609 | *vpp = funcblock; \ | ||
13610 | funcblock = (char *) funcblock + sizeof(type); | ||
13611 | /* do something here with vpp and vp */ | ||
13612 | #define SLIST_COPY_END() \ | ||
13613 | SAVE_PTR((*vpp)->next); \ | ||
13614 | vp = vp->next; \ | ||
13615 | vpp = &(*vpp)->next; \ | ||
13616 | } \ | ||
13617 | *vpp = NULL; \ | ||
13618 | return start; \ | ||
13619 | } | ||
13620 | |||
13621 | /* | ||
13622 | * struct var | ||
13623 | */ | ||
13624 | SLIST_SIZE_BEGIN(var_size,struct var) | ||
13625 | funcstringsize += strlen(p->text) + 1; | ||
13626 | nodeptrsize++; /* p->text */ | ||
13627 | SLIST_SIZE_END() | ||
13628 | |||
13629 | SLIST_COPY_BEGIN(var_copy,struct var) | ||
13630 | (*vpp)->text = nodeckstrdup(vp->text); | ||
13631 | (*vpp)->flags = vp->flags; | ||
13632 | /* | ||
13633 | * The only place that can set struct var#func is varinit[], | ||
13634 | * which will be fixed by forkshell_init() | ||
13635 | */ | ||
13636 | (*vpp)->func = NULL; | ||
13637 | SAVE_PTR((*vpp)->text); | ||
13638 | SLIST_COPY_END() | ||
13639 | |||
13640 | /* | ||
13641 | * struct localvar | ||
13642 | */ | ||
13643 | SLIST_SIZE_BEGIN(localvar_size,struct localvar) | ||
13644 | var_size(p->vp); | ||
13645 | funcstringsize += strlen(p->text) + 1; | ||
13646 | nodeptrsize += 2; /* p->vp, p->text */ | ||
13647 | SLIST_SIZE_END() | ||
13648 | |||
13649 | SLIST_COPY_BEGIN(localvar_copy,struct localvar) | ||
13650 | (*vpp)->text = nodeckstrdup(vp->text); | ||
13651 | (*vpp)->flags = vp->flags; | ||
13652 | (*vpp)->vp = var_copy(vp->vp); | ||
13653 | SAVE_PTR2((*vpp)->vp, (*vpp)->text); | ||
13654 | SLIST_COPY_END() | ||
13655 | |||
13656 | /* | ||
13657 | * struct strlist | ||
13658 | */ | ||
13659 | SLIST_SIZE_BEGIN(strlist_size,struct strlist) | ||
13660 | funcstringsize += strlen(p->text) + 1; | ||
13661 | nodeptrsize++; /* p->text */ | ||
13662 | SLIST_SIZE_END() | ||
13663 | |||
13664 | SLIST_COPY_BEGIN(strlist_copy,struct strlist) | ||
13665 | (*vpp)->text = nodeckstrdup(vp->text); | ||
13666 | SAVE_PTR((*vpp)->text); | ||
13667 | SLIST_COPY_END() | ||
13668 | |||
13669 | /* | ||
13670 | * struct tblentry | ||
13671 | */ | ||
13672 | static void | ||
13673 | tblentry_size(struct tblentry *tep) | ||
13674 | { | ||
13675 | while (tep) { | ||
13676 | funcblocksize += sizeof(struct tblentry) + strlen(tep->cmdname) + 1; | ||
13677 | /* CMDBUILTIN, e->param.cmd needs no pointer relocation */ | ||
13678 | if (tep->cmdtype == CMDFUNCTION) { | ||
13679 | funcblocksize += offsetof(struct funcnode, n); | ||
13680 | calcsize(&tep->param.func->n); | ||
13681 | nodeptrsize++; /* tep->param.func */ | ||
13682 | } | ||
13683 | nodeptrsize++; /* tep->next */ | ||
13684 | tep = tep->next; | ||
13685 | } | ||
13686 | } | ||
13687 | |||
13688 | static struct tblentry * | ||
13689 | tblentry_copy(struct tblentry *tep) | ||
13690 | { | ||
13691 | struct tblentry *start; | ||
13692 | struct tblentry **newp; | ||
13693 | int size; | ||
13694 | |||
13695 | newp = &start; | ||
13696 | while (tep) { | ||
13697 | *newp = funcblock; | ||
13698 | size = sizeof(struct tblentry) + strlen(tep->cmdname) + 1; | ||
13699 | |||
13700 | funcblock = (char *) funcblock + size; | ||
13701 | memcpy(*newp, tep, size); | ||
13702 | switch (tep->cmdtype) { | ||
13703 | case CMDBUILTIN: | ||
13704 | /* No pointer saving, this field must be fixed by forkshell_init() */ | ||
13705 | (*newp)->param.cmd = (const struct builtincmd *)(tep->param.cmd - builtintab); | ||
13706 | break; | ||
13707 | case CMDFUNCTION: | ||
13708 | (*newp)->param.func = funcblock; | ||
13709 | funcblock = (char *) funcblock + offsetof(struct funcnode, n); | ||
13710 | copynode(&tep->param.func->n); | ||
13711 | SAVE_PTR((*newp)->param.func); | ||
13712 | break; | ||
13713 | default: | ||
13714 | break; | ||
13715 | } | ||
13716 | SAVE_PTR((*newp)->next); | ||
13717 | tep = tep->next; | ||
13718 | newp = &(*newp)->next; | ||
13719 | } | ||
13720 | *newp = NULL; | ||
13721 | return start; | ||
13722 | } | ||
13723 | |||
13724 | static void | ||
13725 | cmdtable_size(struct tblentry **cmdtablep) | ||
13726 | { | ||
13727 | int i; | ||
13728 | nodeptrsize += CMDTABLESIZE; | ||
13729 | funcblocksize += sizeof(struct tblentry *)*CMDTABLESIZE; | ||
13730 | for (i = 0; i < CMDTABLESIZE; i++) | ||
13731 | tblentry_size(cmdtablep[i]); | ||
13732 | } | ||
13733 | |||
13734 | static struct tblentry ** | ||
13735 | cmdtable_copy(struct tblentry **cmdtablep) | ||
13736 | { | ||
13737 | struct tblentry **new = funcblock; | ||
13738 | int i; | ||
13739 | |||
13740 | funcblock = (char *) funcblock + sizeof(struct tblentry *)*CMDTABLESIZE; | ||
13741 | for (i = 0; i < CMDTABLESIZE; i++) { | ||
13742 | new[i] = tblentry_copy(cmdtablep[i]); | ||
13743 | SAVE_PTR(new[i]); | ||
13744 | } | ||
13745 | return new; | ||
13746 | } | ||
13747 | |||
13748 | /* | ||
13749 | * char ** | ||
13750 | */ | ||
13751 | static void | ||
13752 | argv_size(char **p) | ||
13753 | { | ||
13754 | while (p && *p) { | ||
13755 | funcblocksize += sizeof(char *); | ||
13756 | funcstringsize += strlen(*p)+1; | ||
13757 | nodeptrsize++; | ||
13758 | p++; | ||
13759 | } | ||
13760 | funcblocksize += sizeof(char *); | ||
13761 | } | ||
13762 | |||
13763 | static char ** | ||
13764 | argv_copy(char **p) | ||
13765 | { | ||
13766 | char **new, **start = funcblock; | ||
13767 | |||
13768 | while (p && *p) { | ||
13769 | new = funcblock; | ||
13770 | funcblock = (char *) funcblock + sizeof(char *); | ||
13771 | *new = nodeckstrdup(*p); | ||
13772 | SAVE_PTR(*new); | ||
13773 | p++; | ||
13774 | new++; | ||
13775 | } | ||
13776 | new = funcblock; | ||
13777 | funcblock = (char *) funcblock + sizeof(char *); | ||
13778 | *new = NULL; | ||
13779 | return start; | ||
13780 | } | ||
13781 | |||
13782 | /* | ||
13783 | * struct redirtab | ||
13784 | */ | ||
13785 | static void | ||
13786 | redirtab_size(struct redirtab *rdtp) | ||
13787 | { | ||
13788 | while (rdtp) { | ||
13789 | funcblocksize += sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count; | ||
13790 | rdtp = rdtp->next; | ||
13791 | nodeptrsize++; /* rdtp->next */ | ||
13792 | } | ||
13793 | } | ||
13794 | |||
13795 | static struct redirtab * | ||
13796 | redirtab_copy(struct redirtab *rdtp) | ||
13797 | { | ||
13798 | struct redirtab *start; | ||
13799 | struct redirtab **vpp; | ||
13800 | |||
13801 | vpp = &start; | ||
13802 | while (rdtp) { | ||
13803 | int size = sizeof(*rdtp)+sizeof(rdtp->two_fd[0])*rdtp->pair_count; | ||
13804 | *vpp = funcblock; | ||
13805 | funcblock = (char *) funcblock + size; | ||
13806 | memcpy(*vpp, rdtp, size); | ||
13807 | SAVE_PTR((*vpp)->next); | ||
13808 | rdtp = rdtp->next; | ||
13809 | vpp = &(*vpp)->next; | ||
13810 | } | ||
13811 | *vpp = NULL; | ||
13812 | return start; | ||
13813 | } | ||
13814 | |||
13815 | #undef shellparam | ||
13816 | #undef redirlist | ||
13817 | #undef varinit | ||
13818 | #undef vartab | ||
13819 | static void | ||
13820 | globals_var_size(struct globals_var *gvp) | ||
13821 | { | ||
13822 | int i; | ||
13823 | |||
13824 | funcblocksize += sizeof(struct globals_var); | ||
13825 | argv_size(gvp->shellparam.p); | ||
13826 | redirtab_size(gvp->redirlist); | ||
13827 | for (i = 0; i < VTABSIZE; i++) | ||
13828 | var_size(gvp->vartab[i]); | ||
13829 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) | ||
13830 | var_size(gvp->varinit+i); | ||
13831 | nodeptrsize += 2 + VTABSIZE; /* gvp->redirlist, gvp->shellparam.p, vartab */ | ||
13832 | } | ||
13833 | |||
13834 | #undef g_nullredirs | ||
13835 | #undef preverrout_fd | ||
13836 | static struct globals_var * | ||
13837 | globals_var_copy(struct globals_var *gvp) | ||
13838 | { | ||
13839 | int i; | ||
13840 | struct globals_var *new; | ||
13841 | |||
13842 | new = funcblock; | ||
13843 | funcblock = (char *) funcblock + sizeof(struct globals_var); | ||
13844 | |||
13845 | /* shparam */ | ||
13846 | memcpy(&new->shellparam, &gvp->shellparam, sizeof(struct shparam)); | ||
13847 | new->shellparam.malloced = 0; | ||
13848 | new->shellparam.p = argv_copy(gvp->shellparam.p); | ||
13849 | SAVE_PTR(new->shellparam.p); | ||
13850 | |||
13851 | new->redirlist = redirtab_copy(gvp->redirlist); | ||
13852 | SAVE_PTR(new->redirlist); | ||
13853 | |||
13854 | new->g_nullredirs = gvp->g_nullredirs; | ||
13855 | new->preverrout_fd = gvp->preverrout_fd; | ||
13856 | for (i = 0; i < VTABSIZE; i++) { | ||
13857 | new->vartab[i] = var_copy(gvp->vartab[i]); | ||
13858 | SAVE_PTR(new->vartab[i]); | ||
13859 | } | ||
13860 | |||
13861 | /* Can't use var_copy because varinit is already allocated */ | ||
13862 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { | ||
13863 | new->varinit[i].next = NULL; | ||
13864 | new->varinit[i].text = nodeckstrdup(gvp->varinit[i].text); | ||
13865 | SAVE_PTR(new->varinit[i].text); | ||
13866 | new->varinit[i].flags = gvp->varinit[i].flags; | ||
13867 | new->varinit[i].func = gvp->varinit[i].func; | ||
13868 | } | ||
13869 | return new; | ||
13870 | } | ||
13871 | |||
13872 | #undef minusc | ||
13873 | #undef curdir | ||
13874 | #undef physdir | ||
13875 | #undef arg0 | ||
13876 | #undef nullstr | ||
13877 | static void | ||
13878 | globals_misc_size(struct globals_misc *p) | ||
13879 | { | ||
13880 | funcblocksize += sizeof(struct globals_misc); | ||
13881 | funcstringsize += p->minusc ? strlen(p->minusc) + 1 : 1; | ||
13882 | if (p->curdir != p->nullstr) | ||
13883 | funcstringsize += strlen(p->curdir) + 1; | ||
13884 | if (p->physdir != p->nullstr) | ||
13885 | funcstringsize += strlen(p->physdir) + 1; | ||
13886 | funcstringsize += strlen(p->arg0) + 1; | ||
13887 | nodeptrsize += 4; /* minusc, curdir, physdir, arg0 */ | ||
13888 | } | ||
13889 | |||
13890 | static struct globals_misc * | ||
13891 | globals_misc_copy(struct globals_misc *p) | ||
13892 | { | ||
13893 | struct globals_misc *new = funcblock; | ||
13894 | |||
13895 | funcblock = (char *) funcblock + sizeof(struct globals_misc); | ||
13896 | memcpy(new, p, sizeof(struct globals_misc)); | ||
13897 | |||
13898 | new->minusc = nodeckstrdup(p->minusc); | ||
13899 | new->curdir = p->curdir != p->nullstr ? nodeckstrdup(p->curdir) : new->nullstr; | ||
13900 | new->physdir = p->physdir != p->nullstr ? nodeckstrdup(p->physdir) : new->nullstr; | ||
13901 | new->arg0 = nodeckstrdup(p->arg0); | ||
13902 | SAVE_PTR4(new->minusc, new->curdir, new->physdir, new->arg0); | ||
13903 | return new; | ||
13904 | } | ||
13905 | |||
13906 | static void | ||
13907 | forkshell_size(struct forkshell *fs) | ||
13908 | { | ||
13909 | funcblocksize += sizeof(struct forkshell); | ||
13910 | globals_var_size(fs->gvp); | ||
13911 | globals_misc_size(fs->gmp); | ||
13912 | cmdtable_size(fs->cmdtable); | ||
13913 | localvar_size(fs->localvars); | ||
13914 | /* optlist_transfer(sending, fd); */ | ||
13915 | /* misc_transfer(sending, fd); */ | ||
13916 | |||
13917 | calcsize(fs->n); | ||
13918 | argv_size(fs->argv); | ||
13919 | funcstringsize += (fs->string ? strlen(fs->string) : 0) + 1; | ||
13920 | strlist_size(fs->strlist); | ||
13921 | |||
13922 | nodeptrsize += 8; /* gvp, gmp, cmdtable, localvars, n, argv, string, strlist */ | ||
13923 | } | ||
13924 | |||
13925 | static struct forkshell * | ||
13926 | forkshell_copy(struct forkshell *fs) | ||
13927 | { | ||
13928 | struct forkshell *new; | ||
13929 | |||
13930 | new = funcblock; | ||
13931 | funcblock = (char *) funcblock + sizeof(struct forkshell); | ||
13932 | |||
13933 | memcpy(new, fs, sizeof(struct forkshell)); /* non-pointer stuff */ | ||
13934 | new->gvp = globals_var_copy(fs->gvp); | ||
13935 | new->gmp = globals_misc_copy(fs->gmp); | ||
13936 | new->cmdtable = cmdtable_copy(fs->cmdtable); | ||
13937 | new->localvars = localvar_copy(fs->localvars); | ||
13938 | SAVE_PTR4(new->gvp, new->gmp, new->cmdtable, new->localvars); | ||
13939 | |||
13940 | /* new->fs will be reconstructed from new->fpid */ | ||
13941 | new->n = copynode(fs->n); | ||
13942 | new->argv = argv_copy(fs->argv); | ||
13943 | new->string = nodeckstrdup(fs->string); | ||
13944 | new->strlist = strlist_copy(fs->strlist); | ||
13945 | SAVE_PTR4(new->n, new->argv, new->string, new->strlist); | ||
13946 | return new; | ||
13947 | } | ||
13948 | |||
13949 | static struct forkshell * | ||
13950 | forkshell_prepare(struct forkshell *fs) | ||
13951 | { | ||
13952 | struct forkshell *new; | ||
13953 | int size, fp, nodeptr_offset; | ||
13954 | HANDLE h; | ||
13955 | SECURITY_ATTRIBUTES sa; | ||
13956 | |||
13957 | for (fp = 0; forkpoints[fp] && forkpoints[fp] != fs->fp; fp++) | ||
13958 | ; | ||
13959 | |||
13960 | if (!forkpoints[fp]) | ||
13961 | bb_error_msg_and_die("invalid forkpoint %08x", (int)fs->fp); | ||
13962 | fs->fpid = fp; | ||
13963 | |||
13964 | /* Calculate size of "new" */ | ||
13965 | fs->gvp = ash_ptr_to_globals_var; | ||
13966 | fs->gmp = ash_ptr_to_globals_misc; | ||
13967 | fs->cmdtable = cmdtable; | ||
13968 | fs->localvars = localvars; | ||
13969 | |||
13970 | nodeptrsize = 1; /* NULL terminated */ | ||
13971 | funcblocksize = 0; | ||
13972 | funcstringsize = 0; | ||
13973 | forkshell_size(fs); | ||
13974 | size = funcblocksize + funcstringsize + nodeptrsize*sizeof(int); | ||
13975 | |||
13976 | /* Allocate, initialize pointers */ | ||
13977 | memset(&sa, 0, sizeof(sa)); | ||
13978 | sa.nLength = sizeof(sa); | ||
13979 | sa.lpSecurityDescriptor = NULL; | ||
13980 | sa.bInheritHandle = TRUE; | ||
13981 | h = CreateFileMapping(INVALID_HANDLE_VALUE, &sa, PAGE_READWRITE, 0, size, NULL); | ||
13982 | new = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0); | ||
13983 | /* new = ckmalloc(size); */ | ||
13984 | funcblock = new; | ||
13985 | funcstring = (char *) funcblock + funcblocksize; | ||
13986 | nodeptr = (int*)((char *) funcstring + funcstringsize); | ||
13987 | nodeptr_offset = (int) nodeptr - (int) new; | ||
13988 | |||
13989 | /* Now pack them all */ | ||
13990 | forkshell_copy(fs); | ||
13991 | |||
13992 | /* Finish it up */ | ||
13993 | *nodeptr = 0; | ||
13994 | new->size = size; | ||
13995 | new->nodeptr_offset = nodeptr_offset; | ||
13996 | new->old_base = new; | ||
13997 | new->hMapFile = h; | ||
13998 | return new; | ||
13999 | } | ||
14000 | |||
14001 | #undef exception_handler | ||
14002 | #undef trap | ||
14003 | #undef trap_ptr | ||
14004 | static void *sticky_mem_start, *sticky_mem_end; | ||
14005 | static void | ||
14006 | forkshell_init(const char *idstr) | ||
14007 | { | ||
14008 | struct forkshell *fs; | ||
14009 | int map_handle; | ||
14010 | HANDLE h; | ||
14011 | struct globals_var **gvpp; | ||
14012 | struct globals_misc **gmpp; | ||
14013 | int i; | ||
14014 | |||
14015 | if (sscanf(idstr, "%x", &map_handle) != 1) | ||
14016 | bb_error_msg_and_die("invalid forkshell ID"); | ||
14017 | |||
14018 | h = (HANDLE)map_handle; | ||
14019 | fs = (struct forkshell *)MapViewOfFile(h, FILE_MAP_WRITE, 0,0, 0); | ||
14020 | if (!fs) | ||
14021 | bb_error_msg_and_die("Invalid forkshell memory"); | ||
14022 | |||
14023 | /* this memory can't be freed */ | ||
14024 | sticky_mem_start = fs; | ||
14025 | sticky_mem_end = (char *) fs + fs->size; | ||
14026 | /* pointer fixup */ | ||
14027 | nodeptr = (int*)((char*)fs + fs->nodeptr_offset); | ||
14028 | while (*nodeptr) { | ||
14029 | int *ptr = (int*)((char*)fs + (*nodeptr - (int)fs->old_base)); | ||
14030 | if (*ptr) | ||
14031 | *ptr -= ((int)fs->old_base - (int)fs); | ||
14032 | nodeptr++; | ||
14033 | } | ||
14034 | /* Now fix up stuff that can't be transferred */ | ||
14035 | fs->fp = forkpoints[fs->fpid]; | ||
14036 | for (i = 0; i < ARRAY_SIZE(varinit_data); i++) | ||
14037 | fs->gvp->varinit[i].func = varinit_data[i].func; | ||
14038 | for (i = 0; i < CMDTABLESIZE; i++) { | ||
14039 | struct tblentry *e = fs->cmdtable[i]; | ||
14040 | while (e) { | ||
14041 | if (e->cmdtype == CMDBUILTIN) | ||
14042 | e->param.cmd = builtintab + (int)e->param.cmd; | ||
14043 | e = e->next; | ||
14044 | } | ||
14045 | } | ||
14046 | fs->gmp->exception_handler = ash_ptr_to_globals_misc->exception_handler; | ||
14047 | for (i = 0; i < NSIG; i++) | ||
14048 | fs->gmp->trap[i] = ash_ptr_to_globals_misc->trap[i]; | ||
14049 | fs->gmp->trap_ptr = ash_ptr_to_globals_misc->trap_ptr; | ||
14050 | |||
14051 | /* Switch global variables */ | ||
14052 | gvpp = (struct globals_var **)&ash_ptr_to_globals_var; | ||
14053 | *gvpp = fs->gvp; | ||
14054 | gmpp = (struct globals_misc **)&ash_ptr_to_globals_misc; | ||
14055 | *gmpp = fs->gmp; | ||
14056 | localvars = fs->localvars; | ||
14057 | cmdtable = fs->cmdtable; | ||
14058 | |||
14059 | fs->fp(fs); | ||
14060 | } | ||
14061 | |||
14062 | #undef free | ||
14063 | static void | ||
14064 | sticky_free(void *base) | ||
14065 | { | ||
14066 | if (base >= sticky_mem_start && base < sticky_mem_end) | ||
14067 | return; | ||
14068 | free(base); | ||
14069 | } | ||
13010 | 14070 | ||
13011 | /*- | 14071 | /*- |
13012 | * Copyright (c) 1989, 1991, 1993, 1994 | 14072 | * Copyright (c) 1989, 1991, 1993, 1994 |
diff --git a/win32/termios.c b/win32/termios.c index 0aba48546..6d85ff98e 100644 --- a/win32/termios.c +++ b/win32/termios.c | |||
@@ -1,4 +1,4 @@ | |||
1 | #include "busybox.h" | 1 | #include "libbb.h" |
2 | 2 | ||
3 | int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM, const struct termios *t UNUSED_PARAM) | 3 | int tcsetattr(int fd UNUSED_PARAM, int mode UNUSED_PARAM, const struct termios *t UNUSED_PARAM) |
4 | { | 4 | { |
@@ -9,3 +9,28 @@ int tcgetattr(int fd UNUSED_PARAM, struct termios *t UNUSED_PARAM) | |||
9 | { | 9 | { |
10 | return -1; | 10 | return -1; |
11 | } | 11 | } |
12 | |||
13 | int64_t FAST_FUNC read_key(int fd, char *buf, int timeout UNUSED_PARAM) | ||
14 | { | ||
15 | static int initialized = 0; | ||
16 | HANDLE cin = GetStdHandle(STD_INPUT_HANDLE); | ||
17 | INPUT_RECORD record; | ||
18 | DWORD nevent_out; | ||
19 | |||
20 | if (fd != 0) | ||
21 | bb_error_msg_and_die("read_key only works on stdin"); | ||
22 | if (cin == INVALID_HANDLE_VALUE) | ||
23 | return -1; | ||
24 | if (!initialized) { | ||
25 | SetConsoleMode(cin, ENABLE_ECHO_INPUT); | ||
26 | initialized = 1; | ||
27 | } | ||
28 | |||
29 | while (1) { | ||
30 | if (!ReadConsoleInput(cin, &record, 1, &nevent_out)) | ||
31 | return -1; | ||
32 | if (record.EventType != KEY_EVENT || !record.Event.KeyEvent.bKeyDown) | ||
33 | continue; | ||
34 | return record.Event.KeyEvent.uChar.AsciiChar; | ||
35 | } | ||
36 | } | ||