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 to
+ * (modulo bugs) to dynamically create 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)
/* Restoring globals */
restore_nofork_data(old);
- return rc;
+ return rc & 0xff; /* don't confuse people with "exitcodes" >255 */
}
int run_nofork_applet(int applet_no, char **argv)
#define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
struct cmdentry {
- int cmdtype;
+ smallint cmdtype; /* CMDxxx */
union param {
int index;
+ /* index >= 0 for commands without path (slashes) */
+ /* (TODO: what exactly does the value mean? PATH position?) */
+ /* index == -1 for commands with slashes */
+ /* index == (-2 - applet_no) for NOFORK applets */
const struct builtincmd *cmd;
struct funcnode *func;
} u;
struct tblentry {
struct tblentry *next; /* next entry in hash chain */
union param param; /* definition of builtin function */
- short cmdtype; /* index identifying command */
+ smallint cmdtype; /* CMDxxx */
char rehash; /* if set, cd done since entry created */
char cmdname[ARB]; /* name of command */
};
case CMDNORMAL: {
int j = entry.u.index;
char *p;
- if (j == -1) {
+ if (j < 0) {
p = command;
} else {
do {
/* Execute the command. */
switch (cmdentry.cmdtype) {
default:
-
#if ENABLE_FEATURE_SH_NOFORK
- {
- /* TODO: don't rerun find_applet_by_name, find_command
- * already did it. Make it save applet_no somewhere */
- int applet_no = find_applet_by_name(argv[0]);
+ {
+ /* find_command() encodes applet_no as (-2 - applet_no) */
+ int applet_no = (- cmdentry.u.index - 2);
if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
- struct nofork_save_area nofork_save;
-
listsetvar(varlist.list, VEXPORT|VSTACK);
- save_nofork_data(&nofork_save);
- /* run <applet>_main(), then restore nofork_save_area */
- exitstatus = run_nofork_applet_prime(&nofork_save, applet_no, argv) & 0xff;
+ /* run <applet>_main() */
+ exitstatus = run_nofork_applet(applet_no, argv);
break;
}
- }
+ }
#endif
/* Fork off a child process if necessary. */
}
#if ENABLE_FEATURE_SH_STANDALONE
- if (find_applet_by_name(name) >= 0) {
- entry->cmdtype = CMDNORMAL;
- entry->u.index = -1;
- return;
+ {
+ int applet_no = find_applet_by_name(name);
+ if (applet_no >= 0) {
+ entry->cmdtype = CMDNORMAL;
+ entry->u.index = -2 - applet_no;
+ return;
+ }
}
#endif
|| prec == PREC(TOK_CONDITIONAL));
}
-typedef struct ARITCH_VAR_NUM {
+typedef struct {
arith_t val;
arith_t contidional_second_val;
char contidional_second_val_initialized;
else is variable name */
} v_n_t;
-typedef struct CHK_VAR_RECURSIVE_LOOPED {
+typedef struct chk_var_recursive_looped_t {
const char *var;
- struct CHK_VAR_RECURSIVE_LOOPED *next;
+ struct chk_var_recursive_looped_t *next;
} chk_var_recursive_looped_t;
static chk_var_recursive_looped_t *prev_chk_var_recursive;
//sp: if (child->sp)
argv_expanded = expand_strvec_to_strvec(argv + i);
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
- rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff;
+ rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded);
free(argv_expanded);
restore_redirects(squirrel);
debug_printf_exec("run_pipe return %d\n", rcode);