Thread: help with pipes/fork

  1. #1
    Registered User
    Join Date
    Mar 2011
    Posts
    29

    Exclamation help with pipes/fork

    i am trying to use pipes/forks to imitate the system command in bash shell, using C programming
    so far i have
    Code:
    int sys_new(char *comm) {
        char pipeout[512];
        int fd[2], status;
        pipe(fd);
        pid_t pid = fork();
        if (pid == 0) { 
            dup2(fd[1], fileno(stdout));
            close(fd[0]); close(fd[1]);
            execl("/bin/sh", "/bin/sh", "-c", comm, NULL);
        }
        else if (pid > 0) { 
            wait(&status);
            dup2(fd[0], fileno(stdin));
            read(fd[0], pipeout, 512);
            close(fd[0]); close(fd[1]);
            printf(pipeout);
            printf("\n");
            printf("%d\n", WEXITSTATUS(status));
        }
        else {
            perror("fork"); exit(1);
        }
        return 0;
    }
    The output is sorta correct, i gave the input command to be ls, the output was
    my_prog.c
    my_prog
    abc
    ñà·
    EÉ÷·8É÷·*à·
    0

    The zero come up since ls was successfull, but i dont understand why the files in the directory came up line by line and not all in one line like how normally doing ls would result in, also theres some gibberish lines after the ls command results, why did that show up? Am I missing a \0 anywhere or something?

    Also i tried giving a command that would fail like cd ffg, and the WEXITSTATUS number came out to be 2, so what really are the possible outcomes for WEXITSTATUS? i only know so far 0 and 2, shouldnt it be -1 instead of 2?

  2. #2
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    Code:
    dup2(fd[0], fileno(stdin));
    This is unnecessary, because you never read from standard input. In fact, this is probably a bad idea because later on in your code, standard input will be hooked up to the end of a closed pipe.
    Code:
    read(fd[0], pipeout, 512);
    You almost always want to check the return value of your functions. How many bytes did read() actually read? This is important. Even if read() is successful, it will not add a terminating null character unless it reads one. Your code does not send a null character, so when you read into pipeout, you're not creating a string! You need to see how many bytes read() returns, and stick a null character (that is, a character with value 0) right after the last byte.
    Code:
    close(fd[1]);
    This needs to be closed before you try to read from fd[0]. You really don't want two writers on one end of the pipe when you're trying to read from it.
    Code:
    printf(pipeout);
    Never call printf() like this, especially with a string you received from the outside world. What if it contains % characters? printf() will go crazy. Use printf("%s", pipeout). Or, since you want a newline, just puts(pipeout).
    Code:
    execl("/bin/sh", "/bin/sh", "-c", comm, NULL);
    As somewhat of a nitpick, that should be (char *)NULL, not just NULL. It probably won't matter on a 32-bit system, but can have bad effects on a 64-bit system.
    Also i tried giving a command that would fail like cd ffg, and the WEXITSTATUS number came out to be 2, so what really are the possible outcomes for WEXITSTATUS? i only know so far 0 and 2, shouldnt it be -1 instead of 2?
    0 to 255. 0 is success, anything else is failure. sh -c "cd ffg" will return 2 (as in exit(2)). Try a command of "false", which will probably exit with a value of 1. exit(-1) will be treated as exit(255) since only the bottom 8 bits of the exit value are actually used.

  3. #3
    Registered User
    Join Date
    Mar 2011
    Posts
    29
    ok i got to work, but theres one problem

    i tried the command was cd abc';' ls
    but i am still in the same directory, is this because the child process ran the exec1 command? if so then if i reverse it so the parent does what the child did and child does what the parent did, then will the cd abc';' ls actually move it to the abc directory?

Popular pages Recent additions subscribe to a feed