diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-28 16:48:27 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-04-28 16:48:27 +0000 |
commit | e3f2f8989139f00e94473882366bd665d4fcc800 (patch) | |
tree | c837d9d68385cb55f96f428e0e02de16f1fb9031 | |
parent | b81b3df1fa387fa5c6a3fe577969285858f494ce (diff) | |
download | busybox-w32-e3f2f8989139f00e94473882366bd665d4fcc800.tar.gz busybox-w32-e3f2f8989139f00e94473882366bd665d4fcc800.tar.bz2 busybox-w32-e3f2f8989139f00e94473882366bd665d4fcc800.zip |
hush: make job control and interactiveness configurable, part 2
-rw-r--r-- | shell/Config.in | 18 | ||||
-rw-r--r-- | shell/hush.c | 133 |
2 files changed, 99 insertions, 52 deletions
diff --git a/shell/Config.in b/shell/Config.in index 81289e4fd..f3726e302 100644 --- a/shell/Config.in +++ b/shell/Config.in | |||
@@ -181,9 +181,21 @@ config HUSH_INTERACTIVE | |||
181 | default y | 181 | default y |
182 | depends on HUSH | 182 | depends on HUSH |
183 | help | 183 | help |
184 | Enable interactive mode (Ctrl-Z, Ctrl-C, command editing) | 184 | Enable interactive mode (prompt and command editing). |
185 | in the hush shell. Without this, hush reads and executes | 185 | Without this, hush simply reads and executes commands |
186 | stdin just like a shell script from the file. | 186 | from stdin just like a shell script from the file. |
187 | No prompt, no PS1/PS2 magic shell variables. | ||
188 | |||
189 | config HUSH_JOB | ||
190 | bool "Job control" | ||
191 | default n | ||
192 | depends on HUSH_INTERACTIVE | ||
193 | help | ||
194 | Enable job control: Ctrl-Z backgrounds, Ctrl-C interrupts current | ||
195 | command (not entire shell), fg/bg builtins work. Without this option, | ||
196 | "cmd &" still works by simply spawning a process and immediately | ||
197 | prompting for next command (or executing next command in a script), | ||
198 | but no separate process group is formed. | ||
187 | 199 | ||
188 | 200 | ||
189 | config LASH | 201 | config LASH |
diff --git a/shell/hush.c b/shell/hush.c index 57a4ac04f..850b38f37 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -86,10 +86,6 @@ | |||
86 | /* Finer-grained debug switch */ | 86 | /* Finer-grained debug switch */ |
87 | //#define DEBUG_SHELL_JOBS | 87 | //#define DEBUG_SHELL_JOBS |
88 | 88 | ||
89 | //TODO: rename HUSH_INTERACTIVE -> HUSH_JOB, | ||
90 | //create HUSH_INTERACTIVE which controls only prompt + line editing, | ||
91 | //make HUSH_JOB dependent on it | ||
92 | |||
93 | #if !ENABLE_HUSH_INTERACTIVE | 89 | #if !ENABLE_HUSH_INTERACTIVE |
94 | #undef ENABLE_FEATURE_EDITING | 90 | #undef ENABLE_FEATURE_EDITING |
95 | #define ENABLE_FEATURE_EDITING 0 | 91 | #define ENABLE_FEATURE_EDITING 0 |
@@ -204,7 +200,7 @@ struct pipe { | |||
204 | int num_progs; /* total number of programs in job */ | 200 | int num_progs; /* total number of programs in job */ |
205 | int running_progs; /* number of programs running (not exited) */ | 201 | int running_progs; /* number of programs running (not exited) */ |
206 | char *cmdbuf; /* buffer various argv's point into */ | 202 | char *cmdbuf; /* buffer various argv's point into */ |
207 | #if ENABLE_HUSH_INTERACTIVE | 203 | #if ENABLE_HUSH_JOB |
208 | int jobid; /* job number */ | 204 | int jobid; /* job number */ |
209 | char *cmdtext; /* name of job */ | 205 | char *cmdtext; /* name of job */ |
210 | pid_t pgrp; /* process group ID for the job */ | 206 | pid_t pgrp; /* process group ID for the job */ |
@@ -243,25 +239,26 @@ static int fake_mode; | |||
243 | static struct close_me *close_me_head; | 239 | static struct close_me *close_me_head; |
244 | static const char *cwd; | 240 | static const char *cwd; |
245 | static unsigned last_bg_pid; | 241 | static unsigned last_bg_pid; |
246 | #if ENABLE_HUSH_INTERACTIVE | 242 | #if !ENABLE_HUSH_INTERACTIVE |
247 | static int last_jobid; | 243 | enum { interactive_fd = 0 }; |
248 | static struct pipe *job_list; | 244 | #else |
249 | /* 'interactive_fd' is a fd# open to ctty, if we have one | 245 | /* 'interactive_fd' is a fd# open to ctty, if we have one |
250 | * _AND_ if we decided to mess with job control */ | 246 | * _AND_ if we decided to mess with job control */ |
251 | static int interactive_fd; | 247 | static int interactive_fd; |
248 | #if ENABLE_HUSH_JOB | ||
252 | static pid_t saved_task_pgrp; | 249 | static pid_t saved_task_pgrp; |
253 | static pid_t saved_tty_pgrp; | 250 | static pid_t saved_tty_pgrp; |
254 | #else | 251 | static int last_jobid; |
255 | enum { interactive_fd = 0 }; | 252 | static struct pipe *job_list; |
256 | #endif | 253 | #endif |
257 | |||
258 | static const char *PS1; | 254 | static const char *PS1; |
259 | static const char *PS2; | 255 | static const char *PS2; |
256 | #endif | ||
257 | |||
260 | static struct variables shell_ver = { NULL, "HUSH_VERSION", "0.01", 1, 1 }; | 258 | static struct variables shell_ver = { NULL, "HUSH_VERSION", "0.01", 1, 1 }; |
261 | static struct variables *top_vars = &shell_ver; | 259 | static struct variables *top_vars = &shell_ver; |
262 | 260 | ||
263 | 261 | #define B_CHUNK 100 | |
264 | #define B_CHUNK (100) | ||
265 | #define B_NOSPAC 1 | 262 | #define B_NOSPAC 1 |
266 | 263 | ||
267 | typedef struct { | 264 | typedef struct { |
@@ -280,8 +277,10 @@ typedef struct { | |||
280 | struct in_str { | 277 | struct in_str { |
281 | const char *p; | 278 | const char *p; |
282 | char peek_buf[2]; | 279 | char peek_buf[2]; |
280 | #if ENABLE_HUSH_INTERACTIVE | ||
283 | int __promptme; | 281 | int __promptme; |
284 | int promptmode; | 282 | int promptmode; |
283 | #endif | ||
285 | FILE *file; | 284 | FILE *file; |
286 | int (*get) (struct in_str *); | 285 | int (*get) (struct in_str *); |
287 | int (*peek) (struct in_str *); | 286 | int (*peek) (struct in_str *); |
@@ -323,12 +322,11 @@ static char *indenter(int i) | |||
323 | 322 | ||
324 | #define final_printf debug_printf | 323 | #define final_printf debug_printf |
325 | 324 | ||
326 | static void __syntax(const char *file, int line) | 325 | static void __syntax(int line) |
327 | { | 326 | { |
328 | bb_error_msg("syntax error %s:%d", file, line); | 327 | bb_error_msg("syntax error hush.c:%d", line); |
329 | } | 328 | } |
330 | /* NB: was __FILE__, but that produces full path sometimes, so... */ | 329 | #define syntax() __syntax(__LINE__) |
331 | #define syntax() __syntax("hush.c", __LINE__) | ||
332 | 330 | ||
333 | /* Index of subroutines: */ | 331 | /* Index of subroutines: */ |
334 | /* function prototypes for builtins */ | 332 | /* function prototypes for builtins */ |
@@ -338,7 +336,7 @@ static int builtin_eval(char **argv); | |||
338 | static int builtin_exec(char **argv); | 336 | static int builtin_exec(char **argv); |
339 | static int builtin_exit(char **argv); | 337 | static int builtin_exit(char **argv); |
340 | static int builtin_export(char **argv); | 338 | static int builtin_export(char **argv); |
341 | #if ENABLE_HUSH_INTERACTIVE | 339 | #if ENABLE_HUSH_JOB |
342 | static int builtin_fg_bg(char **argv); | 340 | static int builtin_fg_bg(char **argv); |
343 | static int builtin_jobs(char **argv); | 341 | static int builtin_jobs(char **argv); |
344 | #endif | 342 | #endif |
@@ -405,7 +403,7 @@ static int parse_string_outer(const char *s, int flag); | |||
405 | static int parse_file_outer(FILE *f); | 403 | static int parse_file_outer(FILE *f); |
406 | /* job management: */ | 404 | /* job management: */ |
407 | static int checkjobs(struct pipe* fg_pipe); | 405 | static int checkjobs(struct pipe* fg_pipe); |
408 | #if ENABLE_HUSH_INTERACTIVE | 406 | #if ENABLE_HUSH_JOB |
409 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe); | 407 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe); |
410 | static void insert_bg_job(struct pipe *pi); | 408 | static void insert_bg_job(struct pipe *pi); |
411 | static void remove_bg_job(struct pipe *pi); | 409 | static void remove_bg_job(struct pipe *pi); |
@@ -427,7 +425,7 @@ static void unset_local_var(const char *name); | |||
427 | * For example, 'unset foo | whatever' will parse and run, but foo will | 425 | * For example, 'unset foo | whatever' will parse and run, but foo will |
428 | * still be set at the end. */ | 426 | * still be set at the end. */ |
429 | static const struct built_in_command bltins[] = { | 427 | static const struct built_in_command bltins[] = { |
430 | #if ENABLE_HUSH_INTERACTIVE | 428 | #if ENABLE_HUSH_JOB |
431 | { "bg", "Resume a job in the background", builtin_fg_bg }, | 429 | { "bg", "Resume a job in the background", builtin_fg_bg }, |
432 | #endif | 430 | #endif |
433 | { "break", "Exit for, while or until loop", builtin_not_written }, | 431 | { "break", "Exit for, while or until loop", builtin_not_written }, |
@@ -439,7 +437,7 @@ static const struct built_in_command bltins[] = { | |||
439 | builtin_exec }, | 437 | builtin_exec }, |
440 | { "exit", "Exit from shell()", builtin_exit }, | 438 | { "exit", "Exit from shell()", builtin_exit }, |
441 | { "export", "Set environment variable", builtin_export }, | 439 | { "export", "Set environment variable", builtin_export }, |
442 | #if ENABLE_HUSH_INTERACTIVE | 440 | #if ENABLE_HUSH_JOB |
443 | { "fg", "Bring job into the foreground", builtin_fg_bg }, | 441 | { "fg", "Bring job into the foreground", builtin_fg_bg }, |
444 | { "jobs", "Lists the active jobs", builtin_jobs }, | 442 | { "jobs", "Lists the active jobs", builtin_jobs }, |
445 | #endif | 443 | #endif |
@@ -457,7 +455,7 @@ static const struct built_in_command bltins[] = { | |||
457 | { NULL, NULL, NULL } | 455 | { NULL, NULL, NULL } |
458 | }; | 456 | }; |
459 | 457 | ||
460 | #if ENABLE_HUSH_INTERACTIVE | 458 | #if ENABLE_HUSH_JOB |
461 | 459 | ||
462 | #if ENABLE_FEATURE_SH_STANDALONE | 460 | #if ENABLE_FEATURE_SH_STANDALONE |
463 | /* move to libbb? */ | 461 | /* move to libbb? */ |
@@ -727,7 +725,7 @@ static int builtin_export(char **argv) | |||
727 | return res; | 725 | return res; |
728 | } | 726 | } |
729 | 727 | ||
730 | #if ENABLE_HUSH_INTERACTIVE | 728 | #if ENABLE_HUSH_JOB |
731 | /* built-in 'fg' and 'bg' handler */ | 729 | /* built-in 'fg' and 'bg' handler */ |
732 | static int builtin_fg_bg(char **argv) | 730 | static int builtin_fg_bg(char **argv) |
733 | { | 731 | { |
@@ -807,7 +805,7 @@ static int builtin_help(char **argv ATTRIBUTE_UNUSED) | |||
807 | return EXIT_SUCCESS; | 805 | return EXIT_SUCCESS; |
808 | } | 806 | } |
809 | 807 | ||
810 | #if ENABLE_HUSH_INTERACTIVE | 808 | #if ENABLE_HUSH_JOB |
811 | /* built-in 'jobs' handler */ | 809 | /* built-in 'jobs' handler */ |
812 | static int builtin_jobs(char **argv ATTRIBUTE_UNUSED) | 810 | static int builtin_jobs(char **argv ATTRIBUTE_UNUSED) |
813 | { | 811 | { |
@@ -1032,6 +1030,7 @@ static int static_peek(struct in_str *i) | |||
1032 | return *i->p; | 1030 | return *i->p; |
1033 | } | 1031 | } |
1034 | 1032 | ||
1033 | #if ENABLE_HUSH_INTERACTIVE | ||
1035 | static void cmdedit_set_initial_prompt(void) | 1034 | static void cmdedit_set_initial_prompt(void) |
1036 | { | 1035 | { |
1037 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT | 1036 | #if !ENABLE_FEATURE_EDITING_FANCY_PROMPT |
@@ -1065,17 +1064,19 @@ static const char* setup_prompt_string(int promptmode) | |||
1065 | debug_printf("result %s\n", prompt_str); | 1064 | debug_printf("result %s\n", prompt_str); |
1066 | return prompt_str; | 1065 | return prompt_str; |
1067 | } | 1066 | } |
1067 | #endif | ||
1068 | 1068 | ||
1069 | #if ENABLE_FEATURE_EDITING | 1069 | #if ENABLE_FEATURE_EDITING |
1070 | static line_input_t *line_input_state; | 1070 | static line_input_t *line_input_state; |
1071 | #endif | 1071 | #endif |
1072 | 1072 | ||
1073 | #if ENABLE_HUSH_INTERACTIVE | ||
1073 | static int get_user_input(struct in_str *i) | 1074 | static int get_user_input(struct in_str *i) |
1074 | { | 1075 | { |
1076 | static char the_command[ENABLE_FEATURE_EDITING ? BUFSIZ : 2]; | ||
1077 | |||
1075 | int r; | 1078 | int r; |
1076 | const char *prompt_str; | 1079 | const char *prompt_str; |
1077 | static char the_command[BUFSIZ]; | ||
1078 | |||
1079 | prompt_str = setup_prompt_string(i->promptmode); | 1080 | prompt_str = setup_prompt_string(i->promptmode); |
1080 | #if ENABLE_FEATURE_EDITING | 1081 | #if ENABLE_FEATURE_EDITING |
1081 | /* | 1082 | /* |
@@ -1095,6 +1096,7 @@ static int get_user_input(struct in_str *i) | |||
1095 | i->p = the_command; | 1096 | i->p = the_command; |
1096 | return r; /* < 0 == EOF. Not meaningful otherwise */ | 1097 | return r; /* < 0 == EOF. Not meaningful otherwise */ |
1097 | } | 1098 | } |
1099 | #endif | ||
1098 | 1100 | ||
1099 | /* This is the magic location that prints prompts | 1101 | /* This is the magic location that prints prompts |
1100 | * and gets data back from the user */ | 1102 | * and gets data back from the user */ |
@@ -1109,7 +1111,8 @@ static int file_get(struct in_str *i) | |||
1109 | } else { | 1111 | } else { |
1110 | /* need to double check i->file because we might be doing something | 1112 | /* need to double check i->file because we might be doing something |
1111 | * more complicated by now, like sourcing or substituting. */ | 1113 | * more complicated by now, like sourcing or substituting. */ |
1112 | if (i->__promptme && interactive_fd && i->file == stdin) { | 1114 | #if ENABLE_HUSH_INTERACTIVE |
1115 | if (interactive_fd && i->__promptme && i->file == stdin) { | ||
1113 | while (!i->p || !(interactive_fd && i->p[0])) { | 1116 | while (!i->p || !(interactive_fd && i->p[0])) { |
1114 | if (get_user_input(i) < 0) | 1117 | if (get_user_input(i) < 0) |
1115 | return EOF; | 1118 | return EOF; |
@@ -1119,14 +1122,17 @@ static int file_get(struct in_str *i) | |||
1119 | if (i->p && *i->p) { | 1122 | if (i->p && *i->p) { |
1120 | ch = *i->p++; | 1123 | ch = *i->p++; |
1121 | } | 1124 | } |
1122 | } else { | 1125 | } else |
1126 | #endif | ||
1127 | { | ||
1123 | ch = fgetc(i->file); | 1128 | ch = fgetc(i->file); |
1124 | } | 1129 | } |
1125 | |||
1126 | debug_printf("b_getch: got a %d\n", ch); | 1130 | debug_printf("b_getch: got a %d\n", ch); |
1127 | } | 1131 | } |
1132 | #if ENABLE_HUSH_INTERACTIVE | ||
1128 | if (ch == '\n') | 1133 | if (ch == '\n') |
1129 | i->__promptme = 1; | 1134 | i->__promptme = 1; |
1135 | #endif | ||
1130 | return ch; | 1136 | return ch; |
1131 | } | 1137 | } |
1132 | 1138 | ||
@@ -1149,8 +1155,10 @@ static void setup_file_in_str(struct in_str *i, FILE *f) | |||
1149 | { | 1155 | { |
1150 | i->peek = file_peek; | 1156 | i->peek = file_peek; |
1151 | i->get = file_get; | 1157 | i->get = file_get; |
1158 | #if ENABLE_HUSH_INTERACTIVE | ||
1152 | i->__promptme = 1; | 1159 | i->__promptme = 1; |
1153 | i->promptmode = 1; | 1160 | i->promptmode = 1; |
1161 | #endif | ||
1154 | i->file = f; | 1162 | i->file = f; |
1155 | i->p = NULL; | 1163 | i->p = NULL; |
1156 | } | 1164 | } |
@@ -1159,8 +1167,10 @@ static void setup_string_in_str(struct in_str *i, const char *s) | |||
1159 | { | 1167 | { |
1160 | i->peek = static_peek; | 1168 | i->peek = static_peek; |
1161 | i->get = static_get; | 1169 | i->get = static_get; |
1170 | #if ENABLE_HUSH_INTERACTIVE | ||
1162 | i->__promptme = 1; | 1171 | i->__promptme = 1; |
1163 | i->promptmode = 1; | 1172 | i->promptmode = 1; |
1173 | #endif | ||
1164 | i->p = s; | 1174 | i->p = s; |
1165 | } | 1175 | } |
1166 | 1176 | ||
@@ -1333,7 +1343,7 @@ static void pseudo_exec(struct child_prog *child) | |||
1333 | _exit(EXIT_SUCCESS); | 1343 | _exit(EXIT_SUCCESS); |
1334 | } | 1344 | } |
1335 | 1345 | ||
1336 | #if ENABLE_HUSH_INTERACTIVE | 1346 | #if ENABLE_HUSH_JOB |
1337 | static const char *get_cmdtext(struct pipe *pi) | 1347 | static const char *get_cmdtext(struct pipe *pi) |
1338 | { | 1348 | { |
1339 | char **argv; | 1349 | char **argv; |
@@ -1364,7 +1374,7 @@ static const char *get_cmdtext(struct pipe *pi) | |||
1364 | } | 1374 | } |
1365 | #endif | 1375 | #endif |
1366 | 1376 | ||
1367 | #if ENABLE_HUSH_INTERACTIVE | 1377 | #if ENABLE_HUSH_JOB |
1368 | static void insert_bg_job(struct pipe *pi) | 1378 | static void insert_bg_job(struct pipe *pi) |
1369 | { | 1379 | { |
1370 | struct pipe *thejob; | 1380 | struct pipe *thejob; |
@@ -1436,7 +1446,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1436 | { | 1446 | { |
1437 | int attributes; | 1447 | int attributes; |
1438 | int status; | 1448 | int status; |
1439 | #if ENABLE_HUSH_INTERACTIVE | 1449 | #if ENABLE_HUSH_JOB |
1440 | int prognum = 0; | 1450 | int prognum = 0; |
1441 | struct pipe *pi; | 1451 | struct pipe *pi; |
1442 | #endif | 1452 | #endif |
@@ -1496,7 +1506,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1496 | fg_pipe->running_progs, fg_pipe->stopped_progs); | 1506 | fg_pipe->running_progs, fg_pipe->stopped_progs); |
1497 | if (fg_pipe->running_progs - fg_pipe->stopped_progs <= 0) { | 1507 | if (fg_pipe->running_progs - fg_pipe->stopped_progs <= 0) { |
1498 | /* All processes in fg pipe have exited/stopped */ | 1508 | /* All processes in fg pipe have exited/stopped */ |
1499 | #if ENABLE_HUSH_INTERACTIVE | 1509 | #if ENABLE_HUSH_JOB |
1500 | if (fg_pipe->running_progs) | 1510 | if (fg_pipe->running_progs) |
1501 | insert_bg_job(fg_pipe); | 1511 | insert_bg_job(fg_pipe); |
1502 | #endif | 1512 | #endif |
@@ -1509,7 +1519,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1509 | /* fall through to searching process in bg pipes */ | 1519 | /* fall through to searching process in bg pipes */ |
1510 | } | 1520 | } |
1511 | 1521 | ||
1512 | #if ENABLE_HUSH_INTERACTIVE | 1522 | #if ENABLE_HUSH_JOB |
1513 | /* We asked to wait for bg or orphaned children */ | 1523 | /* We asked to wait for bg or orphaned children */ |
1514 | /* No need to remember exitcode in this case */ | 1524 | /* No need to remember exitcode in this case */ |
1515 | for (pi = job_list; pi; pi = pi->next) { | 1525 | for (pi = job_list; pi; pi = pi->next) { |
@@ -1526,7 +1536,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1526 | debug_printf("checkjobs: pid %d was not in our list!\n", childpid); | 1536 | debug_printf("checkjobs: pid %d was not in our list!\n", childpid); |
1527 | goto wait_more; | 1537 | goto wait_more; |
1528 | 1538 | ||
1529 | #if ENABLE_HUSH_INTERACTIVE | 1539 | #if ENABLE_HUSH_JOB |
1530 | found_pi_and_prognum: | 1540 | found_pi_and_prognum: |
1531 | if (dead) { | 1541 | if (dead) { |
1532 | /* child exited */ | 1542 | /* child exited */ |
@@ -1556,7 +1566,7 @@ static int checkjobs(struct pipe* fg_pipe) | |||
1556 | return rcode; | 1566 | return rcode; |
1557 | } | 1567 | } |
1558 | 1568 | ||
1559 | #if ENABLE_HUSH_INTERACTIVE | 1569 | #if ENABLE_HUSH_JOB |
1560 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | 1570 | static int checkjobs_and_fg_shell(struct pipe* fg_pipe) |
1561 | { | 1571 | { |
1562 | pid_t p; | 1572 | pid_t p; |
@@ -1575,7 +1585,7 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe) | |||
1575 | static int run_single_fg_nofork(struct pipe *pi, const struct bb_applet *a, | 1585 | static int run_single_fg_nofork(struct pipe *pi, const struct bb_applet *a, |
1576 | char **argv) | 1586 | char **argv) |
1577 | { | 1587 | { |
1578 | #if ENABLE_HUSH_INTERACTIVE | 1588 | #if ENABLE_HUSH_JOB |
1579 | int rcode; | 1589 | int rcode; |
1580 | /* TSTP handler will store pid etc in pi */ | 1590 | /* TSTP handler will store pid etc in pi */ |
1581 | nofork_pipe = pi; | 1591 | nofork_pipe = pi; |
@@ -1637,7 +1647,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1637 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); | 1647 | const int single_fg = (pi->num_progs == 1 && pi->followup != PIPE_BG); |
1638 | 1648 | ||
1639 | nextin = 0; | 1649 | nextin = 0; |
1640 | #if ENABLE_HUSH_INTERACTIVE | 1650 | #if ENABLE_HUSH_JOB |
1641 | pi->pgrp = -1; | 1651 | pi->pgrp = -1; |
1642 | #endif | 1652 | #endif |
1643 | pi->running_progs = 0; | 1653 | pi->running_progs = 0; |
@@ -1766,7 +1776,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1766 | if (!child->pid) { /* child */ | 1776 | if (!child->pid) { /* child */ |
1767 | /* Every child adds itself to new process group | 1777 | /* Every child adds itself to new process group |
1768 | * with pgid == pid of first child in pipe */ | 1778 | * with pgid == pid of first child in pipe */ |
1769 | #if ENABLE_HUSH_INTERACTIVE | 1779 | #if ENABLE_HUSH_JOB |
1770 | if (interactive_fd) { | 1780 | if (interactive_fd) { |
1771 | /* Don't do pgrp restore anymore on fatal signals */ | 1781 | /* Don't do pgrp restore anymore on fatal signals */ |
1772 | set_fatal_sighandler(SIG_DFL); | 1782 | set_fatal_sighandler(SIG_DFL); |
@@ -1805,7 +1815,7 @@ static int run_pipe_real(struct pipe *pi) | |||
1805 | 1815 | ||
1806 | pi->running_progs++; | 1816 | pi->running_progs++; |
1807 | 1817 | ||
1808 | #if ENABLE_HUSH_INTERACTIVE | 1818 | #if ENABLE_HUSH_JOB |
1809 | /* Second and next children need to know pid of first one */ | 1819 | /* Second and next children need to know pid of first one */ |
1810 | if (pi->pgrp < 0) | 1820 | if (pi->pgrp < 0) |
1811 | pi->pgrp = child->pid; | 1821 | pi->pgrp = child->pid; |
@@ -1937,14 +1947,17 @@ static int run_list_real(struct pipe *pi) | |||
1937 | /* XXX check bash's behavior with nontrivial pipes */ | 1947 | /* XXX check bash's behavior with nontrivial pipes */ |
1938 | /* XXX compute jobid */ | 1948 | /* XXX compute jobid */ |
1939 | /* XXX what does bash do with attempts to background builtins? */ | 1949 | /* XXX what does bash do with attempts to background builtins? */ |
1940 | #if ENABLE_HUSH_INTERACTIVE | 1950 | #if ENABLE_HUSH_JOB |
1941 | insert_bg_job(pi); | 1951 | insert_bg_job(pi); |
1942 | #endif | 1952 | #endif |
1943 | rcode = EXIT_SUCCESS; | 1953 | rcode = EXIT_SUCCESS; |
1944 | } else { | 1954 | } else { |
1955 | #if ENABLE_HUSH_JOB | ||
1945 | if (interactive_fd) { | 1956 | if (interactive_fd) { |
1946 | rcode = checkjobs_and_fg_shell(pi); | 1957 | rcode = checkjobs_and_fg_shell(pi); |
1947 | } else { | 1958 | } else |
1959 | #endif | ||
1960 | { | ||
1948 | rcode = checkjobs(pi); | 1961 | rcode = checkjobs(pi); |
1949 | } | 1962 | } |
1950 | debug_printf("checkjobs returned %d\n", rcode); | 1963 | debug_printf("checkjobs returned %d\n", rcode); |
@@ -2012,7 +2025,7 @@ static int free_pipe(struct pipe *pi, int indent) | |||
2012 | } | 2025 | } |
2013 | free(pi->progs); /* children are an array, they get freed all at once */ | 2026 | free(pi->progs); /* children are an array, they get freed all at once */ |
2014 | pi->progs = NULL; | 2027 | pi->progs = NULL; |
2015 | #if ENABLE_HUSH_INTERACTIVE | 2028 | #if ENABLE_HUSH_JOB |
2016 | free(pi->cmdtext); | 2029 | free(pi->cmdtext); |
2017 | pi->cmdtext = NULL; | 2030 | pi->cmdtext = NULL; |
2018 | #endif | 2031 | #endif |
@@ -3084,7 +3097,9 @@ static int parse_stream_outer(struct in_str *inp, int flag) | |||
3084 | update_ifs_map(); | 3097 | update_ifs_map(); |
3085 | if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) | 3098 | if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) |
3086 | mapset(";$&|", 0); | 3099 | mapset(";$&|", 0); |
3100 | #if ENABLE_HUSH_INTERACTIVE | ||
3087 | inp->promptmode = 1; | 3101 | inp->promptmode = 1; |
3102 | #endif | ||
3088 | rcode = parse_stream(&temp, &ctx, inp, '\n'); | 3103 | rcode = parse_stream(&temp, &ctx, inp, '\n'); |
3089 | if (rcode != 1 && ctx.old_flag != 0) { | 3104 | if (rcode != 1 && ctx.old_flag != 0) { |
3090 | syntax(); | 3105 | syntax(); |
@@ -3124,7 +3139,7 @@ static int parse_file_outer(FILE *f) | |||
3124 | return rcode; | 3139 | return rcode; |
3125 | } | 3140 | } |
3126 | 3141 | ||
3127 | #if ENABLE_HUSH_INTERACTIVE | 3142 | #if ENABLE_HUSH_JOB |
3128 | /* Make sure we have a controlling tty. If we get started under a job | 3143 | /* Make sure we have a controlling tty. If we get started under a job |
3129 | * aware app (like bash for example), make sure we are now in charge so | 3144 | * aware app (like bash for example), make sure we are now in charge so |
3130 | * we don't fight over who gets the foreground */ | 3145 | * we don't fight over who gets the foreground */ |
@@ -3183,6 +3198,8 @@ int hush_main(int argc, char **argv) | |||
3183 | close_me_head = NULL; | 3198 | close_me_head = NULL; |
3184 | #if ENABLE_HUSH_INTERACTIVE | 3199 | #if ENABLE_HUSH_INTERACTIVE |
3185 | interactive_fd = 0; | 3200 | interactive_fd = 0; |
3201 | #endif | ||
3202 | #if ENABLE_HUSH_JOB | ||
3186 | last_bg_pid = 0; | 3203 | last_bg_pid = 0; |
3187 | job_list = NULL; | 3204 | job_list = NULL; |
3188 | last_jobid = 0; | 3205 | last_jobid = 0; |
@@ -3190,11 +3207,14 @@ int hush_main(int argc, char **argv) | |||
3190 | 3207 | ||
3191 | /* Initialize some more globals to non-zero values */ | 3208 | /* Initialize some more globals to non-zero values */ |
3192 | set_cwd(); | 3209 | set_cwd(); |
3193 | if (ENABLE_FEATURE_EDITING) | 3210 | #if ENABLE_HUSH_INTERACTIVE |
3194 | cmdedit_set_initial_prompt(); | 3211 | #if ENABLE_FEATURE_EDITING |
3195 | else PS1 = NULL; | 3212 | cmdedit_set_initial_prompt(); |
3213 | #else | ||
3214 | PS1 = NULL; | ||
3215 | #endif | ||
3196 | PS2 = "> "; | 3216 | PS2 = "> "; |
3197 | 3217 | #endif | |
3198 | /* initialize our shell local variables with the values | 3218 | /* initialize our shell local variables with the values |
3199 | * currently living in the environment */ | 3219 | * currently living in the environment */ |
3200 | e = environ; | 3220 | e = environ; |
@@ -3241,7 +3261,7 @@ int hush_main(int argc, char **argv) | |||
3241 | #endif | 3261 | #endif |
3242 | } | 3262 | } |
3243 | } | 3263 | } |
3244 | #if ENABLE_HUSH_INTERACTIVE | 3264 | #if ENABLE_HUSH_JOB |
3245 | /* A shell is interactive if the '-i' flag was given, or if all of | 3265 | /* A shell is interactive if the '-i' flag was given, or if all of |
3246 | * the following conditions are met: | 3266 | * the following conditions are met: |
3247 | * no -c command | 3267 | * no -c command |
@@ -3283,6 +3303,21 @@ int hush_main(int argc, char **argv) | |||
3283 | printf("Enter 'help' for a list of built-in commands.\n\n"); | 3303 | printf("Enter 'help' for a list of built-in commands.\n\n"); |
3284 | #endif | 3304 | #endif |
3285 | } | 3305 | } |
3306 | #elif ENABLE_HUSH_INTERACTIVE | ||
3307 | /* no job control compiled, only prompt/line editing */ | ||
3308 | if (argv[optind] == NULL && input == stdin | ||
3309 | && isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) | ||
3310 | ) { | ||
3311 | interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); | ||
3312 | if (interactive_fd < 0) { | ||
3313 | /* try to dup to any fd */ | ||
3314 | interactive_fd = dup(STDIN_FILENO); | ||
3315 | if (interactive_fd < 0) | ||
3316 | /* give up */ | ||
3317 | interactive_fd = 0; | ||
3318 | } | ||
3319 | } | ||
3320 | |||
3286 | #endif | 3321 | #endif |
3287 | 3322 | ||
3288 | if (argv[optind] == NULL) { | 3323 | if (argv[optind] == NULL) { |