aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2004-02-10 01:07:45 +0000
committerEric Andersen <andersen@codepoet.org>2004-02-10 01:07:45 +0000
commitff9ad47d794fb26022a0e0b14d4ed946bd3bada6 (patch)
treeaec942cfc8b4b5d1bab9535e048e3dbee542e7d2
parenta0e4c3f119a216c890366e01163080e6e45fea7d (diff)
downloadbusybox-w32-ff9ad47d794fb26022a0e0b14d4ed946bd3bada6.tar.gz
busybox-w32-ff9ad47d794fb26022a0e0b14d4ed946bd3bada6.tar.bz2
busybox-w32-ff9ad47d794fb26022a0e0b14d4ed946bd3bada6.zip
Support disabling pipe and redirect support
-rw-r--r--shell/lash.c107
1 files changed, 67 insertions, 40 deletions
diff --git a/shell/lash.c b/shell/lash.c
index 1fcd63bdf..3675d21df 100644
--- a/shell/lash.c
+++ b/shell/lash.c
@@ -56,14 +56,18 @@
56#include <glob.h> 56#include <glob.h>
57#define expand_t glob_t 57#define expand_t glob_t
58 58
59/* Always enable for the moment... */
60#define CONFIG_LASH_PIPE_N_REDIRECTS
59 61
60static const int MAX_READ = 128; /* size of input buffer for `read' builtin */ 62static const int MAX_READ = 128; /* size of input buffer for `read' builtin */
61#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" 63#define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n"
62 64
63 65
66#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
64enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE, 67enum redir_type { REDIRECT_INPUT, REDIRECT_OVERWRITE,
65 REDIRECT_APPEND 68 REDIRECT_APPEND
66}; 69};
70#endif
67 71
68static const unsigned int DEFAULT_CONTEXT=0x1; 72static const unsigned int DEFAULT_CONTEXT=0x1;
69static const unsigned int IF_TRUE_CONTEXT=0x2; 73static const unsigned int IF_TRUE_CONTEXT=0x2;
@@ -71,25 +75,28 @@ static const unsigned int IF_FALSE_CONTEXT=0x4;
71static const unsigned int THEN_EXP_CONTEXT=0x8; 75static const unsigned int THEN_EXP_CONTEXT=0x8;
72static const unsigned int ELSE_EXP_CONTEXT=0x10; 76static const unsigned int ELSE_EXP_CONTEXT=0x10;
73 77
74 78#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
75struct jobset {
76 struct job *head; /* head of list of running jobs */
77 struct job *fg; /* current foreground job */
78};
79
80struct redir_struct { 79struct redir_struct {
81 enum redir_type type; /* type of redirection */ 80 enum redir_type type; /* type of redirection */
82 int fd; /* file descriptor being redirected */ 81 int fd; /* file descriptor being redirected */
83 char *filename; /* file to redirect fd to */ 82 char *filename; /* file to redirect fd to */
84}; 83};
84#endif
85 85
86struct child_prog { 86struct child_prog {
87 pid_t pid; /* 0 if exited */ 87 pid_t pid; /* 0 if exited */
88 char **argv; /* program name and arguments */ 88 char **argv; /* program name and arguments */
89 int num_redirects; /* elements in redirection array */ 89 int num_redirects; /* elements in redirection array */
90 struct redir_struct *redirects; /* I/O redirects */
91 int is_stopped; /* is the program currently running? */ 90 int is_stopped; /* is the program currently running? */
92 struct job *family; /* pointer back to the child's parent job */ 91 struct job *family; /* pointer back to the child's parent job */
92#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
93 struct redir_struct *redirects; /* I/O redirects */
94#endif
95};
96
97struct jobset {
98 struct job *head; /* head of list of running jobs */
99 struct job *fg; /* current foreground job */
93}; 100};
94 101
95struct job { 102struct job {
@@ -514,8 +521,10 @@ static void free_job(struct job *cmd)
514 521
515 for (i = 0; i < cmd->num_progs; i++) { 522 for (i = 0; i < cmd->num_progs; i++) {
516 free(cmd->progs[i].argv); 523 free(cmd->progs[i].argv);
524#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
517 if (cmd->progs[i].redirects) 525 if (cmd->progs[i].redirects)
518 free(cmd->progs[i].redirects); 526 free(cmd->progs[i].redirects);
527#endif
519 } 528 }
520 free(cmd->progs); 529 free(cmd->progs);
521 free(cmd->text); 530 free(cmd->text);
@@ -548,7 +557,7 @@ static void remove_job(struct jobset *j_list, struct job *job)
548 free(job); 557 free(job);
549} 558}
550 559
551/* Checks to see if any background processes have exited -- if they 560/* Checks to see if any background processes have exited -- if they
552 have, figure out why and see if a job has completed */ 561 have, figure out why and see if a job has completed */
553static void checkjobs(struct jobset *j_list) 562static void checkjobs(struct jobset *j_list)
554{ 563{
@@ -593,7 +602,7 @@ static void checkjobs(struct jobset *j_list)
593 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped", 602 printf(JOB_STATUS_FORMAT, job->jobid, "Stopped",
594 job->text); 603 job->text);
595 } 604 }
596#endif 605#endif
597 } 606 }
598 } 607 }
599 608
@@ -601,6 +610,7 @@ static void checkjobs(struct jobset *j_list)
601 bb_perror_msg("waitpid"); 610 bb_perror_msg("waitpid");
602} 611}
603 612
613#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
604/* squirrel != NULL means we squirrel away copies of stdin, stdout, 614/* squirrel != NULL means we squirrel away copies of stdin, stdout,
605 * and stderr if they are redirected. */ 615 * and stderr if they are redirected. */
606static int setup_redirects(struct child_prog *prog, int squirrel[]) 616static int setup_redirects(struct child_prog *prog, int squirrel[])
@@ -656,6 +666,15 @@ static void restore_redirects(int squirrel[])
656 } 666 }
657 } 667 }
658} 668}
669#else
670static inline int setup_redirects(struct child_prog *prog, int squirrel[])
671{
672 return 0;
673}
674static inline void restore_redirects(int squirrel[])
675{
676}
677#endif
659 678
660static inline void cmdedit_set_initial_prompt(void) 679static inline void cmdedit_set_initial_prompt(void)
661{ 680{
@@ -665,7 +684,7 @@ static inline void cmdedit_set_initial_prompt(void)
665 PS1 = getenv("PS1"); 684 PS1 = getenv("PS1");
666 if(PS1==0) 685 if(PS1==0)
667 PS1 = "\\w \\$ "; 686 PS1 = "\\w \\$ ";
668#endif 687#endif
669} 688}
670 689
671static inline void setup_prompt_string(char **prompt_str) 690static inline void setup_prompt_string(char **prompt_str)
@@ -682,7 +701,7 @@ static inline void setup_prompt_string(char **prompt_str)
682 } 701 }
683#else 702#else
684 *prompt_str = (shell_context==0)? PS1 : PS2; 703 *prompt_str = (shell_context==0)? PS1 : PS2;
685#endif 704#endif
686} 705}
687 706
688static int get_command(FILE * source, char *command) 707static int get_command(FILE * source, char *command)
@@ -761,7 +780,7 @@ char * strsep_space( char *string, int * ix)
761 (*ix)++; 780 (*ix)++;
762 } 781 }
763 782
764 /* Find the end of any whitespace trailing behind 783 /* Find the end of any whitespace trailing behind
765 * the token and let that be part of the token */ 784 * the token and let that be part of the token */
766 while( string && string[*ix] && isspace(string[*ix]) ) { 785 while( string && string[*ix] && isspace(string[*ix]) ) {
767 (*ix)++; 786 (*ix)++;
@@ -774,7 +793,7 @@ char * strsep_space( char *string, int * ix)
774 793
775 token = xmalloc(*ix+1); 794 token = xmalloc(*ix+1);
776 token[*ix] = '\0'; 795 token[*ix] = '\0';
777 strncpy(token, string, *ix); 796 strncpy(token, string, *ix);
778 797
779 return token; 798 return token;
780} 799}
@@ -789,10 +808,10 @@ static int expand_arguments(char *command)
789 int flags = GLOB_NOCHECK 808 int flags = GLOB_NOCHECK
790#ifdef GLOB_BRACE 809#ifdef GLOB_BRACE
791 | GLOB_BRACE 810 | GLOB_BRACE
792#endif 811#endif
793#ifdef GLOB_TILDE 812#ifdef GLOB_TILDE
794 | GLOB_TILDE 813 | GLOB_TILDE
795#endif 814#endif
796 ; 815 ;
797 816
798 /* get rid of the terminating \n */ 817 /* get rid of the terminating \n */
@@ -817,7 +836,7 @@ static int expand_arguments(char *command)
817 * we write stuff into the original (in a minute) */ 836 * we write stuff into the original (in a minute) */
818 cmd = cmd_copy = bb_xstrdup(command); 837 cmd = cmd_copy = bb_xstrdup(command);
819 *command = '\0'; 838 *command = '\0';
820 for (ix = 0, tmpcmd = cmd; 839 for (ix = 0, tmpcmd = cmd;
821 (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) { 840 (tmpcmd = strsep_space(cmd, &ix)) != NULL; cmd += ix, ix=0) {
822 if (*tmpcmd == '\0') 841 if (*tmpcmd == '\0')
823 break; 842 break;
@@ -832,7 +851,7 @@ static int expand_arguments(char *command)
832 return FALSE; 851 return FALSE;
833 } else if (retval != 0) { 852 } else if (retval != 0) {
834 /* Some other error. GLOB_NOMATCH shouldn't 853 /* Some other error. GLOB_NOMATCH shouldn't
835 * happen because of the GLOB_NOCHECK flag in 854 * happen because of the GLOB_NOCHECK flag in
836 * the glob call. */ 855 * the glob call. */
837 bb_error_msg("syntax error"); 856 bb_error_msg("syntax error");
838 return FALSE; 857 return FALSE;
@@ -856,7 +875,7 @@ static int expand_arguments(char *command)
856 free(cmd_copy); 875 free(cmd_copy);
857 trim(command); 876 trim(command);
858 877
859 /* Now do the shell variable substitutions which 878 /* Now do the shell variable substitutions which
860 * wordexp can't do for us, namely $? and $! */ 879 * wordexp can't do for us, namely $? and $! */
861 src = command; 880 src = command;
862 while((dst = strchr(src,'$')) != NULL){ 881 while((dst = strchr(src,'$')) != NULL){
@@ -946,21 +965,25 @@ static int expand_arguments(char *command)
946 965
947/* Return cmd->num_progs as 0 if no command is present (e.g. an empty 966/* Return cmd->num_progs as 0 if no command is present (e.g. an empty
948 line). If a valid command is found, command_ptr is set to point to 967 line). If a valid command is found, command_ptr is set to point to
949 the beginning of the next command (if the original command had more 968 the beginning of the next command (if the original command had more
950 then one job associated with it) or NULL if no more commands are 969 then one job associated with it) or NULL if no more commands are
951 present. */ 970 present. */
952static int parse_command(char **command_ptr, struct job *job, int *inbg) 971static int parse_command(char **command_ptr, struct job *job, int *inbg)
953{ 972{
954 char *command; 973 char *command;
955 char *return_command = NULL; 974 char *return_command = NULL;
956 char *src, *buf, *chptr; 975 char *src, *buf;
957 int argc_l = 0; 976 int argc_l = 0;
958 int done = 0; 977 int done = 0;
959 int argv_alloced; 978 int argv_alloced;
960 int i, saw_quote = 0; 979 int saw_quote = 0;
961 char quote = '\0'; 980 char quote = '\0';
962 int count; 981 int count;
963 struct child_prog *prog; 982 struct child_prog *prog;
983#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
984 int i;
985 char *chptr;
986#endif
964 987
965 /* skip leading white space */ 988 /* skip leading white space */
966 while (**command_ptr && isspace(**command_ptr)) 989 while (**command_ptr && isspace(**command_ptr))
@@ -976,21 +999,23 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
976 job->num_progs = 1; 999 job->num_progs = 1;
977 job->progs = xmalloc(sizeof(*job->progs)); 1000 job->progs = xmalloc(sizeof(*job->progs));
978 1001
979 /* We set the argv elements to point inside of this string. The 1002 /* We set the argv elements to point inside of this string. The
980 memory is freed by free_job(). Allocate twice the original 1003 memory is freed by free_job(). Allocate twice the original
981 length in case we need to quote every single character. 1004 length in case we need to quote every single character.
982 1005
983 Getting clean memory relieves us of the task of NULL 1006 Getting clean memory relieves us of the task of NULL
984 terminating things and makes the rest of this look a bit 1007 terminating things and makes the rest of this look a bit
985 cleaner (though it is, admittedly, a tad less efficient) */ 1008 cleaner (though it is, admittedly, a tad less efficient) */
986 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char)); 1009 job->cmdbuf = command = xcalloc(2*strlen(*command_ptr) + 1, sizeof(char));
987 job->text = NULL; 1010 job->text = NULL;
988 1011
989 prog = job->progs; 1012 prog = job->progs;
990 prog->num_redirects = 0; 1013 prog->num_redirects = 0;
991 prog->redirects = NULL;
992 prog->is_stopped = 0; 1014 prog->is_stopped = 0;
993 prog->family = job; 1015 prog->family = job;
1016#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
1017 prog->redirects = NULL;
1018#endif
994 1019
995 argv_alloced = 5; 1020 argv_alloced = 5;
996 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced); 1021 prog->argv = xmalloc(sizeof(*prog->argv) * argv_alloced);
@@ -1046,6 +1071,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
1046 done = 1; 1071 done = 1;
1047 break; 1072 break;
1048 1073
1074#ifdef CONFIG_LASH_PIPE_N_REDIRECTS
1049 case '>': /* redirects */ 1075 case '>': /* redirects */
1050 case '<': 1076 case '<':
1051 i = prog->num_redirects++; 1077 i = prog->num_redirects++;
@@ -1143,6 +1169,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
1143 src--; /* we'll ++ it at the end of the loop */ 1169 src--; /* we'll ++ it at the end of the loop */
1144 1170
1145 break; 1171 break;
1172#endif
1146 1173
1147 case '&': /* background */ 1174 case '&': /* background */
1148 *inbg = 1; 1175 *inbg = 1;
@@ -1189,7 +1216,7 @@ static int parse_command(char **command_ptr, struct job *job, int *inbg)
1189 } 1216 }
1190 1217
1191 *command_ptr = return_command; 1218 *command_ptr = return_command;
1192 1219
1193 return 0; 1220 return 0;
1194} 1221}
1195 1222
@@ -1236,7 +1263,7 @@ static int pseudo_exec(struct child_prog *child)
1236 1263
1237#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN 1264#ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
1238 /* If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN, then 1265 /* If you enable CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN, then
1239 * if you run /bin/cat, it will use BusyBox cat even if 1266 * if you run /bin/cat, it will use BusyBox cat even if
1240 * /bin/cat exists on the filesystem and is _not_ busybox. 1267 * /bin/cat exists on the filesystem and is _not_ busybox.
1241 * Some systems want this, others do not. Choose wisely. :-) 1268 * Some systems want this, others do not. Choose wisely. :-)
1242 */ 1269 */
@@ -1254,7 +1281,7 @@ static int pseudo_exec(struct child_prog *child)
1254 1281
1255 execvp(child->argv[0], child->argv); 1282 execvp(child->argv[0], child->argv);
1256 1283
1257 /* Do not use bb_perror_msg_and_die() here, since we must not 1284 /* Do not use bb_perror_msg_and_die() here, since we must not
1258 * call exit() but should call _exit() instead */ 1285 * call exit() but should call _exit() instead */
1259 fprintf(stderr, "%s: %m\n", child->argv[0]); 1286 fprintf(stderr, "%s: %m\n", child->argv[0]);
1260 _exit(EXIT_FAILURE); 1287 _exit(EXIT_FAILURE);
@@ -1286,7 +1313,7 @@ static void insert_job(struct job *newjob, int inbg)
1286 thejob->stopped_progs = 0; 1313 thejob->stopped_progs = 0;
1287 1314
1288 if (inbg) { 1315 if (inbg) {
1289 /* we don't wait for background thejobs to return -- append it 1316 /* we don't wait for background thejobs to return -- append it
1290 to the list of backgrounded thejobs and leave it alone */ 1317 to the list of backgrounded thejobs and leave it alone */
1291 printf("[%d] %d\n", thejob->jobid, 1318 printf("[%d] %d\n", thejob->jobid,
1292 newjob->progs[newjob->num_progs - 1].pid); 1319 newjob->progs[newjob->num_progs - 1].pid);
@@ -1336,8 +1363,8 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
1336 if (newjob->num_progs == 1) { 1363 if (newjob->num_progs == 1) {
1337 for (x = bltins; x->cmd; x++) { 1364 for (x = bltins; x->cmd; x++) {
1338 if (strcmp(child->argv[0], x->cmd) == 0 ) { 1365 if (strcmp(child->argv[0], x->cmd) == 0 ) {
1339 int squirrel[] = {-1, -1, -1};
1340 int rcode; 1366 int rcode;
1367 int squirrel[] = {-1, -1, -1};
1341 setup_redirects(child, squirrel); 1368 setup_redirects(child, squirrel);
1342 rcode = x->function(child); 1369 rcode = x->function(child);
1343 restore_redirects(squirrel); 1370 restore_redirects(squirrel);
@@ -1347,9 +1374,9 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
1347 } 1374 }
1348 1375
1349#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__) 1376#if !defined(__UCLIBC__) || defined(__UCLIBC_HAS_MMU__)
1350 if (!(child->pid = fork())) 1377 if (!(child->pid = fork()))
1351#else 1378#else
1352 if (!(child->pid = vfork())) 1379 if (!(child->pid = vfork()))
1353#endif 1380#endif
1354 { 1381 {
1355 /* Set the handling for job control signals back to the default. */ 1382 /* Set the handling for job control signals back to the default. */
@@ -1394,7 +1421,7 @@ static int run_command(struct job *newjob, int inbg, int outpipe[2])
1394 if (nextout != 1) 1421 if (nextout != 1)
1395 close(nextout); 1422 close(nextout);
1396 1423
1397 /* If there isn't another process, nextin is garbage 1424 /* If there isn't another process, nextin is garbage
1398 but it doesn't matter */ 1425 but it doesn't matter */
1399 nextin = pipefds[0]; 1426 nextin = pipefds[0];
1400 } 1427 }
@@ -1446,7 +1473,7 @@ static int busy_loop(FILE * input)
1446 if (!parse_command(&next_command, &newjob, &inbg) && 1473 if (!parse_command(&next_command, &newjob, &inbg) &&
1447 newjob.num_progs) { 1474 newjob.num_progs) {
1448 int pipefds[2] = {-1,-1}; 1475 int pipefds[2] = {-1,-1};
1449 debug_printf( "job=%p fed to run_command by busy_loop()'\n", 1476 debug_printf( "job=%p fed to run_command by busy_loop()'\n",
1450 &newjob); 1477 &newjob);
1451 run_command(&newjob, inbg, pipefds); 1478 run_command(&newjob, inbg, pipefds);
1452 } 1479 }
@@ -1495,7 +1522,7 @@ static int busy_loop(FILE * input)
1495 /* move the shell to the foreground */ 1522 /* move the shell to the foreground */
1496 /* suppress messages when run from /linuxrc mag@sysgo.de */ 1523 /* suppress messages when run from /linuxrc mag@sysgo.de */
1497 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY) 1524 if (tcsetpgrp(shell_terminal, getpgrp()) && errno != ENOTTY)
1498 bb_perror_msg("tcsetpgrp"); 1525 bb_perror_msg("tcsetpgrp");
1499 } 1526 }
1500 } 1527 }
1501 } 1528 }
@@ -1508,7 +1535,7 @@ static int busy_loop(FILE * input)
1508 /* return exit status if called with "-c" */ 1535 /* return exit status if called with "-c" */
1509 if (input == NULL && WIFEXITED(status)) 1536 if (input == NULL && WIFEXITED(status))
1510 return WEXITSTATUS(status); 1537 return WEXITSTATUS(status);
1511 1538
1512 return 0; 1539 return 0;
1513} 1540}
1514 1541
@@ -1534,7 +1561,7 @@ void free_memory(void)
1534static void setup_job_control(void) 1561static void setup_job_control(void)
1535{ 1562{
1536 int status; 1563 int status;
1537 1564
1538 /* Loop until we are in the foreground. */ 1565 /* Loop until we are in the foreground. */
1539 while ((status = tcgetpgrp (shell_terminal)) >= 0) { 1566 while ((status = tcgetpgrp (shell_terminal)) >= 0) {
1540 if (status == (shell_pgrp = getpgrp ())) { 1567 if (status == (shell_pgrp = getpgrp ())) {
@@ -1580,7 +1607,7 @@ int lash_main(int argc_l, char **argv_l)
1580 prof_input = fopen("/etc/profile", "r"); 1607 prof_input = fopen("/etc/profile", "r");
1581 if (prof_input) { 1608 if (prof_input) {
1582 int tmp_fd = fileno(prof_input); 1609 int tmp_fd = fileno(prof_input);
1583 mark_open(tmp_fd); 1610 mark_open(tmp_fd);
1584 /* Now run the file */ 1611 /* Now run the file */
1585 busy_loop(prof_input); 1612 busy_loop(prof_input);
1586 fclose(prof_input); 1613 fclose(prof_input);
@@ -1644,6 +1671,6 @@ int lash_main(int argc_l, char **argv_l)
1644#else 1671#else
1645 PS1 = NULL; 1672 PS1 = NULL;
1646#endif 1673#endif
1647 1674
1648 return (busy_loop(input)); 1675 return (busy_loop(input));
1649} 1676}