- {
- int old_sleep = die_sleep;
- int old_x = xfunc_error_retval;
- die_sleep = -1; /* special flag */
- /* xfunc_die() checks for it */
-
- rc = setjmp(die_jmp);
- if (!rc) {
- const struct bb_applet *old_a = current_applet;
- current_applet = a;
- applet_name = a->name;
-// what else should we save/restore?
- rc = a->main(argc, argv);
- current_applet = old_a;
- applet_name = old_a->name;
- } else {
- /* xfunc died in NOFORK applet */
- if (rc == -111)
- rc = 0;
- }
-
- die_sleep = old_sleep;
- xfunc_error_retval = old_x;
- return rc;
- }
-#ifndef BB_NOMMU /* MMU only */
- /* a->noexec is true */
- rc = fork();
- if (rc)
- goto w;
- /* child */
- current_applet = a;
- run_current_applet_and_exit(argc, argv);
-#endif
- }
-
+ /* optarg = NULL; opterr = 1; optopt = 63; - do we need this too? */
+ /* (values above are what they initialized to in glibc and uclibc) */
+ /* option_mask32 = 0; - not needed, no applet depends on it being 0 */
+
+ argc = 1;
+ while (argv[argc])
+ argc++;
+
+ rc = setjmp(die_jmp);
+ if (!rc) {
+ /* Some callers (xargs)
+ * need argv untouched because they free argv[i]! */
+ char *tmp_argv[argc+1];
+ memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
+ /* Finally we can call NOFORK applet's main() */
+ rc = applet_main[applet_no](argc, tmp_argv);
+
+ /* The whole reason behind nofork_save_area is that <applet>_main
+ * may exit non-locally! For example, in hush Ctrl-Z tries
+ * (modulo bugs) to dynamically create a child (backgrounded task)
+ * if it detects that Ctrl-Z was pressed when a NOFORK was running.
+ * Testcase: interactive "rm -i".
+ * Don't fool yourself into thinking "and <applet>_main() returns
+ * quickly here" and removing "useless" nofork_save_area code. */
+
+ } else { /* xfunc died in NOFORK applet */
+ /* in case they meant to return 0... */
+ if (rc == -2222)
+ rc = 0;