diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
commit | c0d4367d6b581eb5989c02815880cf0fa2851ae8 (patch) | |
tree | 868c266e627e2d7f65ba5a4d5f98a1c421453181 /libbb/vfork_daemon_rexec.c | |
parent | f6bad5ef766b0447158e3de2f55c35f1f6cecb58 (diff) | |
parent | da4441c44f6efccb6f7b7588404d9c6bfb7b6af8 (diff) | |
download | busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.gz busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.bz2 busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.zip |
Merge commit 'da4441c44f6efccb6f7b7588404d9c6bfb7b6af8' into merge
Conflicts:
libbb/vfork_daemon_rexec.c
networking/wget.c
procps/ps.c
Diffstat (limited to 'libbb/vfork_daemon_rexec.c')
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 61 |
1 files changed, 26 insertions, 35 deletions
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 1fbb1bba9..5d8056bd6 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -55,6 +55,7 @@ pid_t FAST_FUNC spawn(char **argv) | |||
55 | * Interested party can wait on pid and learn exit code. | 55 | * Interested party can wait on pid and learn exit code. |
56 | * If 111 - then it (most probably) failed to exec */ | 56 | * If 111 - then it (most probably) failed to exec */ |
57 | if (failed) { | 57 | if (failed) { |
58 | safe_waitpid(pid, NULL, 0); /* prevent zombie */ | ||
58 | errno = failed; | 59 | errno = failed; |
59 | return -1; | 60 | return -1; |
60 | } | 61 | } |
@@ -71,17 +72,22 @@ pid_t FAST_FUNC xspawn(char **argv) | |||
71 | } | 72 | } |
72 | 73 | ||
73 | #if ENABLE_FEATURE_PREFER_APPLETS | 74 | #if ENABLE_FEATURE_PREFER_APPLETS |
74 | void FAST_FUNC save_nofork_data(struct nofork_save_area *save) | 75 | struct nofork_save_area { |
76 | jmp_buf die_jmp; | ||
77 | const char *applet_name; | ||
78 | uint32_t option_mask32; | ||
79 | int die_sleep; | ||
80 | uint8_t xfunc_error_retval; | ||
81 | }; | ||
82 | static void save_nofork_data(struct nofork_save_area *save) | ||
75 | { | 83 | { |
76 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); | 84 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); |
77 | save->applet_name = applet_name; | 85 | save->applet_name = applet_name; |
78 | save->xfunc_error_retval = xfunc_error_retval; | 86 | save->xfunc_error_retval = xfunc_error_retval; |
79 | save->option_mask32 = option_mask32; | 87 | save->option_mask32 = option_mask32; |
80 | save->die_sleep = die_sleep; | 88 | save->die_sleep = die_sleep; |
81 | save->saved = 1; | ||
82 | } | 89 | } |
83 | 90 | static void restore_nofork_data(struct nofork_save_area *save) | |
84 | void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) | ||
85 | { | 91 | { |
86 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); | 92 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); |
87 | applet_name = save->applet_name; | 93 | applet_name = save->applet_name; |
@@ -90,19 +96,17 @@ void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) | |||
90 | die_sleep = save->die_sleep; | 96 | die_sleep = save->die_sleep; |
91 | } | 97 | } |
92 | 98 | ||
93 | int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv) | 99 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) |
94 | { | 100 | { |
95 | int rc, argc; | 101 | int rc, argc; |
102 | struct nofork_save_area old; | ||
103 | |||
104 | save_nofork_data(&old); | ||
96 | 105 | ||
97 | applet_name = APPLET_NAME(applet_no); | 106 | applet_name = APPLET_NAME(applet_no); |
98 | 107 | ||
99 | xfunc_error_retval = EXIT_FAILURE; | 108 | xfunc_error_retval = EXIT_FAILURE; |
100 | 109 | ||
101 | /* Special flag for xfunc_die(). If xfunc will "die" | ||
102 | * in NOFORK applet, xfunc_die() sees negative | ||
103 | * die_sleep and longjmp here instead. */ | ||
104 | die_sleep = -1; | ||
105 | |||
106 | /* In case getopt() or getopt32() was already called: | 110 | /* In case getopt() or getopt32() was already called: |
107 | * reset the libc getopt() function, which keeps internal state. | 111 | * reset the libc getopt() function, which keeps internal state. |
108 | * | 112 | * |
@@ -132,6 +136,11 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
132 | while (argv[argc]) | 136 | while (argv[argc]) |
133 | argc++; | 137 | argc++; |
134 | 138 | ||
139 | /* Special flag for xfunc_die(). If xfunc will "die" | ||
140 | * in NOFORK applet, xfunc_die() sees negative | ||
141 | * die_sleep and longjmp here instead. */ | ||
142 | die_sleep = -1; | ||
143 | |||
135 | rc = setjmp(die_jmp); | 144 | rc = setjmp(die_jmp); |
136 | if (!rc) { | 145 | if (!rc) { |
137 | /* Some callers (xargs) | 146 | /* Some callers (xargs) |
@@ -140,15 +149,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
140 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); | 149 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); |
141 | /* Finally we can call NOFORK applet's main() */ | 150 | /* Finally we can call NOFORK applet's main() */ |
142 | rc = applet_main[applet_no](argc, tmp_argv); | 151 | rc = applet_main[applet_no](argc, tmp_argv); |
143 | |||
144 | /* The whole reason behind nofork_save_area is that <applet>_main | ||
145 | * may exit non-locally! For example, in hush Ctrl-Z tries | ||
146 | * (modulo bugs) to dynamically create a child (backgrounded task) | ||
147 | * if it detects that Ctrl-Z was pressed when a NOFORK was running. | ||
148 | * Testcase: interactive "rm -i". | ||
149 | * Don't fool yourself into thinking "and <applet>_main() returns | ||
150 | * quickly here" and removing "useless" nofork_save_area code. */ | ||
151 | |||
152 | } else { /* xfunc died in NOFORK applet */ | 152 | } else { /* xfunc died in NOFORK applet */ |
153 | /* in case they meant to return 0... */ | 153 | /* in case they meant to return 0... */ |
154 | if (rc == -2222) | 154 | if (rc == -2222) |
@@ -156,7 +156,7 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* Restoring some globals */ | 158 | /* Restoring some globals */ |
159 | restore_nofork_data(old); | 159 | restore_nofork_data(&old); |
160 | 160 | ||
161 | /* Other globals can be simply reset to defaults */ | 161 | /* Other globals can be simply reset to defaults */ |
162 | #ifdef __GLIBC__ | 162 | #ifdef __GLIBC__ |
@@ -167,15 +167,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
167 | 167 | ||
168 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | 168 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ |
169 | } | 169 | } |
170 | |||
171 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | ||
172 | { | ||
173 | struct nofork_save_area old; | ||
174 | |||
175 | /* Saving globals */ | ||
176 | save_nofork_data(&old); | ||
177 | return run_nofork_applet_prime(&old, applet_no, argv); | ||
178 | } | ||
179 | #endif /* FEATURE_PREFER_APPLETS */ | 170 | #endif /* FEATURE_PREFER_APPLETS */ |
180 | 171 | ||
181 | int FAST_FUNC spawn_and_wait(char **argv) | 172 | int FAST_FUNC spawn_and_wait(char **argv) |
@@ -185,17 +176,17 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
185 | int a = find_applet_by_name(argv[0]); | 176 | int a = find_applet_by_name(argv[0]); |
186 | 177 | ||
187 | if (a >= 0 && (APPLET_IS_NOFORK(a) | 178 | if (a >= 0 && (APPLET_IS_NOFORK(a) |
188 | #if BB_MMU | 179 | # if BB_MMU |
189 | || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ | 180 | || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ |
190 | #endif | 181 | # endif |
191 | )) { | 182 | )) { |
192 | #if BB_MMU | 183 | # if BB_MMU |
193 | if (APPLET_IS_NOFORK(a)) | 184 | if (APPLET_IS_NOFORK(a)) |
194 | #endif | 185 | # endif |
195 | { | 186 | { |
196 | return run_nofork_applet(a, argv); | 187 | return run_nofork_applet(a, argv); |
197 | } | 188 | } |
198 | #if BB_MMU && !ENABLE_PLATFORM_MINGW32 | 189 | # if BB_MMU && !ENABLE_PLATFORM_MINGW32 |
199 | /* MMU only */ | 190 | /* MMU only */ |
200 | /* a->noexec is true */ | 191 | /* a->noexec is true */ |
201 | rc = fork(); | 192 | rc = fork(); |
@@ -204,7 +195,7 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
204 | /* child */ | 195 | /* child */ |
205 | xfunc_error_retval = EXIT_FAILURE; | 196 | xfunc_error_retval = EXIT_FAILURE; |
206 | run_applet_no_and_exit(a, argv); | 197 | run_applet_no_and_exit(a, argv); |
207 | #endif | 198 | # endif |
208 | } | 199 | } |
209 | #endif /* FEATURE_PREFER_APPLETS */ | 200 | #endif /* FEATURE_PREFER_APPLETS */ |
210 | rc = spawn(argv); | 201 | rc = spawn(argv); |