Unix/Linux

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • pipin' problems - stdin & stdout messed up after executing piped command

    1 answers - 5825 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    hi
    iv been writing this lightweight shell. just finished writing a
    function to implement piping.
    the problem is that everytime i call a piped command, the command
    executes ok, but afterwards stdin and stout get thrown for a toss.
    for example, the prompt doesnt show up. then, if i do enter a command,
    both the prompt and command output show up as complete output. i figure
    there's a problem with my file descriptor handling in the piping
    function.
    flushing stdin and stdout dont seem to solve the problem.
    code below.
    swagat
    p.s. the shell aint complete yet the redirections havent been
    implemented, and there are probably fallacies in the main fn.
    #include <stdio.h>
    #include <string.h>
    #include <unistd.h>
    #define CMMLINESIZ 300 /* Size of command input line/buffer */
    #define CMMTKMAX 20 /* Maximum no. of tokens in command input line
    */
    #define CMMINDIVMAX 20 /* Maximum no. of individulal commands in input
    line */
    int status;
    void prompt() {
    fprintf(stdout, "%s:%s$ ", getlogin(), get_current_dir_name());
    fflush(stdout);
    }
    void tokenize(char *commandLine, char **commandTokens, char
    *separators) {
    int index; /* Index for parsing */
    commandTokens[0] = strtok(commandLine, separators);
    for (index = 1; index < CMMTKMAX; index++) {
    commandTokens[index] = strtok(NULL, separators);
    if (commandTokens[index] == NULL)
    break;
    }
    }
    int individualCommandsFn(char *commandLine, char **individualCommands)
    {
    char *separators = ";";
    int Commands;
    individualCommands[0] = strtok(commandLine, separators);
    for (Commands = 1; Commands < CMMINDIVMAX ;
    Commands++) {
    individualCommands[Commands] = strtok(NULL, separators);
    if (individualCommands[Commands] == NULL)
    break;
    }
    return Commands;
    }
    void execute(char *commandLine) {
    char *commandTokens[CMMTKMAX]; /* Command input line tokens */
    char *separators = " \t\n"; /* Command input token separators */
    int pid, wpid; /* Process ids */
    tokenize(commandLine, commandTokens, separators);
    switch (pid = fork()) {
    case -1:
    break;
    case 0:
    execvp(commandTokens[0], commandTokens);
    default:
    wpid = wait(0);
    if (wpid < 0)
    fprintf(stdout, "%s: Invalid command\n", commandTokens[0]);
    break;
    };
    }
    void executePipedCommand(char *commandLine) {
    char *prePipeCommandTokens[CMMTKMAX],
    *postPipeCommandTokens[CMMTKMAX], *pipeIndex;
    char *separators = " \t\n";
    int pid, pid2, wpid;
    int pfd[2];
    pipe(pfd);
    pipeIndex = strchr(commandLine, '|');
    *pipeIndex = '\0';
    pipeIndex++;
    tokenize(commandLine, prePipeCommandTokens, separators);
    tokenize(pipeIndex, postPipeCommandTokens, separators);
    pid = fork();
    if (pid == 0) {
    close(pfd[1]);
    dup2(pfd[0], 0);
    close(pfd[0]);
    execvp(postPipeCommandTokens[0], postPipeCommandTokens);
    } else {
    pid2 = fork();
    if (pid2 == 0) {
    close(pfd[0]);
    dup2(pfd[1], 1);
    close(pfd[1]);
    execvp(prePipeCommandTokens[0], prePipeCommandTokens);
    } else {// I THINK THE PRBLEM IS SMEWHERE HERE!!!!
    close(pfd[0]);
    close(pfd[1]);
    wpid = wait(0);
    }
    }
    }
    void executeIPRedirCommand(char *commandLine) {
    }
    void PRedirCommand(char *commandLine) {
    }
    int isPipingFn(char *commandLine, int *isPiping) {
    char *pipingF, *pipingL;
    if (pipingF = strchr(commandLine, '|')) {
    pipingL = strrchr(commandLine, '|');
    if (pipingF != pipingL) {
    fprintf(stdout, "Multilevel piping not supported\n");
    *isPiping = -1;
    } else *isPiping = 1;
    }
    return *isPiping;
    }
    int PRedirectionFn(char *commandLine, int *PRedirection) {
    char *opRedirF, *opRedirL;
    if (opRedirF = strchr(commandLine, '>')) {
    opRedirL = strrchr(commandLine, '>');
    if (opRedirF != opRedirL) {
    fprintf(stdout, "Multilevel output redirection not supported\n");
    *PRedirection = -1;
    } else *PRedirection = 1;
    }
    return *PRedirection;
    }
    int isIPRedirectionFn(char *commandLine, int *isIPRedirection) {
    char *ipRedirF, *ipRedirL;
    if (ipRedirF = strchr(commandLine, '<')) {
    ipRedirL = strrchr(commandLine, '<');
    if (ipRedirF != ipRedirL) {
    fprintf(stdout, "Multilevel input redirection not supported\n");
    *isIPRedirection = -1;
    } else *isIPRedirection = 1;
    }
    return *isIPRedirection;
    }
    int main() {
    char commandLine[CMMLINESIZ]; /* Command input line/buffer */
    char *individualCommands[CMMINDIVMAX];
    int isPiping, isIPRedirection, PRedirection, Commands, i;
    while(1) {
    prompt();
    fgets(commandLine, CMMLINESIZ, stdin);
    fflush(stdin);
    if (commandLine[0] == '#' || commandLine[0] == '\n')
    continue;
    Commands = individualCommandsFn(commandLine,
    individualCommands);
    for (i = 0; i < Commands; i++) {
    isPiping = isPipingFn(individualCommands[i], &isPiping);
    isIPRedirection = isIPRedirectionFn(individualCommands[i],
    &isIPRedirection);
    PRedirection = PRedirectionFn(individualCommands[i],
    &PRedirection);
    if (isPiping == -1 || isIPRedirection == -1 || PRedirection ==
    -1){
    continue;
    }
    if (isPiping)
    executePipedCommand(individualCommands[i]);
    else if (isIPRedirection)
    executeIPRedirCommand(individualCommands[i]);
    else if (PRedirection)
    PRedirCommand(individualCommands[i]);
    else execute(individualCommands[i]);
    isPiping = isIPRedirection = PRedirection = 0;
    }
    }
    return 0;
    }
  • No.1 | | 1234 bytes | |

    Tue, 22 Nov 2005 01:54:39 -0800, swagat.dasgupta wrote:

    hi

    iv been writing this lightweight shell. just finished writing a
    function to implement piping.

    the problem is that everytime i call a piped command, the command
    executes ok, but afterwards stdin and stout get thrown for a toss.

    for example, the prompt doesnt show up. then, if i do enter a command,
    both the prompt and command output show up as complete output. i figure
    there's a problem with my file descriptor handling in the piping
    function.

    flushing stdin and stdout dont seem to solve the problem.

    code below.

    The traditional way to do this is the following pseudo-code

    If isPiping
    fork
    if parent then wait
    else
    pipe
    fork
    if child
    rearrange file descriptors
    exec one side of pipe
    else
    rearrange file descriptors
    exec other side of pipe
    endif
    endif
    endif

    Note that you fork first, then pipe, then fork, rather than pipe, fork, fork.

    course on of the things that made ksh a more efficient shell than the
    original bourne shell was that it would look at the RHS of a pipe and
    see if it could avoid one of the forks.

Re: pipin' problems - stdin & stdout messed up after executing piped command


max 4000 letters.
Your nickname that display:
In order to stop the spam: 1 + 0 =
QUESTION ON "Unix/Linux"

EMSDN.COM