diff options
author | Eric Andersen <andersen@codepoet.org> | 2000-07-14 01:13:11 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2000-07-14 01:13:11 +0000 |
commit | ec10b9d534d3c7c215144049b10df175aed02aa9 (patch) | |
tree | 675a2de47518a4e94f040b44d44e2cc2f8bf7404 | |
parent | 34623db61895ab5575f7851c9313ab2bf4fecc03 (diff) | |
download | busybox-w32-ec10b9d534d3c7c215144049b10df175aed02aa9.tar.gz busybox-w32-ec10b9d534d3c7c215144049b10df175aed02aa9.tar.bz2 busybox-w32-ec10b9d534d3c7c215144049b10df175aed02aa9.zip |
Add in redimentary backtick suport (doesn't work properly yet, but is
close).
-Erik
-rw-r--r-- | lash.c | 113 | ||||
-rw-r--r-- | sh.c | 113 | ||||
-rw-r--r-- | shell/lash.c | 113 |
3 files changed, 219 insertions, 120 deletions
@@ -106,9 +106,9 @@ static int builtin_read(struct job *cmd, struct jobSet *junk); | |||
106 | /* function prototypes for shell stuff */ | 106 | /* function prototypes for shell stuff */ |
107 | static void checkJobs(struct jobSet *jobList); | 107 | static void checkJobs(struct jobSet *jobList); |
108 | static int getCommand(FILE * source, char *command); | 108 | static int getCommand(FILE * source, char *command); |
109 | static int parseCommand(char **commandPtr, struct job *job, int *isBg); | 109 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg); |
110 | static int setupRedirections(struct childProgram *prog); | 110 | static int setupRedirections(struct childProgram *prog); |
111 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg); | 111 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg); |
112 | static int busy_loop(FILE * input); | 112 | static int busy_loop(FILE * input); |
113 | 113 | ||
114 | 114 | ||
@@ -389,6 +389,7 @@ static void freeJob(struct job *cmd) | |||
389 | if (cmd->text) | 389 | if (cmd->text) |
390 | free(cmd->text); | 390 | free(cmd->text); |
391 | free(cmd->cmdBuf); | 391 | free(cmd->cmdBuf); |
392 | memset(cmd, 0, sizeof(struct job)); | ||
392 | } | 393 | } |
393 | 394 | ||
394 | /* remove a job from the jobList */ | 395 | /* remove a job from the jobList */ |
@@ -471,7 +472,7 @@ static int getCommand(FILE * source, char *command) | |||
471 | char *promptStr; | 472 | char *promptStr; |
472 | len=fprintf(stdout, "%s %s", cwd, prompt); | 473 | len=fprintf(stdout, "%s %s", cwd, prompt); |
473 | fflush(stdout); | 474 | fflush(stdout); |
474 | promptStr=(char*)malloc(sizeof(char)*(len+1)); | 475 | promptStr=(char*)xmalloc(sizeof(char)*(len+1)); |
475 | sprintf(promptStr, "%s %s", cwd, prompt); | 476 | sprintf(promptStr, "%s %s", cwd, prompt); |
476 | cmdedit_read_input(promptStr, command); | 477 | cmdedit_read_input(promptStr, command); |
477 | free( promptStr); | 478 | free( promptStr); |
@@ -550,7 +551,7 @@ static void globLastArgument(struct childProgram *prog, int *argcPtr, | |||
550 | the beginning of the next command (if the original command had more | 551 | the beginning of the next command (if the original command had more |
551 | then one job associated with it) or NULL if no more commands are | 552 | then one job associated with it) or NULL if no more commands are |
552 | present. */ | 553 | present. */ |
553 | static int parseCommand(char **commandPtr, struct job *job, int *isBg) | 554 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg) |
554 | { | 555 | { |
555 | char *command; | 556 | char *command; |
556 | char *returnCommand = NULL; | 557 | char *returnCommand = NULL; |
@@ -569,14 +570,13 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
569 | 570 | ||
570 | /* this handles empty lines or leading '#' characters */ | 571 | /* this handles empty lines or leading '#' characters */ |
571 | if (!**commandPtr || (**commandPtr == '#')) { | 572 | if (!**commandPtr || (**commandPtr == '#')) { |
572 | job->numProgs = 0; | 573 | job->numProgs=0; |
573 | *commandPtr = NULL; | ||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | *isBg = 0; | 577 | *isBg = 0; |
578 | job->numProgs = 1; | 578 | job->numProgs = 1; |
579 | job->progs = malloc(sizeof(*job->progs)); | 579 | job->progs = xmalloc(sizeof(*job->progs)); |
580 | 580 | ||
581 | /* We set the argv elements to point inside of this string. The | 581 | /* We set the argv elements to point inside of this string. The |
582 | memory is freed by freeJob(). Allocate twice the original | 582 | memory is freed by freeJob(). Allocate twice the original |
@@ -595,7 +595,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
595 | prog->isStopped = 0; | 595 | prog->isStopped = 0; |
596 | 596 | ||
597 | argvAlloced = 5; | 597 | argvAlloced = 5; |
598 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 598 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
599 | prog->argv[0] = job->cmdBuf; | 599 | prog->argv[0] = job->cmdBuf; |
600 | 600 | ||
601 | buf = command; | 601 | buf = command; |
@@ -688,6 +688,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
688 | if (!*chptr) { | 688 | if (!*chptr) { |
689 | fprintf(stderr, "file name expected after %c\n", *src); | 689 | fprintf(stderr, "file name expected after %c\n", *src); |
690 | freeJob(job); | 690 | freeJob(job); |
691 | job->numProgs=0; | ||
691 | return 1; | 692 | return 1; |
692 | } | 693 | } |
693 | 694 | ||
@@ -704,8 +705,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
704 | if (*prog->argv[argc]) | 705 | if (*prog->argv[argc]) |
705 | argc++; | 706 | argc++; |
706 | if (!argc) { | 707 | if (!argc) { |
707 | fprintf(stderr, "empty command in pipe\n"); | 708 | fprintf(stderr, "empty command in pipe1.\n"); |
708 | freeJob(job); | 709 | freeJob(job); |
710 | job->numProgs=0; | ||
709 | return 1; | 711 | return 1; |
710 | } | 712 | } |
711 | prog->argv[argc] = NULL; | 713 | prog->argv[argc] = NULL; |
@@ -721,7 +723,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
721 | argc = 0; | 723 | argc = 0; |
722 | 724 | ||
723 | argvAlloced = 5; | 725 | argvAlloced = 5; |
724 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 726 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
725 | prog->argv[0] = ++buf; | 727 | prog->argv[0] = ++buf; |
726 | 728 | ||
727 | src++; | 729 | src++; |
@@ -729,7 +731,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
729 | src++; | 731 | src++; |
730 | 732 | ||
731 | if (!*src) { | 733 | if (!*src) { |
732 | fprintf(stderr, "empty command in pipe\n"); | 734 | fprintf(stderr, "empty command in pipe2\n"); |
735 | freeJob(job); | ||
736 | job->numProgs=0; | ||
733 | return 1; | 737 | return 1; |
734 | } | 738 | } |
735 | src--; /* we'll ++ it at the end of the loop */ | 739 | src--; /* we'll ++ it at the end of the loop */ |
@@ -746,13 +750,40 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
746 | case '\\': | 750 | case '\\': |
747 | src++; | 751 | src++; |
748 | if (!*src) { | 752 | if (!*src) { |
749 | freeJob(job); | ||
750 | fprintf(stderr, "character expected after \\\n"); | 753 | fprintf(stderr, "character expected after \\\n"); |
754 | freeJob(job); | ||
751 | return 1; | 755 | return 1; |
752 | } | 756 | } |
753 | if (*src == '*' || *src == '[' || *src == ']' | 757 | if (*src == '*' || *src == '[' || *src == ']' |
754 | || *src == '?') *buf++ = '\\'; | 758 | || *src == '?') *buf++ = '\\'; |
755 | /* fallthrough */ | 759 | /* fallthrough */ |
760 | case '`': | ||
761 | /* Exec a backtick-ed command */ | ||
762 | { | ||
763 | char* newcmd=NULL; | ||
764 | char* ptr=NULL; | ||
765 | struct job newJob; | ||
766 | |||
767 | ptr=strchr(++src, '`'); | ||
768 | if (ptr==NULL) { | ||
769 | fprintf(stderr, "Unmatched '`' in command\n"); | ||
770 | freeJob(job); | ||
771 | return 1; | ||
772 | } | ||
773 | |||
774 | newcmd = xmalloc(1+ptr-src); | ||
775 | snprintf(newcmd, 1+ptr-src, src); | ||
776 | |||
777 | if (!parseCommand(&newcmd, &newJob, jobList, isBg) && | ||
778 | newJob.numProgs) { | ||
779 | runCommand(&newJob, jobList, *isBg); | ||
780 | } | ||
781 | |||
782 | /* Clip out the the backticked command from the string */ | ||
783 | memmove(--src, ptr, strlen(ptr)+1); | ||
784 | free(newcmd); | ||
785 | } | ||
786 | break; | ||
756 | default: | 787 | default: |
757 | *buf++ = *src; | 788 | *buf++ = *src; |
758 | } | 789 | } |
@@ -771,12 +802,12 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
771 | prog->argv[argc] = NULL; | 802 | prog->argv[argc] = NULL; |
772 | 803 | ||
773 | if (!returnCommand) { | 804 | if (!returnCommand) { |
774 | job->text = malloc(strlen(*commandPtr) + 1); | 805 | job->text = xmalloc(strlen(*commandPtr) + 1); |
775 | strcpy(job->text, *commandPtr); | 806 | strcpy(job->text, *commandPtr); |
776 | } else { | 807 | } else { |
777 | /* This leaves any trailing spaces, which is a bit sloppy */ | 808 | /* This leaves any trailing spaces, which is a bit sloppy */ |
778 | count = returnCommand - *commandPtr; | 809 | count = returnCommand - *commandPtr; |
779 | job->text = malloc(count + 1); | 810 | job->text = xmalloc(count + 1); |
780 | strncpy(job->text, *commandPtr, count); | 811 | strncpy(job->text, *commandPtr, count); |
781 | job->text[count] = '\0'; | 812 | job->text[count] = '\0'; |
782 | } | 813 | } |
@@ -787,7 +818,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
787 | } | 818 | } |
788 | 819 | ||
789 | 820 | ||
790 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | 821 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg) |
791 | { | 822 | { |
792 | struct job *job; | 823 | struct job *job; |
793 | int i; | 824 | int i; |
@@ -800,8 +831,8 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
800 | 831 | ||
801 | 832 | ||
802 | nextin = 0, nextout = 1; | 833 | nextin = 0, nextout = 1; |
803 | for (i = 0; i < newJob.numProgs; i++) { | 834 | for (i = 0; i < newJob->numProgs; i++) { |
804 | if ((i + 1) < newJob.numProgs) { | 835 | if ((i + 1) < newJob->numProgs) { |
805 | pipe(pipefds); | 836 | pipe(pipefds); |
806 | nextout = pipefds[1]; | 837 | nextout = pipefds[1]; |
807 | } else { | 838 | } else { |
@@ -810,12 +841,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
810 | 841 | ||
811 | /* Check if the command matches any non-forking builtins */ | 842 | /* Check if the command matches any non-forking builtins */ |
812 | for (x = bltins; x->cmd; x++) { | 843 | for (x = bltins; x->cmd; x++) { |
813 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 844 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
814 | return (x->function(&newJob, jobList)); | 845 | return (x->function(newJob, jobList)); |
815 | } | 846 | } |
816 | } | 847 | } |
817 | 848 | ||
818 | if (!(newJob.progs[i].pid = fork())) { | 849 | if (!(newJob->progs[i].pid = fork())) { |
819 | signal(SIGTTOU, SIG_DFL); | 850 | signal(SIGTTOU, SIG_DFL); |
820 | 851 | ||
821 | if (nextin != 0) { | 852 | if (nextin != 0) { |
@@ -829,12 +860,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
829 | } | 860 | } |
830 | 861 | ||
831 | /* explicit redirections override pipes */ | 862 | /* explicit redirections override pipes */ |
832 | setupRedirections(newJob.progs + i); | 863 | setupRedirections(newJob->progs + i); |
833 | 864 | ||
834 | /* Check if the command matches any of the other builtins */ | 865 | /* Check if the command matches any of the other builtins */ |
835 | for (x = bltins_forking; x->cmd; x++) { | 866 | for (x = bltins_forking; x->cmd; x++) { |
836 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 867 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
837 | exit (x->function(&newJob, jobList)); | 868 | exit (x->function(newJob, jobList)); |
838 | } | 869 | } |
839 | } | 870 | } |
840 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
@@ -842,24 +873,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
842 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently | 873 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
843 | * works, but '/bin/cat' doesn't ) */ | 874 | * works, but '/bin/cat' doesn't ) */ |
844 | while (a->name != 0) { | 875 | while (a->name != 0) { |
845 | if (strcmp(newJob.progs[i].argv[0], a->name) == 0) { | 876 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
846 | int argc; | 877 | int argc; |
847 | char** argv=newJob.progs[i].argv; | 878 | char** argv=newJob->progs[i].argv; |
848 | for(argc=0;*argv!=NULL; argv++, argc++); | 879 | for(argc=0;*argv!=NULL; argv++, argc++); |
849 | exit((*(a->main)) (argc, newJob.progs[i].argv)); | 880 | exit((*(a->main)) (argc, newJob->progs[i].argv)); |
850 | } | 881 | } |
851 | a++; | 882 | a++; |
852 | } | 883 | } |
853 | #endif | 884 | #endif |
854 | 885 | ||
855 | execvp(newJob.progs[i].argv[0], newJob.progs[i].argv); | 886 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
856 | fatalError("%s: %s\n", newJob.progs[i].argv[0], | 887 | fatalError("%s: %s\n", newJob->progs[i].argv[0], |
857 | strerror(errno)); | 888 | strerror(errno)); |
858 | } | 889 | } |
859 | 890 | ||
860 | /* put our child in the process group whose leader is the | 891 | /* put our child in the process group whose leader is the |
861 | first process in this pipe */ | 892 | first process in this pipe */ |
862 | setpgid(newJob.progs[i].pid, newJob.progs[0].pid); | 893 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
863 | 894 | ||
864 | if (nextin != 0) | 895 | if (nextin != 0) |
865 | close(nextin); | 896 | close(nextin); |
@@ -871,24 +902,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
871 | nextin = pipefds[0]; | 902 | nextin = pipefds[0]; |
872 | } | 903 | } |
873 | 904 | ||
874 | newJob.pgrp = newJob.progs[0].pid; | 905 | newJob->pgrp = newJob->progs[0].pid; |
875 | 906 | ||
876 | /* find the ID for the job to use */ | 907 | /* find the ID for the job to use */ |
877 | newJob.jobId = 1; | 908 | newJob->jobId = 1; |
878 | for (job = jobList->head; job; job = job->next) | 909 | for (job = jobList->head; job; job = job->next) |
879 | if (job->jobId >= newJob.jobId) | 910 | if (job->jobId >= newJob->jobId) |
880 | newJob.jobId = job->jobId + 1; | 911 | newJob->jobId = job->jobId + 1; |
881 | 912 | ||
882 | /* add the job to the list of running jobs */ | 913 | /* add the job to the list of running jobs */ |
883 | if (!jobList->head) { | 914 | if (!jobList->head) { |
884 | job = jobList->head = malloc(sizeof(*job)); | 915 | job = jobList->head = xmalloc(sizeof(*job)); |
885 | } else { | 916 | } else { |
886 | for (job = jobList->head; job->next; job = job->next); | 917 | for (job = jobList->head; job->next; job = job->next); |
887 | job->next = malloc(sizeof(*job)); | 918 | job->next = xmalloc(sizeof(*job)); |
888 | job = job->next; | 919 | job = job->next; |
889 | } | 920 | } |
890 | 921 | ||
891 | *job = newJob; | 922 | *job = *newJob; |
892 | job->next = NULL; | 923 | job->next = NULL; |
893 | job->runningProgs = job->numProgs; | 924 | job->runningProgs = job->numProgs; |
894 | job->stoppedProgs = 0; | 925 | job->stoppedProgs = 0; |
@@ -897,13 +928,13 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
897 | /* we don't wait for background jobs to return -- append it | 928 | /* we don't wait for background jobs to return -- append it |
898 | to the list of backgrounded jobs and leave it alone */ | 929 | to the list of backgrounded jobs and leave it alone */ |
899 | printf("[%d] %d\n", job->jobId, | 930 | printf("[%d] %d\n", job->jobId, |
900 | newJob.progs[newJob.numProgs - 1].pid); | 931 | newJob->progs[newJob->numProgs - 1].pid); |
901 | } else { | 932 | } else { |
902 | jobList->fg = job; | 933 | jobList->fg = job; |
903 | 934 | ||
904 | /* move the new process group into the foreground */ | 935 | /* move the new process group into the foreground */ |
905 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 936 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
906 | if (tcsetpgrp(0, newJob.pgrp) && errno != ENOTTY) | 937 | if (tcsetpgrp(0, newJob->pgrp) && errno != ENOTTY) |
907 | perror("tcsetpgrp"); | 938 | perror("tcsetpgrp"); |
908 | } | 939 | } |
909 | 940 | ||
@@ -982,9 +1013,11 @@ static int busy_loop(FILE * input) | |||
982 | nextCommand = command; | 1013 | nextCommand = command; |
983 | } | 1014 | } |
984 | 1015 | ||
985 | if (!parseCommand(&nextCommand, &newJob, &inBg) && | 1016 | if (!parseCommand(&nextCommand, &newJob, &jobList, &inBg) && |
986 | newJob.numProgs) { | 1017 | newJob.numProgs) { |
987 | runCommand(newJob, &jobList, inBg); | 1018 | runCommand(&newJob, &jobList, inBg); |
1019 | } else { | ||
1020 | nextCommand=NULL; | ||
988 | } | 1021 | } |
989 | } else { | 1022 | } else { |
990 | /* a job is running in the foreground; wait for it */ | 1023 | /* a job is running in the foreground; wait for it */ |
@@ -106,9 +106,9 @@ static int builtin_read(struct job *cmd, struct jobSet *junk); | |||
106 | /* function prototypes for shell stuff */ | 106 | /* function prototypes for shell stuff */ |
107 | static void checkJobs(struct jobSet *jobList); | 107 | static void checkJobs(struct jobSet *jobList); |
108 | static int getCommand(FILE * source, char *command); | 108 | static int getCommand(FILE * source, char *command); |
109 | static int parseCommand(char **commandPtr, struct job *job, int *isBg); | 109 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg); |
110 | static int setupRedirections(struct childProgram *prog); | 110 | static int setupRedirections(struct childProgram *prog); |
111 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg); | 111 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg); |
112 | static int busy_loop(FILE * input); | 112 | static int busy_loop(FILE * input); |
113 | 113 | ||
114 | 114 | ||
@@ -389,6 +389,7 @@ static void freeJob(struct job *cmd) | |||
389 | if (cmd->text) | 389 | if (cmd->text) |
390 | free(cmd->text); | 390 | free(cmd->text); |
391 | free(cmd->cmdBuf); | 391 | free(cmd->cmdBuf); |
392 | memset(cmd, 0, sizeof(struct job)); | ||
392 | } | 393 | } |
393 | 394 | ||
394 | /* remove a job from the jobList */ | 395 | /* remove a job from the jobList */ |
@@ -471,7 +472,7 @@ static int getCommand(FILE * source, char *command) | |||
471 | char *promptStr; | 472 | char *promptStr; |
472 | len=fprintf(stdout, "%s %s", cwd, prompt); | 473 | len=fprintf(stdout, "%s %s", cwd, prompt); |
473 | fflush(stdout); | 474 | fflush(stdout); |
474 | promptStr=(char*)malloc(sizeof(char)*(len+1)); | 475 | promptStr=(char*)xmalloc(sizeof(char)*(len+1)); |
475 | sprintf(promptStr, "%s %s", cwd, prompt); | 476 | sprintf(promptStr, "%s %s", cwd, prompt); |
476 | cmdedit_read_input(promptStr, command); | 477 | cmdedit_read_input(promptStr, command); |
477 | free( promptStr); | 478 | free( promptStr); |
@@ -550,7 +551,7 @@ static void globLastArgument(struct childProgram *prog, int *argcPtr, | |||
550 | the beginning of the next command (if the original command had more | 551 | the beginning of the next command (if the original command had more |
551 | then one job associated with it) or NULL if no more commands are | 552 | then one job associated with it) or NULL if no more commands are |
552 | present. */ | 553 | present. */ |
553 | static int parseCommand(char **commandPtr, struct job *job, int *isBg) | 554 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg) |
554 | { | 555 | { |
555 | char *command; | 556 | char *command; |
556 | char *returnCommand = NULL; | 557 | char *returnCommand = NULL; |
@@ -569,14 +570,13 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
569 | 570 | ||
570 | /* this handles empty lines or leading '#' characters */ | 571 | /* this handles empty lines or leading '#' characters */ |
571 | if (!**commandPtr || (**commandPtr == '#')) { | 572 | if (!**commandPtr || (**commandPtr == '#')) { |
572 | job->numProgs = 0; | 573 | job->numProgs=0; |
573 | *commandPtr = NULL; | ||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | *isBg = 0; | 577 | *isBg = 0; |
578 | job->numProgs = 1; | 578 | job->numProgs = 1; |
579 | job->progs = malloc(sizeof(*job->progs)); | 579 | job->progs = xmalloc(sizeof(*job->progs)); |
580 | 580 | ||
581 | /* We set the argv elements to point inside of this string. The | 581 | /* We set the argv elements to point inside of this string. The |
582 | memory is freed by freeJob(). Allocate twice the original | 582 | memory is freed by freeJob(). Allocate twice the original |
@@ -595,7 +595,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
595 | prog->isStopped = 0; | 595 | prog->isStopped = 0; |
596 | 596 | ||
597 | argvAlloced = 5; | 597 | argvAlloced = 5; |
598 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 598 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
599 | prog->argv[0] = job->cmdBuf; | 599 | prog->argv[0] = job->cmdBuf; |
600 | 600 | ||
601 | buf = command; | 601 | buf = command; |
@@ -688,6 +688,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
688 | if (!*chptr) { | 688 | if (!*chptr) { |
689 | fprintf(stderr, "file name expected after %c\n", *src); | 689 | fprintf(stderr, "file name expected after %c\n", *src); |
690 | freeJob(job); | 690 | freeJob(job); |
691 | job->numProgs=0; | ||
691 | return 1; | 692 | return 1; |
692 | } | 693 | } |
693 | 694 | ||
@@ -704,8 +705,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
704 | if (*prog->argv[argc]) | 705 | if (*prog->argv[argc]) |
705 | argc++; | 706 | argc++; |
706 | if (!argc) { | 707 | if (!argc) { |
707 | fprintf(stderr, "empty command in pipe\n"); | 708 | fprintf(stderr, "empty command in pipe1.\n"); |
708 | freeJob(job); | 709 | freeJob(job); |
710 | job->numProgs=0; | ||
709 | return 1; | 711 | return 1; |
710 | } | 712 | } |
711 | prog->argv[argc] = NULL; | 713 | prog->argv[argc] = NULL; |
@@ -721,7 +723,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
721 | argc = 0; | 723 | argc = 0; |
722 | 724 | ||
723 | argvAlloced = 5; | 725 | argvAlloced = 5; |
724 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 726 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
725 | prog->argv[0] = ++buf; | 727 | prog->argv[0] = ++buf; |
726 | 728 | ||
727 | src++; | 729 | src++; |
@@ -729,7 +731,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
729 | src++; | 731 | src++; |
730 | 732 | ||
731 | if (!*src) { | 733 | if (!*src) { |
732 | fprintf(stderr, "empty command in pipe\n"); | 734 | fprintf(stderr, "empty command in pipe2\n"); |
735 | freeJob(job); | ||
736 | job->numProgs=0; | ||
733 | return 1; | 737 | return 1; |
734 | } | 738 | } |
735 | src--; /* we'll ++ it at the end of the loop */ | 739 | src--; /* we'll ++ it at the end of the loop */ |
@@ -746,13 +750,40 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
746 | case '\\': | 750 | case '\\': |
747 | src++; | 751 | src++; |
748 | if (!*src) { | 752 | if (!*src) { |
749 | freeJob(job); | ||
750 | fprintf(stderr, "character expected after \\\n"); | 753 | fprintf(stderr, "character expected after \\\n"); |
754 | freeJob(job); | ||
751 | return 1; | 755 | return 1; |
752 | } | 756 | } |
753 | if (*src == '*' || *src == '[' || *src == ']' | 757 | if (*src == '*' || *src == '[' || *src == ']' |
754 | || *src == '?') *buf++ = '\\'; | 758 | || *src == '?') *buf++ = '\\'; |
755 | /* fallthrough */ | 759 | /* fallthrough */ |
760 | case '`': | ||
761 | /* Exec a backtick-ed command */ | ||
762 | { | ||
763 | char* newcmd=NULL; | ||
764 | char* ptr=NULL; | ||
765 | struct job newJob; | ||
766 | |||
767 | ptr=strchr(++src, '`'); | ||
768 | if (ptr==NULL) { | ||
769 | fprintf(stderr, "Unmatched '`' in command\n"); | ||
770 | freeJob(job); | ||
771 | return 1; | ||
772 | } | ||
773 | |||
774 | newcmd = xmalloc(1+ptr-src); | ||
775 | snprintf(newcmd, 1+ptr-src, src); | ||
776 | |||
777 | if (!parseCommand(&newcmd, &newJob, jobList, isBg) && | ||
778 | newJob.numProgs) { | ||
779 | runCommand(&newJob, jobList, *isBg); | ||
780 | } | ||
781 | |||
782 | /* Clip out the the backticked command from the string */ | ||
783 | memmove(--src, ptr, strlen(ptr)+1); | ||
784 | free(newcmd); | ||
785 | } | ||
786 | break; | ||
756 | default: | 787 | default: |
757 | *buf++ = *src; | 788 | *buf++ = *src; |
758 | } | 789 | } |
@@ -771,12 +802,12 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
771 | prog->argv[argc] = NULL; | 802 | prog->argv[argc] = NULL; |
772 | 803 | ||
773 | if (!returnCommand) { | 804 | if (!returnCommand) { |
774 | job->text = malloc(strlen(*commandPtr) + 1); | 805 | job->text = xmalloc(strlen(*commandPtr) + 1); |
775 | strcpy(job->text, *commandPtr); | 806 | strcpy(job->text, *commandPtr); |
776 | } else { | 807 | } else { |
777 | /* This leaves any trailing spaces, which is a bit sloppy */ | 808 | /* This leaves any trailing spaces, which is a bit sloppy */ |
778 | count = returnCommand - *commandPtr; | 809 | count = returnCommand - *commandPtr; |
779 | job->text = malloc(count + 1); | 810 | job->text = xmalloc(count + 1); |
780 | strncpy(job->text, *commandPtr, count); | 811 | strncpy(job->text, *commandPtr, count); |
781 | job->text[count] = '\0'; | 812 | job->text[count] = '\0'; |
782 | } | 813 | } |
@@ -787,7 +818,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
787 | } | 818 | } |
788 | 819 | ||
789 | 820 | ||
790 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | 821 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg) |
791 | { | 822 | { |
792 | struct job *job; | 823 | struct job *job; |
793 | int i; | 824 | int i; |
@@ -800,8 +831,8 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
800 | 831 | ||
801 | 832 | ||
802 | nextin = 0, nextout = 1; | 833 | nextin = 0, nextout = 1; |
803 | for (i = 0; i < newJob.numProgs; i++) { | 834 | for (i = 0; i < newJob->numProgs; i++) { |
804 | if ((i + 1) < newJob.numProgs) { | 835 | if ((i + 1) < newJob->numProgs) { |
805 | pipe(pipefds); | 836 | pipe(pipefds); |
806 | nextout = pipefds[1]; | 837 | nextout = pipefds[1]; |
807 | } else { | 838 | } else { |
@@ -810,12 +841,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
810 | 841 | ||
811 | /* Check if the command matches any non-forking builtins */ | 842 | /* Check if the command matches any non-forking builtins */ |
812 | for (x = bltins; x->cmd; x++) { | 843 | for (x = bltins; x->cmd; x++) { |
813 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 844 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
814 | return (x->function(&newJob, jobList)); | 845 | return (x->function(newJob, jobList)); |
815 | } | 846 | } |
816 | } | 847 | } |
817 | 848 | ||
818 | if (!(newJob.progs[i].pid = fork())) { | 849 | if (!(newJob->progs[i].pid = fork())) { |
819 | signal(SIGTTOU, SIG_DFL); | 850 | signal(SIGTTOU, SIG_DFL); |
820 | 851 | ||
821 | if (nextin != 0) { | 852 | if (nextin != 0) { |
@@ -829,12 +860,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
829 | } | 860 | } |
830 | 861 | ||
831 | /* explicit redirections override pipes */ | 862 | /* explicit redirections override pipes */ |
832 | setupRedirections(newJob.progs + i); | 863 | setupRedirections(newJob->progs + i); |
833 | 864 | ||
834 | /* Check if the command matches any of the other builtins */ | 865 | /* Check if the command matches any of the other builtins */ |
835 | for (x = bltins_forking; x->cmd; x++) { | 866 | for (x = bltins_forking; x->cmd; x++) { |
836 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 867 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
837 | exit (x->function(&newJob, jobList)); | 868 | exit (x->function(newJob, jobList)); |
838 | } | 869 | } |
839 | } | 870 | } |
840 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
@@ -842,24 +873,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
842 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently | 873 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
843 | * works, but '/bin/cat' doesn't ) */ | 874 | * works, but '/bin/cat' doesn't ) */ |
844 | while (a->name != 0) { | 875 | while (a->name != 0) { |
845 | if (strcmp(newJob.progs[i].argv[0], a->name) == 0) { | 876 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
846 | int argc; | 877 | int argc; |
847 | char** argv=newJob.progs[i].argv; | 878 | char** argv=newJob->progs[i].argv; |
848 | for(argc=0;*argv!=NULL; argv++, argc++); | 879 | for(argc=0;*argv!=NULL; argv++, argc++); |
849 | exit((*(a->main)) (argc, newJob.progs[i].argv)); | 880 | exit((*(a->main)) (argc, newJob->progs[i].argv)); |
850 | } | 881 | } |
851 | a++; | 882 | a++; |
852 | } | 883 | } |
853 | #endif | 884 | #endif |
854 | 885 | ||
855 | execvp(newJob.progs[i].argv[0], newJob.progs[i].argv); | 886 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
856 | fatalError("%s: %s\n", newJob.progs[i].argv[0], | 887 | fatalError("%s: %s\n", newJob->progs[i].argv[0], |
857 | strerror(errno)); | 888 | strerror(errno)); |
858 | } | 889 | } |
859 | 890 | ||
860 | /* put our child in the process group whose leader is the | 891 | /* put our child in the process group whose leader is the |
861 | first process in this pipe */ | 892 | first process in this pipe */ |
862 | setpgid(newJob.progs[i].pid, newJob.progs[0].pid); | 893 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
863 | 894 | ||
864 | if (nextin != 0) | 895 | if (nextin != 0) |
865 | close(nextin); | 896 | close(nextin); |
@@ -871,24 +902,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
871 | nextin = pipefds[0]; | 902 | nextin = pipefds[0]; |
872 | } | 903 | } |
873 | 904 | ||
874 | newJob.pgrp = newJob.progs[0].pid; | 905 | newJob->pgrp = newJob->progs[0].pid; |
875 | 906 | ||
876 | /* find the ID for the job to use */ | 907 | /* find the ID for the job to use */ |
877 | newJob.jobId = 1; | 908 | newJob->jobId = 1; |
878 | for (job = jobList->head; job; job = job->next) | 909 | for (job = jobList->head; job; job = job->next) |
879 | if (job->jobId >= newJob.jobId) | 910 | if (job->jobId >= newJob->jobId) |
880 | newJob.jobId = job->jobId + 1; | 911 | newJob->jobId = job->jobId + 1; |
881 | 912 | ||
882 | /* add the job to the list of running jobs */ | 913 | /* add the job to the list of running jobs */ |
883 | if (!jobList->head) { | 914 | if (!jobList->head) { |
884 | job = jobList->head = malloc(sizeof(*job)); | 915 | job = jobList->head = xmalloc(sizeof(*job)); |
885 | } else { | 916 | } else { |
886 | for (job = jobList->head; job->next; job = job->next); | 917 | for (job = jobList->head; job->next; job = job->next); |
887 | job->next = malloc(sizeof(*job)); | 918 | job->next = xmalloc(sizeof(*job)); |
888 | job = job->next; | 919 | job = job->next; |
889 | } | 920 | } |
890 | 921 | ||
891 | *job = newJob; | 922 | *job = *newJob; |
892 | job->next = NULL; | 923 | job->next = NULL; |
893 | job->runningProgs = job->numProgs; | 924 | job->runningProgs = job->numProgs; |
894 | job->stoppedProgs = 0; | 925 | job->stoppedProgs = 0; |
@@ -897,13 +928,13 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
897 | /* we don't wait for background jobs to return -- append it | 928 | /* we don't wait for background jobs to return -- append it |
898 | to the list of backgrounded jobs and leave it alone */ | 929 | to the list of backgrounded jobs and leave it alone */ |
899 | printf("[%d] %d\n", job->jobId, | 930 | printf("[%d] %d\n", job->jobId, |
900 | newJob.progs[newJob.numProgs - 1].pid); | 931 | newJob->progs[newJob->numProgs - 1].pid); |
901 | } else { | 932 | } else { |
902 | jobList->fg = job; | 933 | jobList->fg = job; |
903 | 934 | ||
904 | /* move the new process group into the foreground */ | 935 | /* move the new process group into the foreground */ |
905 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 936 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
906 | if (tcsetpgrp(0, newJob.pgrp) && errno != ENOTTY) | 937 | if (tcsetpgrp(0, newJob->pgrp) && errno != ENOTTY) |
907 | perror("tcsetpgrp"); | 938 | perror("tcsetpgrp"); |
908 | } | 939 | } |
909 | 940 | ||
@@ -982,9 +1013,11 @@ static int busy_loop(FILE * input) | |||
982 | nextCommand = command; | 1013 | nextCommand = command; |
983 | } | 1014 | } |
984 | 1015 | ||
985 | if (!parseCommand(&nextCommand, &newJob, &inBg) && | 1016 | if (!parseCommand(&nextCommand, &newJob, &jobList, &inBg) && |
986 | newJob.numProgs) { | 1017 | newJob.numProgs) { |
987 | runCommand(newJob, &jobList, inBg); | 1018 | runCommand(&newJob, &jobList, inBg); |
1019 | } else { | ||
1020 | nextCommand=NULL; | ||
988 | } | 1021 | } |
989 | } else { | 1022 | } else { |
990 | /* a job is running in the foreground; wait for it */ | 1023 | /* a job is running in the foreground; wait for it */ |
diff --git a/shell/lash.c b/shell/lash.c index bb258c788..f4564f7f7 100644 --- a/shell/lash.c +++ b/shell/lash.c | |||
@@ -106,9 +106,9 @@ static int builtin_read(struct job *cmd, struct jobSet *junk); | |||
106 | /* function prototypes for shell stuff */ | 106 | /* function prototypes for shell stuff */ |
107 | static void checkJobs(struct jobSet *jobList); | 107 | static void checkJobs(struct jobSet *jobList); |
108 | static int getCommand(FILE * source, char *command); | 108 | static int getCommand(FILE * source, char *command); |
109 | static int parseCommand(char **commandPtr, struct job *job, int *isBg); | 109 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg); |
110 | static int setupRedirections(struct childProgram *prog); | 110 | static int setupRedirections(struct childProgram *prog); |
111 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg); | 111 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg); |
112 | static int busy_loop(FILE * input); | 112 | static int busy_loop(FILE * input); |
113 | 113 | ||
114 | 114 | ||
@@ -389,6 +389,7 @@ static void freeJob(struct job *cmd) | |||
389 | if (cmd->text) | 389 | if (cmd->text) |
390 | free(cmd->text); | 390 | free(cmd->text); |
391 | free(cmd->cmdBuf); | 391 | free(cmd->cmdBuf); |
392 | memset(cmd, 0, sizeof(struct job)); | ||
392 | } | 393 | } |
393 | 394 | ||
394 | /* remove a job from the jobList */ | 395 | /* remove a job from the jobList */ |
@@ -471,7 +472,7 @@ static int getCommand(FILE * source, char *command) | |||
471 | char *promptStr; | 472 | char *promptStr; |
472 | len=fprintf(stdout, "%s %s", cwd, prompt); | 473 | len=fprintf(stdout, "%s %s", cwd, prompt); |
473 | fflush(stdout); | 474 | fflush(stdout); |
474 | promptStr=(char*)malloc(sizeof(char)*(len+1)); | 475 | promptStr=(char*)xmalloc(sizeof(char)*(len+1)); |
475 | sprintf(promptStr, "%s %s", cwd, prompt); | 476 | sprintf(promptStr, "%s %s", cwd, prompt); |
476 | cmdedit_read_input(promptStr, command); | 477 | cmdedit_read_input(promptStr, command); |
477 | free( promptStr); | 478 | free( promptStr); |
@@ -550,7 +551,7 @@ static void globLastArgument(struct childProgram *prog, int *argcPtr, | |||
550 | the beginning of the next command (if the original command had more | 551 | the beginning of the next command (if the original command had more |
551 | then one job associated with it) or NULL if no more commands are | 552 | then one job associated with it) or NULL if no more commands are |
552 | present. */ | 553 | present. */ |
553 | static int parseCommand(char **commandPtr, struct job *job, int *isBg) | 554 | static int parseCommand(char **commandPtr, struct job *job, struct jobSet *jobList, int *isBg) |
554 | { | 555 | { |
555 | char *command; | 556 | char *command; |
556 | char *returnCommand = NULL; | 557 | char *returnCommand = NULL; |
@@ -569,14 +570,13 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
569 | 570 | ||
570 | /* this handles empty lines or leading '#' characters */ | 571 | /* this handles empty lines or leading '#' characters */ |
571 | if (!**commandPtr || (**commandPtr == '#')) { | 572 | if (!**commandPtr || (**commandPtr == '#')) { |
572 | job->numProgs = 0; | 573 | job->numProgs=0; |
573 | *commandPtr = NULL; | ||
574 | return 0; | 574 | return 0; |
575 | } | 575 | } |
576 | 576 | ||
577 | *isBg = 0; | 577 | *isBg = 0; |
578 | job->numProgs = 1; | 578 | job->numProgs = 1; |
579 | job->progs = malloc(sizeof(*job->progs)); | 579 | job->progs = xmalloc(sizeof(*job->progs)); |
580 | 580 | ||
581 | /* We set the argv elements to point inside of this string. The | 581 | /* We set the argv elements to point inside of this string. The |
582 | memory is freed by freeJob(). Allocate twice the original | 582 | memory is freed by freeJob(). Allocate twice the original |
@@ -595,7 +595,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
595 | prog->isStopped = 0; | 595 | prog->isStopped = 0; |
596 | 596 | ||
597 | argvAlloced = 5; | 597 | argvAlloced = 5; |
598 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 598 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
599 | prog->argv[0] = job->cmdBuf; | 599 | prog->argv[0] = job->cmdBuf; |
600 | 600 | ||
601 | buf = command; | 601 | buf = command; |
@@ -688,6 +688,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
688 | if (!*chptr) { | 688 | if (!*chptr) { |
689 | fprintf(stderr, "file name expected after %c\n", *src); | 689 | fprintf(stderr, "file name expected after %c\n", *src); |
690 | freeJob(job); | 690 | freeJob(job); |
691 | job->numProgs=0; | ||
691 | return 1; | 692 | return 1; |
692 | } | 693 | } |
693 | 694 | ||
@@ -704,8 +705,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
704 | if (*prog->argv[argc]) | 705 | if (*prog->argv[argc]) |
705 | argc++; | 706 | argc++; |
706 | if (!argc) { | 707 | if (!argc) { |
707 | fprintf(stderr, "empty command in pipe\n"); | 708 | fprintf(stderr, "empty command in pipe1.\n"); |
708 | freeJob(job); | 709 | freeJob(job); |
710 | job->numProgs=0; | ||
709 | return 1; | 711 | return 1; |
710 | } | 712 | } |
711 | prog->argv[argc] = NULL; | 713 | prog->argv[argc] = NULL; |
@@ -721,7 +723,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
721 | argc = 0; | 723 | argc = 0; |
722 | 724 | ||
723 | argvAlloced = 5; | 725 | argvAlloced = 5; |
724 | prog->argv = malloc(sizeof(*prog->argv) * argvAlloced); | 726 | prog->argv = xmalloc(sizeof(*prog->argv) * argvAlloced); |
725 | prog->argv[0] = ++buf; | 727 | prog->argv[0] = ++buf; |
726 | 728 | ||
727 | src++; | 729 | src++; |
@@ -729,7 +731,9 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
729 | src++; | 731 | src++; |
730 | 732 | ||
731 | if (!*src) { | 733 | if (!*src) { |
732 | fprintf(stderr, "empty command in pipe\n"); | 734 | fprintf(stderr, "empty command in pipe2\n"); |
735 | freeJob(job); | ||
736 | job->numProgs=0; | ||
733 | return 1; | 737 | return 1; |
734 | } | 738 | } |
735 | src--; /* we'll ++ it at the end of the loop */ | 739 | src--; /* we'll ++ it at the end of the loop */ |
@@ -746,13 +750,40 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
746 | case '\\': | 750 | case '\\': |
747 | src++; | 751 | src++; |
748 | if (!*src) { | 752 | if (!*src) { |
749 | freeJob(job); | ||
750 | fprintf(stderr, "character expected after \\\n"); | 753 | fprintf(stderr, "character expected after \\\n"); |
754 | freeJob(job); | ||
751 | return 1; | 755 | return 1; |
752 | } | 756 | } |
753 | if (*src == '*' || *src == '[' || *src == ']' | 757 | if (*src == '*' || *src == '[' || *src == ']' |
754 | || *src == '?') *buf++ = '\\'; | 758 | || *src == '?') *buf++ = '\\'; |
755 | /* fallthrough */ | 759 | /* fallthrough */ |
760 | case '`': | ||
761 | /* Exec a backtick-ed command */ | ||
762 | { | ||
763 | char* newcmd=NULL; | ||
764 | char* ptr=NULL; | ||
765 | struct job newJob; | ||
766 | |||
767 | ptr=strchr(++src, '`'); | ||
768 | if (ptr==NULL) { | ||
769 | fprintf(stderr, "Unmatched '`' in command\n"); | ||
770 | freeJob(job); | ||
771 | return 1; | ||
772 | } | ||
773 | |||
774 | newcmd = xmalloc(1+ptr-src); | ||
775 | snprintf(newcmd, 1+ptr-src, src); | ||
776 | |||
777 | if (!parseCommand(&newcmd, &newJob, jobList, isBg) && | ||
778 | newJob.numProgs) { | ||
779 | runCommand(&newJob, jobList, *isBg); | ||
780 | } | ||
781 | |||
782 | /* Clip out the the backticked command from the string */ | ||
783 | memmove(--src, ptr, strlen(ptr)+1); | ||
784 | free(newcmd); | ||
785 | } | ||
786 | break; | ||
756 | default: | 787 | default: |
757 | *buf++ = *src; | 788 | *buf++ = *src; |
758 | } | 789 | } |
@@ -771,12 +802,12 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
771 | prog->argv[argc] = NULL; | 802 | prog->argv[argc] = NULL; |
772 | 803 | ||
773 | if (!returnCommand) { | 804 | if (!returnCommand) { |
774 | job->text = malloc(strlen(*commandPtr) + 1); | 805 | job->text = xmalloc(strlen(*commandPtr) + 1); |
775 | strcpy(job->text, *commandPtr); | 806 | strcpy(job->text, *commandPtr); |
776 | } else { | 807 | } else { |
777 | /* This leaves any trailing spaces, which is a bit sloppy */ | 808 | /* This leaves any trailing spaces, which is a bit sloppy */ |
778 | count = returnCommand - *commandPtr; | 809 | count = returnCommand - *commandPtr; |
779 | job->text = malloc(count + 1); | 810 | job->text = xmalloc(count + 1); |
780 | strncpy(job->text, *commandPtr, count); | 811 | strncpy(job->text, *commandPtr, count); |
781 | job->text[count] = '\0'; | 812 | job->text[count] = '\0'; |
782 | } | 813 | } |
@@ -787,7 +818,7 @@ static int parseCommand(char **commandPtr, struct job *job, int *isBg) | |||
787 | } | 818 | } |
788 | 819 | ||
789 | 820 | ||
790 | static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | 821 | static int runCommand(struct job *newJob, struct jobSet *jobList, int inBg) |
791 | { | 822 | { |
792 | struct job *job; | 823 | struct job *job; |
793 | int i; | 824 | int i; |
@@ -800,8 +831,8 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
800 | 831 | ||
801 | 832 | ||
802 | nextin = 0, nextout = 1; | 833 | nextin = 0, nextout = 1; |
803 | for (i = 0; i < newJob.numProgs; i++) { | 834 | for (i = 0; i < newJob->numProgs; i++) { |
804 | if ((i + 1) < newJob.numProgs) { | 835 | if ((i + 1) < newJob->numProgs) { |
805 | pipe(pipefds); | 836 | pipe(pipefds); |
806 | nextout = pipefds[1]; | 837 | nextout = pipefds[1]; |
807 | } else { | 838 | } else { |
@@ -810,12 +841,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
810 | 841 | ||
811 | /* Check if the command matches any non-forking builtins */ | 842 | /* Check if the command matches any non-forking builtins */ |
812 | for (x = bltins; x->cmd; x++) { | 843 | for (x = bltins; x->cmd; x++) { |
813 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 844 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
814 | return (x->function(&newJob, jobList)); | 845 | return (x->function(newJob, jobList)); |
815 | } | 846 | } |
816 | } | 847 | } |
817 | 848 | ||
818 | if (!(newJob.progs[i].pid = fork())) { | 849 | if (!(newJob->progs[i].pid = fork())) { |
819 | signal(SIGTTOU, SIG_DFL); | 850 | signal(SIGTTOU, SIG_DFL); |
820 | 851 | ||
821 | if (nextin != 0) { | 852 | if (nextin != 0) { |
@@ -829,12 +860,12 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
829 | } | 860 | } |
830 | 861 | ||
831 | /* explicit redirections override pipes */ | 862 | /* explicit redirections override pipes */ |
832 | setupRedirections(newJob.progs + i); | 863 | setupRedirections(newJob->progs + i); |
833 | 864 | ||
834 | /* Check if the command matches any of the other builtins */ | 865 | /* Check if the command matches any of the other builtins */ |
835 | for (x = bltins_forking; x->cmd; x++) { | 866 | for (x = bltins_forking; x->cmd; x++) { |
836 | if (!strcmp(newJob.progs[i].argv[0], x->cmd)) { | 867 | if (!strcmp(newJob->progs[i].argv[0], x->cmd)) { |
837 | exit (x->function(&newJob, jobList)); | 868 | exit (x->function(newJob, jobList)); |
838 | } | 869 | } |
839 | } | 870 | } |
840 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL | 871 | #ifdef BB_FEATURE_SH_STANDALONE_SHELL |
@@ -842,24 +873,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
842 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently | 873 | /* TODO: Add matching when paths are appended (i.e. 'cat' currently |
843 | * works, but '/bin/cat' doesn't ) */ | 874 | * works, but '/bin/cat' doesn't ) */ |
844 | while (a->name != 0) { | 875 | while (a->name != 0) { |
845 | if (strcmp(newJob.progs[i].argv[0], a->name) == 0) { | 876 | if (strcmp(newJob->progs[i].argv[0], a->name) == 0) { |
846 | int argc; | 877 | int argc; |
847 | char** argv=newJob.progs[i].argv; | 878 | char** argv=newJob->progs[i].argv; |
848 | for(argc=0;*argv!=NULL; argv++, argc++); | 879 | for(argc=0;*argv!=NULL; argv++, argc++); |
849 | exit((*(a->main)) (argc, newJob.progs[i].argv)); | 880 | exit((*(a->main)) (argc, newJob->progs[i].argv)); |
850 | } | 881 | } |
851 | a++; | 882 | a++; |
852 | } | 883 | } |
853 | #endif | 884 | #endif |
854 | 885 | ||
855 | execvp(newJob.progs[i].argv[0], newJob.progs[i].argv); | 886 | execvp(newJob->progs[i].argv[0], newJob->progs[i].argv); |
856 | fatalError("%s: %s\n", newJob.progs[i].argv[0], | 887 | fatalError("%s: %s\n", newJob->progs[i].argv[0], |
857 | strerror(errno)); | 888 | strerror(errno)); |
858 | } | 889 | } |
859 | 890 | ||
860 | /* put our child in the process group whose leader is the | 891 | /* put our child in the process group whose leader is the |
861 | first process in this pipe */ | 892 | first process in this pipe */ |
862 | setpgid(newJob.progs[i].pid, newJob.progs[0].pid); | 893 | setpgid(newJob->progs[i].pid, newJob->progs[0].pid); |
863 | 894 | ||
864 | if (nextin != 0) | 895 | if (nextin != 0) |
865 | close(nextin); | 896 | close(nextin); |
@@ -871,24 +902,24 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
871 | nextin = pipefds[0]; | 902 | nextin = pipefds[0]; |
872 | } | 903 | } |
873 | 904 | ||
874 | newJob.pgrp = newJob.progs[0].pid; | 905 | newJob->pgrp = newJob->progs[0].pid; |
875 | 906 | ||
876 | /* find the ID for the job to use */ | 907 | /* find the ID for the job to use */ |
877 | newJob.jobId = 1; | 908 | newJob->jobId = 1; |
878 | for (job = jobList->head; job; job = job->next) | 909 | for (job = jobList->head; job; job = job->next) |
879 | if (job->jobId >= newJob.jobId) | 910 | if (job->jobId >= newJob->jobId) |
880 | newJob.jobId = job->jobId + 1; | 911 | newJob->jobId = job->jobId + 1; |
881 | 912 | ||
882 | /* add the job to the list of running jobs */ | 913 | /* add the job to the list of running jobs */ |
883 | if (!jobList->head) { | 914 | if (!jobList->head) { |
884 | job = jobList->head = malloc(sizeof(*job)); | 915 | job = jobList->head = xmalloc(sizeof(*job)); |
885 | } else { | 916 | } else { |
886 | for (job = jobList->head; job->next; job = job->next); | 917 | for (job = jobList->head; job->next; job = job->next); |
887 | job->next = malloc(sizeof(*job)); | 918 | job->next = xmalloc(sizeof(*job)); |
888 | job = job->next; | 919 | job = job->next; |
889 | } | 920 | } |
890 | 921 | ||
891 | *job = newJob; | 922 | *job = *newJob; |
892 | job->next = NULL; | 923 | job->next = NULL; |
893 | job->runningProgs = job->numProgs; | 924 | job->runningProgs = job->numProgs; |
894 | job->stoppedProgs = 0; | 925 | job->stoppedProgs = 0; |
@@ -897,13 +928,13 @@ static int runCommand(struct job newJob, struct jobSet *jobList, int inBg) | |||
897 | /* we don't wait for background jobs to return -- append it | 928 | /* we don't wait for background jobs to return -- append it |
898 | to the list of backgrounded jobs and leave it alone */ | 929 | to the list of backgrounded jobs and leave it alone */ |
899 | printf("[%d] %d\n", job->jobId, | 930 | printf("[%d] %d\n", job->jobId, |
900 | newJob.progs[newJob.numProgs - 1].pid); | 931 | newJob->progs[newJob->numProgs - 1].pid); |
901 | } else { | 932 | } else { |
902 | jobList->fg = job; | 933 | jobList->fg = job; |
903 | 934 | ||
904 | /* move the new process group into the foreground */ | 935 | /* move the new process group into the foreground */ |
905 | /* suppress messages when run from /linuxrc mag@sysgo.de */ | 936 | /* suppress messages when run from /linuxrc mag@sysgo.de */ |
906 | if (tcsetpgrp(0, newJob.pgrp) && errno != ENOTTY) | 937 | if (tcsetpgrp(0, newJob->pgrp) && errno != ENOTTY) |
907 | perror("tcsetpgrp"); | 938 | perror("tcsetpgrp"); |
908 | } | 939 | } |
909 | 940 | ||
@@ -982,9 +1013,11 @@ static int busy_loop(FILE * input) | |||
982 | nextCommand = command; | 1013 | nextCommand = command; |
983 | } | 1014 | } |
984 | 1015 | ||
985 | if (!parseCommand(&nextCommand, &newJob, &inBg) && | 1016 | if (!parseCommand(&nextCommand, &newJob, &jobList, &inBg) && |
986 | newJob.numProgs) { | 1017 | newJob.numProgs) { |
987 | runCommand(newJob, &jobList, inBg); | 1018 | runCommand(&newJob, &jobList, inBg); |
1019 | } else { | ||
1020 | nextCommand=NULL; | ||
988 | } | 1021 | } |
989 | } else { | 1022 | } else { |
990 | /* a job is running in the foreground; wait for it */ | 1023 | /* a job is running in the foreground; wait for it */ |