aboutsummaryrefslogtreecommitdiff
path: root/shell/hush.c
diff options
context:
space:
mode:
authorvda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-28 16:48:27 +0000
committervda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277>2007-04-28 16:48:27 +0000
commita7a0f08adc692821bb869bb407707466a976c5d2 (patch)
treec837d9d68385cb55f96f428e0e02de16f1fb9031 /shell/hush.c
parentecda805284f997a57e834f67de27bd879968f636 (diff)
downloadbusybox-w32-a7a0f08adc692821bb869bb407707466a976c5d2.tar.gz
busybox-w32-a7a0f08adc692821bb869bb407707466a976c5d2.tar.bz2
busybox-w32-a7a0f08adc692821bb869bb407707466a976c5d2.zip
hush: make job control and interactiveness configurable, part 2
git-svn-id: svn://busybox.net/trunk/busybox@18526 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'shell/hush.c')
-rw-r--r--shell/hush.c133
1 files changed, 84 insertions, 49 deletions
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;
243static struct close_me *close_me_head; 239static struct close_me *close_me_head;
244static const char *cwd; 240static const char *cwd;
245static unsigned last_bg_pid; 241static unsigned last_bg_pid;
246#if ENABLE_HUSH_INTERACTIVE 242#if !ENABLE_HUSH_INTERACTIVE
247static int last_jobid; 243enum { interactive_fd = 0 };
248static 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 */
251static int interactive_fd; 247static int interactive_fd;
248#if ENABLE_HUSH_JOB
252static pid_t saved_task_pgrp; 249static pid_t saved_task_pgrp;
253static pid_t saved_tty_pgrp; 250static pid_t saved_tty_pgrp;
254#else 251static int last_jobid;
255enum { interactive_fd = 0 }; 252static struct pipe *job_list;
256#endif 253#endif
257
258static const char *PS1; 254static const char *PS1;
259static const char *PS2; 255static const char *PS2;
256#endif
257
260static struct variables shell_ver = { NULL, "HUSH_VERSION", "0.01", 1, 1 }; 258static struct variables shell_ver = { NULL, "HUSH_VERSION", "0.01", 1, 1 };
261static struct variables *top_vars = &shell_ver; 259static 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
267typedef struct { 264typedef struct {
@@ -280,8 +277,10 @@ typedef struct {
280struct in_str { 277struct 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
326static void __syntax(const char *file, int line) 325static 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);
338static int builtin_exec(char **argv); 336static int builtin_exec(char **argv);
339static int builtin_exit(char **argv); 337static int builtin_exit(char **argv);
340static int builtin_export(char **argv); 338static int builtin_export(char **argv);
341#if ENABLE_HUSH_INTERACTIVE 339#if ENABLE_HUSH_JOB
342static int builtin_fg_bg(char **argv); 340static int builtin_fg_bg(char **argv);
343static int builtin_jobs(char **argv); 341static int builtin_jobs(char **argv);
344#endif 342#endif
@@ -405,7 +403,7 @@ static int parse_string_outer(const char *s, int flag);
405static int parse_file_outer(FILE *f); 403static int parse_file_outer(FILE *f);
406/* job management: */ 404/* job management: */
407static int checkjobs(struct pipe* fg_pipe); 405static int checkjobs(struct pipe* fg_pipe);
408#if ENABLE_HUSH_INTERACTIVE 406#if ENABLE_HUSH_JOB
409static int checkjobs_and_fg_shell(struct pipe* fg_pipe); 407static int checkjobs_and_fg_shell(struct pipe* fg_pipe);
410static void insert_bg_job(struct pipe *pi); 408static void insert_bg_job(struct pipe *pi);
411static void remove_bg_job(struct pipe *pi); 409static 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. */
429static const struct built_in_command bltins[] = { 427static 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 */
732static int builtin_fg_bg(char **argv) 730static 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 */
812static int builtin_jobs(char **argv ATTRIBUTE_UNUSED) 810static 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
1035static void cmdedit_set_initial_prompt(void) 1034static 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
1070static line_input_t *line_input_state; 1070static line_input_t *line_input_state;
1071#endif 1071#endif
1072 1072
1073#if ENABLE_HUSH_INTERACTIVE
1073static int get_user_input(struct in_str *i) 1074static 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
1337static const char *get_cmdtext(struct pipe *pi) 1347static 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
1368static void insert_bg_job(struct pipe *pi) 1378static 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
1560static int checkjobs_and_fg_shell(struct pipe* fg_pipe) 1570static 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)
1575static int run_single_fg_nofork(struct pipe *pi, const struct bb_applet *a, 1585static 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) {