aboutsummaryrefslogtreecommitdiff
path: root/libbb/vfork_daemon_rexec.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-03-22 13:15:08 +0000
committerRon Yorston <rmy@pobox.com>2012-03-22 13:15:08 +0000
commitc0d4367d6b581eb5989c02815880cf0fa2851ae8 (patch)
tree868c266e627e2d7f65ba5a4d5f98a1c421453181 /libbb/vfork_daemon_rexec.c
parentf6bad5ef766b0447158e3de2f55c35f1f6cecb58 (diff)
parentda4441c44f6efccb6f7b7588404d9c6bfb7b6af8 (diff)
downloadbusybox-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.c61
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
74void FAST_FUNC save_nofork_data(struct nofork_save_area *save) 75struct 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};
82static 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 90static void restore_nofork_data(struct nofork_save_area *save)
84void 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
93int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv) 99int 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
171int 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
181int FAST_FUNC spawn_and_wait(char **argv) 172int 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);