diff options
author | Eric Andersen <andersen@codepoet.org> | 2000-07-18 08:16:39 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2000-07-18 08:16:39 +0000 |
commit | 6efc48c1aebfc7bebd05c6f9c21cc0f9014abbd0 (patch) | |
tree | 2bf45b0b615aeead7d14492a43e46b66de64cd90 | |
parent | 9c5fcc3408626c46bc5187554e950b981143bb38 (diff) | |
download | busybox-w32-6efc48c1aebfc7bebd05c6f9c21cc0f9014abbd0.tar.gz busybox-w32-6efc48c1aebfc7bebd05c6f9c21cc0f9014abbd0.tar.bz2 busybox-w32-6efc48c1aebfc7bebd05c6f9c21cc0f9014abbd0.zip |
Sigh -- can't sleep. Clean up some mem leaks, fixed some bugs.
-Erik
-rw-r--r-- | lash.c | 82 | ||||
-rw-r--r-- | sh.c | 82 | ||||
-rw-r--r-- | shell/lash.c | 82 |
3 files changed, 129 insertions, 117 deletions
@@ -46,10 +46,7 @@ | |||
46 | #include "cmdedit.h" | 46 | #include "cmdedit.h" |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define bb_need_full_version | 49 | #define MAX_LINE 256 /* size of input buffer for `read' builtin */ |
50 | #define BB_DECLARE_EXTERN | ||
51 | #include "messages.c" | ||
52 | |||
53 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ | 50 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ |
54 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" | 51 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" |
55 | 52 | ||
@@ -147,7 +144,7 @@ static struct builtInCommand bltins_forking[] = { | |||
147 | }; | 144 | }; |
148 | 145 | ||
149 | static char *prompt = "# "; | 146 | static char *prompt = "# "; |
150 | static char *cwd = NULL; | 147 | static char *cwd; |
151 | static char *local_pending_command = NULL; | 148 | static char *local_pending_command = NULL; |
152 | 149 | ||
153 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 150 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
@@ -175,7 +172,7 @@ static int builtin_cd(struct job *cmd, struct jobSet *junk) | |||
175 | printf("cd: %s: %s\n", newdir, strerror(errno)); | 172 | printf("cd: %s: %s\n", newdir, strerror(errno)); |
176 | return FALSE; | 173 | return FALSE; |
177 | } | 174 | } |
178 | getcwd(cwd, sizeof(cwd)); | 175 | getcwd(cwd, sizeof(char)*MAX_LINE); |
179 | 176 | ||
180 | return TRUE; | 177 | return TRUE; |
181 | } | 178 | } |
@@ -289,7 +286,7 @@ static int builtin_jobs(struct job *dummy, struct jobSet *jobList) | |||
289 | /* built-in 'pwd' handler */ | 286 | /* built-in 'pwd' handler */ |
290 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) | 287 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) |
291 | { | 288 | { |
292 | getcwd(cwd, sizeof(cwd)); | 289 | getcwd(cwd, sizeof(char)*MAX_LINE); |
293 | fprintf(stdout, "%s\n", cwd); | 290 | fprintf(stdout, "%s\n", cwd); |
294 | return TRUE; | 291 | return TRUE; |
295 | } | 292 | } |
@@ -780,13 +777,8 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
780 | return 1; | 777 | return 1; |
781 | } | 778 | } |
782 | 779 | ||
783 | /* Make a copy of any stuff left over in the command | ||
784 | * line after the second backtick */ | ||
785 | charptr2 = xmalloc(strlen(ptr)+1); | ||
786 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
787 | |||
788 | /* Make some space to hold just the backticked command */ | 780 | /* Make some space to hold just the backticked command */ |
789 | charptr1 = xmalloc(1+ptr-src); | 781 | charptr1 = charptr2 = xmalloc(1+ptr-src); |
790 | snprintf(charptr1, 1+ptr-src, src); | 782 | snprintf(charptr1, 1+ptr-src, src); |
791 | newJob = xmalloc(sizeof(struct job)); | 783 | newJob = xmalloc(sizeof(struct job)); |
792 | /* Now parse and run the backticked command */ | 784 | /* Now parse and run the backticked command */ |
@@ -796,7 +788,14 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
796 | runCommand(newJob, &njobList, 0, pipefd); | 788 | runCommand(newJob, &njobList, 0, pipefd); |
797 | } | 789 | } |
798 | checkJobs(jobList); | 790 | checkJobs(jobList); |
799 | free(charptr1); | 791 | freeJob(newJob); |
792 | free(charptr2); | ||
793 | |||
794 | /* Make a copy of any stuff left over in the command | ||
795 | * line after the second backtick */ | ||
796 | charptr2 = xmalloc(strlen(ptr)+1); | ||
797 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
798 | |||
800 | 799 | ||
801 | /* Copy the output from the backtick-ed command into the | 800 | /* Copy the output from the backtick-ed command into the |
802 | * command line, making extra room as needed */ | 801 | * command line, making extra room as needed */ |
@@ -819,13 +818,12 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
819 | /* Now paste into the *commandPtr all the stuff | 818 | /* Now paste into the *commandPtr all the stuff |
820 | * leftover after the second backtick */ | 819 | * leftover after the second backtick */ |
821 | memcpy(src, charptr2, strlen(charptr2)); | 820 | memcpy(src, charptr2, strlen(charptr2)); |
822 | fprintf(stderr,"*commandPtr='%s'\n", *commandPtr); | ||
823 | free(charptr2); | 821 | free(charptr2); |
824 | 822 | ||
825 | |||
826 | /* Now recursively call parseCommand to deal with the new | 823 | /* Now recursively call parseCommand to deal with the new |
827 | * and improved version of the command line with the backtick | 824 | * and improved version of the command line with the backtick |
828 | * results expanded in place... */ | 825 | * results expanded in place... */ |
826 | freeJob(job); | ||
829 | return(parseCommand(commandPtr, job, jobList, isBg)); | 827 | return(parseCommand(commandPtr, job, jobList, isBg)); |
830 | } | 828 | } |
831 | break; | 829 | break; |
@@ -863,24 +861,29 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
863 | return 0; | 861 | return 0; |
864 | } | 862 | } |
865 | 863 | ||
866 | |||
867 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) | 864 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) |
868 | { | 865 | { |
869 | struct job *job; | 866 | struct job *job; |
870 | int nextin=0, nextout, stdoutfd=fileno(stdout); | ||
871 | int i; | 867 | int i; |
868 | int nextin, nextout; | ||
872 | int pipefds[2]; /* pipefd[0] is for reading */ | 869 | int pipefds[2]; /* pipefd[0] is for reading */ |
873 | struct builtInCommand *x; | 870 | struct builtInCommand *x; |
874 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
875 | const struct BB_applet *a = applets; | 872 | const struct BB_applet *a = applets; |
876 | #endif | 873 | #endif |
877 | 874 | ||
875 | |||
876 | nextin = 0, nextout = 1; | ||
878 | for (i = 0; i < newJob->numProgs; i++) { | 877 | for (i = 0; i < newJob->numProgs; i++) { |
879 | if ((i + 1) < newJob->numProgs) { | 878 | if ((i + 1) < newJob->numProgs) { |
880 | pipe(pipefds); | 879 | pipe(pipefds); |
881 | nextout = pipefds[1]; | 880 | nextout = pipefds[1]; |
882 | } else { | 881 | } else { |
883 | nextout = stdoutfd; | 882 | if (outPipe[1]!=-1) { |
883 | nextout = outPipe[1]; | ||
884 | } else { | ||
885 | nextout = 1; | ||
886 | } | ||
884 | } | 887 | } |
885 | 888 | ||
886 | /* Check if the command matches any non-forking builtins */ | 889 | /* Check if the command matches any non-forking builtins */ |
@@ -895,15 +898,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
895 | 898 | ||
896 | if (outPipe[1]!=-1) { | 899 | if (outPipe[1]!=-1) { |
897 | close(outPipe[0]); | 900 | close(outPipe[0]); |
898 | nextout = stdoutfd = outPipe[1]; | 901 | } |
902 | if (nextin != 0) { | ||
903 | dup2(nextin, 0); | ||
904 | close(nextin); | ||
905 | } | ||
906 | |||
907 | if (nextout != 1) { | ||
899 | dup2(nextout, 1); | 908 | dup2(nextout, 1); |
900 | dup2(nextout, 2); | 909 | dup2(nextout, 2); |
901 | close(nextout); | 910 | close(nextout); |
902 | } | 911 | } |
903 | 912 | ||
904 | //dup2(nextin, 0); | ||
905 | //close(nextin); | ||
906 | |||
907 | /* explicit redirections override pipes */ | 913 | /* explicit redirections override pipes */ |
908 | setupRedirections(newJob->progs + i); | 914 | setupRedirections(newJob->progs + i); |
909 | 915 | ||
@@ -915,8 +921,8 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
915 | } | 921 | } |
916 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 922 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
917 | /* Check if the command matches any busybox internal commands here */ | 923 | /* Check if the command matches any busybox internal commands here */ |
918 | /* TODO: Add matching on commands with paths appended (i.e. 'cat' | 924 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
919 | * currently works, but '/bin/cat' doesn't ) */ | 925 | * works, but '/bin/cat' doesn't ) */ |
920 | while (a->name != 0) { | 926 | while (a->name != 0) { |
921 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { | 927 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
922 | int argc; | 928 | int argc; |
@@ -929,20 +935,19 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
929 | #endif | 935 | #endif |
930 | 936 | ||
931 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); | 937 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
932 | fatalError("%s: %s\n", newJob->progs[i].argv[0], | 938 | fatalError("sh: %s: %s\n", newJob->progs[i].argv[0], |
933 | strerror(errno)); | 939 | strerror(errno)); |
934 | } | 940 | } |
935 | if (outPipe[1]!=-1) { | 941 | if (outPipe[1]!=-1) { |
936 | close(outPipe[1]); | 942 | close(outPipe[1]); |
937 | } | 943 | } |
938 | 944 | ||
939 | /* put our child in the process group whose leader is the | 945 | /* put our child in the process group whose leader is the |
940 | first process in this pipe */ | 946 | first process in this pipe */ |
941 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); | 947 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
942 | |||
943 | if (nextin != 0) | 948 | if (nextin != 0) |
944 | close(nextin); | 949 | close(nextin); |
945 | if (nextout != stdoutfd) | 950 | if (nextout != 1) |
946 | close(nextout); | 951 | close(nextout); |
947 | 952 | ||
948 | /* If there isn't another process, nextin is garbage | 953 | /* If there isn't another process, nextin is garbage |
@@ -960,10 +965,10 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
960 | 965 | ||
961 | /* add the job to the list of running jobs */ | 966 | /* add the job to the list of running jobs */ |
962 | if (!jobList->head) { | 967 | if (!jobList->head) { |
963 | job = jobList->head = xmalloc(sizeof(*job)); | 968 | job = jobList->head = malloc(sizeof(*job)); |
964 | } else { | 969 | } else { |
965 | for (job = jobList->head; job->next; job = job->next); | 970 | for (job = jobList->head; job->next; job = job->next); |
966 | job->next = xmalloc(sizeof(*job)); | 971 | job->next = malloc(sizeof(*job)); |
967 | job = job->next; | 972 | job = job->next; |
968 | } | 973 | } |
969 | 974 | ||
@@ -1066,9 +1071,9 @@ static int busy_loop(FILE * input) | |||
1066 | int pipefds[2] = {-1,-1}; | 1071 | int pipefds[2] = {-1,-1}; |
1067 | runCommand(&newJob, &jobList, inBg, pipefds); | 1072 | runCommand(&newJob, &jobList, inBg, pipefds); |
1068 | } else { | 1073 | } else { |
1069 | nextCommand=NULL; | ||
1070 | free(command); | 1074 | free(command); |
1071 | command = (char *) calloc(BUFSIZ, sizeof(char)); | 1075 | command = (char *) calloc(BUFSIZ, sizeof(char)); |
1076 | nextCommand = NULL; | ||
1072 | } | 1077 | } |
1073 | } else { | 1078 | } else { |
1074 | /* a job is running in the foreground; wait for it */ | 1079 | /* a job is running in the foreground; wait for it */ |
@@ -1123,16 +1128,14 @@ static int busy_loop(FILE * input) | |||
1123 | } | 1128 | } |
1124 | 1129 | ||
1125 | 1130 | ||
1131 | |||
1126 | int shell_main(int argc, char **argv) | 1132 | int shell_main(int argc, char **argv) |
1127 | { | 1133 | { |
1128 | FILE *input = stdin; | 1134 | FILE *input = stdin; |
1129 | 1135 | ||
1130 | /* initialize the cwd */ | 1136 | /* initialize the cwd -- this is never freed...*/ |
1131 | cwd = (char *) calloc(BUFSIZ, sizeof(char)); | 1137 | cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); |
1132 | if (cwd == 0) { | 1138 | getcwd(cwd, sizeof(char)*MAX_LINE); |
1133 | fatalError("out of memory\n"); | ||
1134 | } | ||
1135 | getcwd(cwd, sizeof(char)*BUFSIZ); | ||
1136 | 1139 | ||
1137 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 1140 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
1138 | cmdedit_init(); | 1141 | cmdedit_init(); |
@@ -1144,8 +1147,9 @@ int shell_main(int argc, char **argv) | |||
1144 | // builtin_source("/etc/profile"); | 1147 | // builtin_source("/etc/profile"); |
1145 | //} | 1148 | //} |
1146 | 1149 | ||
1150 | |||
1147 | if (argc < 2) { | 1151 | if (argc < 2) { |
1148 | fprintf(stdout, "\n\n%s Built-in shell\n", full_version); | 1152 | fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT); |
1149 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); | 1153 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); |
1150 | } else { | 1154 | } else { |
1151 | if (argv[1][0]=='-' && argv[1][1]=='c') { | 1155 | if (argv[1][0]=='-' && argv[1][1]=='c') { |
@@ -46,10 +46,7 @@ | |||
46 | #include "cmdedit.h" | 46 | #include "cmdedit.h" |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define bb_need_full_version | 49 | #define MAX_LINE 256 /* size of input buffer for `read' builtin */ |
50 | #define BB_DECLARE_EXTERN | ||
51 | #include "messages.c" | ||
52 | |||
53 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ | 50 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ |
54 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" | 51 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" |
55 | 52 | ||
@@ -147,7 +144,7 @@ static struct builtInCommand bltins_forking[] = { | |||
147 | }; | 144 | }; |
148 | 145 | ||
149 | static char *prompt = "# "; | 146 | static char *prompt = "# "; |
150 | static char *cwd = NULL; | 147 | static char *cwd; |
151 | static char *local_pending_command = NULL; | 148 | static char *local_pending_command = NULL; |
152 | 149 | ||
153 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 150 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
@@ -175,7 +172,7 @@ static int builtin_cd(struct job *cmd, struct jobSet *junk) | |||
175 | printf("cd: %s: %s\n", newdir, strerror(errno)); | 172 | printf("cd: %s: %s\n", newdir, strerror(errno)); |
176 | return FALSE; | 173 | return FALSE; |
177 | } | 174 | } |
178 | getcwd(cwd, sizeof(cwd)); | 175 | getcwd(cwd, sizeof(char)*MAX_LINE); |
179 | 176 | ||
180 | return TRUE; | 177 | return TRUE; |
181 | } | 178 | } |
@@ -289,7 +286,7 @@ static int builtin_jobs(struct job *dummy, struct jobSet *jobList) | |||
289 | /* built-in 'pwd' handler */ | 286 | /* built-in 'pwd' handler */ |
290 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) | 287 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) |
291 | { | 288 | { |
292 | getcwd(cwd, sizeof(cwd)); | 289 | getcwd(cwd, sizeof(char)*MAX_LINE); |
293 | fprintf(stdout, "%s\n", cwd); | 290 | fprintf(stdout, "%s\n", cwd); |
294 | return TRUE; | 291 | return TRUE; |
295 | } | 292 | } |
@@ -780,13 +777,8 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
780 | return 1; | 777 | return 1; |
781 | } | 778 | } |
782 | 779 | ||
783 | /* Make a copy of any stuff left over in the command | ||
784 | * line after the second backtick */ | ||
785 | charptr2 = xmalloc(strlen(ptr)+1); | ||
786 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
787 | |||
788 | /* Make some space to hold just the backticked command */ | 780 | /* Make some space to hold just the backticked command */ |
789 | charptr1 = xmalloc(1+ptr-src); | 781 | charptr1 = charptr2 = xmalloc(1+ptr-src); |
790 | snprintf(charptr1, 1+ptr-src, src); | 782 | snprintf(charptr1, 1+ptr-src, src); |
791 | newJob = xmalloc(sizeof(struct job)); | 783 | newJob = xmalloc(sizeof(struct job)); |
792 | /* Now parse and run the backticked command */ | 784 | /* Now parse and run the backticked command */ |
@@ -796,7 +788,14 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
796 | runCommand(newJob, &njobList, 0, pipefd); | 788 | runCommand(newJob, &njobList, 0, pipefd); |
797 | } | 789 | } |
798 | checkJobs(jobList); | 790 | checkJobs(jobList); |
799 | free(charptr1); | 791 | freeJob(newJob); |
792 | free(charptr2); | ||
793 | |||
794 | /* Make a copy of any stuff left over in the command | ||
795 | * line after the second backtick */ | ||
796 | charptr2 = xmalloc(strlen(ptr)+1); | ||
797 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
798 | |||
800 | 799 | ||
801 | /* Copy the output from the backtick-ed command into the | 800 | /* Copy the output from the backtick-ed command into the |
802 | * command line, making extra room as needed */ | 801 | * command line, making extra room as needed */ |
@@ -819,13 +818,12 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
819 | /* Now paste into the *commandPtr all the stuff | 818 | /* Now paste into the *commandPtr all the stuff |
820 | * leftover after the second backtick */ | 819 | * leftover after the second backtick */ |
821 | memcpy(src, charptr2, strlen(charptr2)); | 820 | memcpy(src, charptr2, strlen(charptr2)); |
822 | fprintf(stderr,"*commandPtr='%s'\n", *commandPtr); | ||
823 | free(charptr2); | 821 | free(charptr2); |
824 | 822 | ||
825 | |||
826 | /* Now recursively call parseCommand to deal with the new | 823 | /* Now recursively call parseCommand to deal with the new |
827 | * and improved version of the command line with the backtick | 824 | * and improved version of the command line with the backtick |
828 | * results expanded in place... */ | 825 | * results expanded in place... */ |
826 | freeJob(job); | ||
829 | return(parseCommand(commandPtr, job, jobList, isBg)); | 827 | return(parseCommand(commandPtr, job, jobList, isBg)); |
830 | } | 828 | } |
831 | break; | 829 | break; |
@@ -863,24 +861,29 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
863 | return 0; | 861 | return 0; |
864 | } | 862 | } |
865 | 863 | ||
866 | |||
867 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) | 864 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) |
868 | { | 865 | { |
869 | struct job *job; | 866 | struct job *job; |
870 | int nextin=0, nextout, stdoutfd=fileno(stdout); | ||
871 | int i; | 867 | int i; |
868 | int nextin, nextout; | ||
872 | int pipefds[2]; /* pipefd[0] is for reading */ | 869 | int pipefds[2]; /* pipefd[0] is for reading */ |
873 | struct builtInCommand *x; | 870 | struct builtInCommand *x; |
874 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
875 | const struct BB_applet *a = applets; | 872 | const struct BB_applet *a = applets; |
876 | #endif | 873 | #endif |
877 | 874 | ||
875 | |||
876 | nextin = 0, nextout = 1; | ||
878 | for (i = 0; i < newJob->numProgs; i++) { | 877 | for (i = 0; i < newJob->numProgs; i++) { |
879 | if ((i + 1) < newJob->numProgs) { | 878 | if ((i + 1) < newJob->numProgs) { |
880 | pipe(pipefds); | 879 | pipe(pipefds); |
881 | nextout = pipefds[1]; | 880 | nextout = pipefds[1]; |
882 | } else { | 881 | } else { |
883 | nextout = stdoutfd; | 882 | if (outPipe[1]!=-1) { |
883 | nextout = outPipe[1]; | ||
884 | } else { | ||
885 | nextout = 1; | ||
886 | } | ||
884 | } | 887 | } |
885 | 888 | ||
886 | /* Check if the command matches any non-forking builtins */ | 889 | /* Check if the command matches any non-forking builtins */ |
@@ -895,15 +898,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
895 | 898 | ||
896 | if (outPipe[1]!=-1) { | 899 | if (outPipe[1]!=-1) { |
897 | close(outPipe[0]); | 900 | close(outPipe[0]); |
898 | nextout = stdoutfd = outPipe[1]; | 901 | } |
902 | if (nextin != 0) { | ||
903 | dup2(nextin, 0); | ||
904 | close(nextin); | ||
905 | } | ||
906 | |||
907 | if (nextout != 1) { | ||
899 | dup2(nextout, 1); | 908 | dup2(nextout, 1); |
900 | dup2(nextout, 2); | 909 | dup2(nextout, 2); |
901 | close(nextout); | 910 | close(nextout); |
902 | } | 911 | } |
903 | 912 | ||
904 | //dup2(nextin, 0); | ||
905 | //close(nextin); | ||
906 | |||
907 | /* explicit redirections override pipes */ | 913 | /* explicit redirections override pipes */ |
908 | setupRedirections(newJob->progs + i); | 914 | setupRedirections(newJob->progs + i); |
909 | 915 | ||
@@ -915,8 +921,8 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
915 | } | 921 | } |
916 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 922 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
917 | /* Check if the command matches any busybox internal commands here */ | 923 | /* Check if the command matches any busybox internal commands here */ |
918 | /* TODO: Add matching on commands with paths appended (i.e. 'cat' | 924 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
919 | * currently works, but '/bin/cat' doesn't ) */ | 925 | * works, but '/bin/cat' doesn't ) */ |
920 | while (a->name != 0) { | 926 | while (a->name != 0) { |
921 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { | 927 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
922 | int argc; | 928 | int argc; |
@@ -929,20 +935,19 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
929 | #endif | 935 | #endif |
930 | 936 | ||
931 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); | 937 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
932 | fatalError("%s: %s\n", newJob->progs[i].argv[0], | 938 | fatalError("sh: %s: %s\n", newJob->progs[i].argv[0], |
933 | strerror(errno)); | 939 | strerror(errno)); |
934 | } | 940 | } |
935 | if (outPipe[1]!=-1) { | 941 | if (outPipe[1]!=-1) { |
936 | close(outPipe[1]); | 942 | close(outPipe[1]); |
937 | } | 943 | } |
938 | 944 | ||
939 | /* put our child in the process group whose leader is the | 945 | /* put our child in the process group whose leader is the |
940 | first process in this pipe */ | 946 | first process in this pipe */ |
941 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); | 947 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
942 | |||
943 | if (nextin != 0) | 948 | if (nextin != 0) |
944 | close(nextin); | 949 | close(nextin); |
945 | if (nextout != stdoutfd) | 950 | if (nextout != 1) |
946 | close(nextout); | 951 | close(nextout); |
947 | 952 | ||
948 | /* If there isn't another process, nextin is garbage | 953 | /* If there isn't another process, nextin is garbage |
@@ -960,10 +965,10 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
960 | 965 | ||
961 | /* add the job to the list of running jobs */ | 966 | /* add the job to the list of running jobs */ |
962 | if (!jobList->head) { | 967 | if (!jobList->head) { |
963 | job = jobList->head = xmalloc(sizeof(*job)); | 968 | job = jobList->head = malloc(sizeof(*job)); |
964 | } else { | 969 | } else { |
965 | for (job = jobList->head; job->next; job = job->next); | 970 | for (job = jobList->head; job->next; job = job->next); |
966 | job->next = xmalloc(sizeof(*job)); | 971 | job->next = malloc(sizeof(*job)); |
967 | job = job->next; | 972 | job = job->next; |
968 | } | 973 | } |
969 | 974 | ||
@@ -1066,9 +1071,9 @@ static int busy_loop(FILE * input) | |||
1066 | int pipefds[2] = {-1,-1}; | 1071 | int pipefds[2] = {-1,-1}; |
1067 | runCommand(&newJob, &jobList, inBg, pipefds); | 1072 | runCommand(&newJob, &jobList, inBg, pipefds); |
1068 | } else { | 1073 | } else { |
1069 | nextCommand=NULL; | ||
1070 | free(command); | 1074 | free(command); |
1071 | command = (char *) calloc(BUFSIZ, sizeof(char)); | 1075 | command = (char *) calloc(BUFSIZ, sizeof(char)); |
1076 | nextCommand = NULL; | ||
1072 | } | 1077 | } |
1073 | } else { | 1078 | } else { |
1074 | /* a job is running in the foreground; wait for it */ | 1079 | /* a job is running in the foreground; wait for it */ |
@@ -1123,16 +1128,14 @@ static int busy_loop(FILE * input) | |||
1123 | } | 1128 | } |
1124 | 1129 | ||
1125 | 1130 | ||
1131 | |||
1126 | int shell_main(int argc, char **argv) | 1132 | int shell_main(int argc, char **argv) |
1127 | { | 1133 | { |
1128 | FILE *input = stdin; | 1134 | FILE *input = stdin; |
1129 | 1135 | ||
1130 | /* initialize the cwd */ | 1136 | /* initialize the cwd -- this is never freed...*/ |
1131 | cwd = (char *) calloc(BUFSIZ, sizeof(char)); | 1137 | cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); |
1132 | if (cwd == 0) { | 1138 | getcwd(cwd, sizeof(char)*MAX_LINE); |
1133 | fatalError("out of memory\n"); | ||
1134 | } | ||
1135 | getcwd(cwd, sizeof(char)*BUFSIZ); | ||
1136 | 1139 | ||
1137 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 1140 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
1138 | cmdedit_init(); | 1141 | cmdedit_init(); |
@@ -1144,8 +1147,9 @@ int shell_main(int argc, char **argv) | |||
1144 | // builtin_source("/etc/profile"); | 1147 | // builtin_source("/etc/profile"); |
1145 | //} | 1148 | //} |
1146 | 1149 | ||
1150 | |||
1147 | if (argc < 2) { | 1151 | if (argc < 2) { |
1148 | fprintf(stdout, "\n\n%s Built-in shell\n", full_version); | 1152 | fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT); |
1149 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); | 1153 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); |
1150 | } else { | 1154 | } else { |
1151 | if (argv[1][0]=='-' && argv[1][1]=='c') { | 1155 | if (argv[1][0]=='-' && argv[1][1]=='c') { |
diff --git a/shell/lash.c b/shell/lash.c index c9ef39f49..6029eaa5c 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -46,10 +46,7 @@ | |||
46 | #include "cmdedit.h" | 46 | #include "cmdedit.h" |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define bb_need_full_version | 49 | #define MAX_LINE 256 /* size of input buffer for `read' builtin */ |
50 | #define BB_DECLARE_EXTERN | ||
51 | #include "messages.c" | ||
52 | |||
53 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ | 50 | #define MAX_READ 128 /* size of input buffer for `read' builtin */ |
54 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" | 51 | #define JOB_STATUS_FORMAT "[%d] %-22s %.40s\n" |
55 | 52 | ||
@@ -147,7 +144,7 @@ static struct builtInCommand bltins_forking[] = { | |||
147 | }; | 144 | }; |
148 | 145 | ||
149 | static char *prompt = "# "; | 146 | static char *prompt = "# "; |
150 | static char *cwd = NULL; | 147 | static char *cwd; |
151 | static char *local_pending_command = NULL; | 148 | static char *local_pending_command = NULL; |
152 | 149 | ||
153 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 150 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
@@ -175,7 +172,7 @@ static int builtin_cd(struct job *cmd, struct jobSet *junk) | |||
175 | printf("cd: %s: %s\n", newdir, strerror(errno)); | 172 | printf("cd: %s: %s\n", newdir, strerror(errno)); |
176 | return FALSE; | 173 | return FALSE; |
177 | } | 174 | } |
178 | getcwd(cwd, sizeof(cwd)); | 175 | getcwd(cwd, sizeof(char)*MAX_LINE); |
179 | 176 | ||
180 | return TRUE; | 177 | return TRUE; |
181 | } | 178 | } |
@@ -289,7 +286,7 @@ static int builtin_jobs(struct job *dummy, struct jobSet *jobList) | |||
289 | /* built-in 'pwd' handler */ | 286 | /* built-in 'pwd' handler */ |
290 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) | 287 | static int builtin_pwd(struct job *dummy, struct jobSet *junk) |
291 | { | 288 | { |
292 | getcwd(cwd, sizeof(cwd)); | 289 | getcwd(cwd, sizeof(char)*MAX_LINE); |
293 | fprintf(stdout, "%s\n", cwd); | 290 | fprintf(stdout, "%s\n", cwd); |
294 | return TRUE; | 291 | return TRUE; |
295 | } | 292 | } |
@@ -780,13 +777,8 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
780 | return 1; | 777 | return 1; |
781 | } | 778 | } |
782 | 779 | ||
783 | /* Make a copy of any stuff left over in the command | ||
784 | * line after the second backtick */ | ||
785 | charptr2 = xmalloc(strlen(ptr)+1); | ||
786 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
787 | |||
788 | /* Make some space to hold just the backticked command */ | 780 | /* Make some space to hold just the backticked command */ |
789 | charptr1 = xmalloc(1+ptr-src); | 781 | charptr1 = charptr2 = xmalloc(1+ptr-src); |
790 | snprintf(charptr1, 1+ptr-src, src); | 782 | snprintf(charptr1, 1+ptr-src, src); |
791 | newJob = xmalloc(sizeof(struct job)); | 783 | newJob = xmalloc(sizeof(struct job)); |
792 | /* Now parse and run the backticked command */ | 784 | /* Now parse and run the backticked command */ |
@@ -796,7 +788,14 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
796 | runCommand(newJob, &njobList, 0, pipefd); | 788 | runCommand(newJob, &njobList, 0, pipefd); |
797 | } | 789 | } |
798 | checkJobs(jobList); | 790 | checkJobs(jobList); |
799 | free(charptr1); | 791 | freeJob(newJob); |
792 | free(charptr2); | ||
793 | |||
794 | /* Make a copy of any stuff left over in the command | ||
795 | * line after the second backtick */ | ||
796 | charptr2 = xmalloc(strlen(ptr)+1); | ||
797 | memcpy(charptr2, ptr+1, strlen(ptr)); | ||
798 | |||
800 | 799 | ||
801 | /* Copy the output from the backtick-ed command into the | 800 | /* Copy the output from the backtick-ed command into the |
802 | * command line, making extra room as needed */ | 801 | * command line, making extra room as needed */ |
@@ -819,13 +818,12 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
819 | /* Now paste into the *commandPtr all the stuff | 818 | /* Now paste into the *commandPtr all the stuff |
820 | * leftover after the second backtick */ | 819 | * leftover after the second backtick */ |
821 | memcpy(src, charptr2, strlen(charptr2)); | 820 | memcpy(src, charptr2, strlen(charptr2)); |
822 | fprintf(stderr,"*commandPtr='%s'\n", *commandPtr); | ||
823 | free(charptr2); | 821 | free(charptr2); |
824 | 822 | ||
825 | |||
826 | /* Now recursively call parseCommand to deal with the new | 823 | /* Now recursively call parseCommand to deal with the new |
827 | * and improved version of the command line with the backtick | 824 | * and improved version of the command line with the backtick |
828 | * results expanded in place... */ | 825 | * results expanded in place... */ |
826 | freeJob(job); | ||
829 | return(parseCommand(commandPtr, job, jobList, isBg)); | 827 | return(parseCommand(commandPtr, job, jobList, isBg)); |
830 | } | 828 | } |
831 | break; | 829 | break; |
@@ -863,24 +861,29 @@ static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobLi | |||
863 | return 0; | 861 | return 0; |
864 | } | 862 | } |
865 | 863 | ||
866 | |||
867 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) | 864 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int outPipe[2]) |
868 | { | 865 | { |
869 | struct job *job; | 866 | struct job *job; |
870 | int nextin=0, nextout, stdoutfd=fileno(stdout); | ||
871 | int i; | 867 | int i; |
868 | int nextin, nextout; | ||
872 | int pipefds[2]; /* pipefd[0] is for reading */ | 869 | int pipefds[2]; /* pipefd[0] is for reading */ |
873 | struct builtInCommand *x; | 870 | struct builtInCommand *x; |
874 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
875 | const struct BB_applet *a = applets; | 872 | const struct BB_applet *a = applets; |
876 | #endif | 873 | #endif |
877 | 874 | ||
875 | |||
876 | nextin = 0, nextout = 1; | ||
878 | for (i = 0; i < newJob->numProgs; i++) { | 877 | for (i = 0; i < newJob->numProgs; i++) { |
879 | if ((i + 1) < newJob->numProgs) { | 878 | if ((i + 1) < newJob->numProgs) { |
880 | pipe(pipefds); | 879 | pipe(pipefds); |
881 | nextout = pipefds[1]; | 880 | nextout = pipefds[1]; |
882 | } else { | 881 | } else { |
883 | nextout = stdoutfd; | 882 | if (outPipe[1]!=-1) { |
883 | nextout = outPipe[1]; | ||
884 | } else { | ||
885 | nextout = 1; | ||
886 | } | ||
884 | } | 887 | } |
885 | 888 | ||
886 | /* Check if the command matches any non-forking builtins */ | 889 | /* Check if the command matches any non-forking builtins */ |
@@ -895,15 +898,18 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
895 | 898 | ||
896 | if (outPipe[1]!=-1) { | 899 | if (outPipe[1]!=-1) { |
897 | close(outPipe[0]); | 900 | close(outPipe[0]); |
898 | nextout = stdoutfd = outPipe[1]; | 901 | } |
902 | if (nextin != 0) { | ||
903 | dup2(nextin, 0); | ||
904 | close(nextin); | ||
905 | } | ||
906 | |||
907 | if (nextout != 1) { | ||
899 | dup2(nextout, 1); | 908 | dup2(nextout, 1); |
900 | dup2(nextout, 2); | 909 | dup2(nextout, 2); |
901 | close(nextout); | 910 | close(nextout); |
902 | } | 911 | } |
903 | 912 | ||
904 | //dup2(nextin, 0); | ||
905 | //close(nextin); | ||
906 | |||
907 | /* explicit redirections override pipes */ | 913 | /* explicit redirections override pipes */ |
908 | setupRedirections(newJob->progs + i); | 914 | setupRedirections(newJob->progs + i); |
909 | 915 | ||
@@ -915,8 +921,8 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
915 | } | 921 | } |
916 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 922 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
917 | /* Check if the command matches any busybox internal commands here */ | 923 | /* Check if the command matches any busybox internal commands here */ |
918 | /* TODO: Add matching on commands with paths appended (i.e. 'cat' | 924 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
919 | * currently works, but '/bin/cat' doesn't ) */ | 925 | * works, but '/bin/cat' doesn't ) */ |
920 | while (a->name != 0) { | 926 | while (a->name != 0) { |
921 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { | 927 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
922 | int argc; | 928 | int argc; |
@@ -929,20 +935,19 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
929 | #endif | 935 | #endif |
930 | 936 | ||
931 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); | 937 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
932 | fatalError("%s: %s\n", newJob->progs[i].argv[0], | 938 | fatalError("sh: %s: %s\n", newJob->progs[i].argv[0], |
933 | strerror(errno)); | 939 | strerror(errno)); |
934 | } | 940 | } |
935 | if (outPipe[1]!=-1) { | 941 | if (outPipe[1]!=-1) { |
936 | close(outPipe[1]); | 942 | close(outPipe[1]); |
937 | } | 943 | } |
938 | 944 | ||
939 | /* put our child in the process group whose leader is the | 945 | /* put our child in the process group whose leader is the |
940 | first process in this pipe */ | 946 | first process in this pipe */ |
941 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); | 947 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
942 | |||
943 | if (nextin != 0) | 948 | if (nextin != 0) |
944 | close(nextin); | 949 | close(nextin); |
945 | if (nextout != stdoutfd) | 950 | if (nextout != 1) |
946 | close(nextout); | 951 | close(nextout); |
947 | 952 | ||
948 | /* If there isn't another process, nextin is garbage | 953 | /* If there isn't another process, nextin is garbage |
@@ -960,10 +965,10 @@ static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg, int | |||
960 | 965 | ||
961 | /* add the job to the list of running jobs */ | 966 | /* add the job to the list of running jobs */ |
962 | if (!jobList->head) { | 967 | if (!jobList->head) { |
963 | job = jobList->head = xmalloc(sizeof(*job)); | 968 | job = jobList->head = malloc(sizeof(*job)); |
964 | } else { | 969 | } else { |
965 | for (job = jobList->head; job->next; job = job->next); | 970 | for (job = jobList->head; job->next; job = job->next); |
966 | job->next = xmalloc(sizeof(*job)); | 971 | job->next = malloc(sizeof(*job)); |
967 | job = job->next; | 972 | job = job->next; |
968 | } | 973 | } |
969 | 974 | ||
@@ -1066,9 +1071,9 @@ static int busy_loop(FILE * input) | |||
1066 | int pipefds[2] = {-1,-1}; | 1071 | int pipefds[2] = {-1,-1}; |
1067 | runCommand(&newJob, &jobList, inBg, pipefds); | 1072 | runCommand(&newJob, &jobList, inBg, pipefds); |
1068 | } else { | 1073 | } else { |
1069 | nextCommand=NULL; | ||
1070 | free(command); | 1074 | free(command); |
1071 | command = (char *) calloc(BUFSIZ, sizeof(char)); | 1075 | command = (char *) calloc(BUFSIZ, sizeof(char)); |
1076 | nextCommand = NULL; | ||
1072 | } | 1077 | } |
1073 | } else { | 1078 | } else { |
1074 | /* a job is running in the foreground; wait for it */ | 1079 | /* a job is running in the foreground; wait for it */ |
@@ -1123,16 +1128,14 @@ static int busy_loop(FILE * input) | |||
1123 | } | 1128 | } |
1124 | 1129 | ||
1125 | 1130 | ||
1131 | |||
1126 | int shell_main(int argc, char **argv) | 1132 | int shell_main(int argc, char **argv) |
1127 | { | 1133 | { |
1128 | FILE *input = stdin; | 1134 | FILE *input = stdin; |
1129 | 1135 | ||
1130 | /* initialize the cwd */ | 1136 | /* initialize the cwd -- this is never freed...*/ |
1131 | cwd = (char *) calloc(BUFSIZ, sizeof(char)); | 1137 | cwd=(char*)xmalloc(sizeof(char)*MAX_LINE+1); |
1132 | if (cwd == 0) { | 1138 | getcwd(cwd, sizeof(char)*MAX_LINE); |
1133 | fatalError("out of memory\n"); | ||
1134 | } | ||
1135 | getcwd(cwd, sizeof(char)*BUFSIZ); | ||
1136 | 1139 | ||
1137 | #ifdef BB_FEATURE_SH_COMMAND_EDITING | 1140 | #ifdef BB_FEATURE_SH_COMMAND_EDITING |
1138 | cmdedit_init(); | 1141 | cmdedit_init(); |
@@ -1144,8 +1147,9 @@ int shell_main(int argc, char **argv) | |||
1144 | // builtin_source("/etc/profile"); | 1147 | // builtin_source("/etc/profile"); |
1145 | //} | 1148 | //} |
1146 | 1149 | ||
1150 | |||
1147 | if (argc < 2) { | 1151 | if (argc < 2) { |
1148 | fprintf(stdout, "\n\n%s Built-in shell\n", full_version); | 1152 | fprintf(stdout, "\n\nBusyBox v%s (%s) Built-in shell\n", BB_VER, BB_BT); |
1149 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); | 1153 | fprintf(stdout, "Enter 'help' for a list of built-in commands.\n\n"); |
1150 | } else { | 1154 | } else { |
1151 | if (argv[1][0]=='-' && argv[1][1]=='c') { | 1155 | if (argv[1][0]=='-' && argv[1][1]=='c') { |