linux - Implementing unlimited piping in shell using C -
i'm trying implement c shell allows unlimited unidirectional pipes using character '>'
so can handle ls -a > tail > grep '.zip'
i understand pipes supposed talk between processes, thought came idea use 1 pipe , multiple children.
this have far
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <stdlib.h> /*#include <wait.h>*/ char *args[1000][1000];//array of arguments int args_count = 0;//count of arguments in array int runcommand(char **arguments, int *fd, int pipehassomedata, int basecase) { pid_t pid; int x = 0; int status; pid = fork(); if(pid != 0) { waitpid(pid, &status, 0); if(basecase) { if(wifexited(status)) { if(wexitstatus(status) == 0) { /*it worked*/ } else if(wexitstatus(status) == 255) { printf("the program %s not exist \n", arguments[0]); } else { printf("error: error code: %d", wexitstatus(status)); } } else { printf("there problem not normal"); } printf("\n \n"); } return 1; } else { if(pipehassomedata == 1) {// read pipe dup2(fd[0], 0);//read pipe } if(basecase == 0) {// not base case dup2(fd[1], 1);//write pipe } else { close(fd[1]);//close write } exit(execvp(arguments[0], arguments)); return 0; } } int execute_commands(char *arguments[1000][1000], int pd[2] = null) { int current_count = args_count; int iterator = 0; int fd[2]; int useapipeincommand = 0; pipe(fd); while(iterator <= args_count) {//go through , execute commands if(current_count == 0) {//base case return runcommand(arguments[iterator], fd, useapipeincommand, 1); } else { runcommand(arguments[iterator], fd, useapipeincommand, 0); useapipeincommand = 1; } iterator++; current_count--; }//end while return 1; } int main () { int = 0; char text[1024]; /* input line */ char *tok2; while (1) { /* repeat until done .... */ fflush(stdin); fflush(stdout); printf("shell -> "); /* display prompt */ *text = 0; fgets(text, sizeof text, stdin); /* read in command line */ fflush(stdout); printf("\n"); char * tok = strtok(text, " \n\t"); if (strcmp(tok, "exit") == 0) { /* "exit"? */ return 0; /* exit if */ } if (strcmp(tok, " ") == 0) { /* "exit"? */ continue; /* exit if */ } tok2 = tok; memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear arguments array args_count = 0; int count = 0; while(tok2 != null) { if(strcmp(tok2, ">") != 0) { args[args_count][count] = tok2; count++; tok2 = strtok(null, " \n\t"); } else {//pipe found, argument counter , set count 0 args[args_count][count] = null; args_count++; count = 0; tok2 = strtok(null, " \n\t"); } } args[args_count][count] = null; execute_commands(args); }//end while return 0; } it running single base case no problem shell freezes when pipe. ideas on issue?
correct answer comments @beau-bouchard , @rici:
pipes have (small) finite buffer; cannot write more little bit pipe without blocking unless other end of pipe being read.
for correct implementation, check out "multiple pipes in c" coding multiple pipe in c
--update:
here final working code having similar issue:
#include <stdio.h> #include <sys/types.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <wait.h> int read = 0; int write = 1; char *args[1000][1000];//array of arguments int args_count = 0;//count of arguments in array int execute_commands(char *arguments[1000][1000]) { int pd[2]; int iterator = 0; int fd[2]; int f_in = 0; while(iterator <= args_count) {//go through , execute commands pid_t pid; int status; pipe(fd); pid = fork(); if(pid != 0) { waitpid(pid, &status, 0);//wait child exit close(fd[write]);//close writing end if(wifexited(status)) { if(wexitstatus(status) == 0) { /*it worked*/ } else if(wexitstatus(status) == 255) { printf("the program %s not exist \n", arguments[iterator][0]); } else { printf("error: error code: %d", wexitstatus(status)); } } else { printf("there problem not normal %d", status); } f_in = fd[read];//set pipe in if(iterator == args_count) { printf("\n \n"); } //return 1; } else { dup2(f_in, 0); if(iterator != args_count) {//its not main value dup2(fd[write], 1);//write pipe } close(fd[read]); exit(execvp(arguments[iterator][0], arguments[iterator])); return 0; } iterator++; }//end while return 1; } int main () { int = 0; char text[1024]; /* input line */ char *tok2; while (1) { /* repeat until done .... */ fflush(stdin); fflush(stdout); printf("shell -> "); /* display prompt */ *text = 0; fgets(text, sizeof text, stdin); /* read in command line */ fflush(stdout); printf("\n"); char * tok = strtok(text, " \n\t"); if (strcmp(tok, "exit") == 0) { /* "exit"? */ return 0; /* exit if */ } if (strcmp(tok, " ") == 0) { /* "exit"? */ continue; /* exit if */ } tok2 = tok; memset(args, 0, sizeof(args[0][0]) * 1000 * 1000);//clear arguments array args_count = 0; int count = 0; while(tok2 != null) { if(strcmp(tok2, ">") != 0) { args[args_count][count] = tok2; count++; tok2 = strtok(null, " \n\t"); } else {//pipe found, argument counter , set count 0 args[args_count][count] = null; args_count++; count = 0; tok2 = strtok(null, " \n\t"); } } args[args_count][count] = null; execute_commands(args); }//end while return 0; }
Comments
Post a Comment