开发者

pipe, fork and shell commands in C

I am trying to reproduce the pipes in a shell. for example ls | sort At first I am trying the pipes but I can't get the parent to read the result of what the child has executed:

//pipes essai
# include <stdio.h>
# include <stdlib.h>
# include <unistd.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <assert.h>
# include <string.h>
# include <sys/stat.h>
# include <fcntl.h>

enum {
MaxLigne = 1024, // longueur max d'une ligne de commandes
MaxMot = MaxLigne / 2, // nbre max de mot dans la ligne
MaxDirs = 100, // nbre max de repertoire dans PATH
MaxPathLength = 512,
 // longueur max d'un nom de fichier
 };

void decouper(char *, char *, char **, int);
int spawn(char * pathname, char * mot[]);

# define PROMPT "? "

int main(int argc, char * argv[]) {
char ligne[MaxLigne];
char pathname[MaxPathLength];
char * mot[MaxMot];
char * dirs[MaxDirs];
int i, tmp, x;
int fd[2];
int t, res = 0;
char buf[1024];
char * mot2[10];

/* Decouper PATH en repertoires */
decouper(getenv("PATH"), ":", dirs, MaxDirs);

/* read the command lines and try to execute them */
for (printf(PROMPT); fgets(ligne, sizeof ligne, stdin) != 0; printf(PROMPT)) {
    decouper(ligne, " \t\n", mot, MaxMot);
    if (mot[0] == 0) // empty line
        continue;

        //launch the pipe
        int p=pipe(fd);
        assert(p>=0);


        tmp = fork(); // launch the pipe process
        if (tmp < 0) {
            perror("fork");
            continue;
        }

      开发者_JAVA技巧  if (tmp != 0) { // parent wait for end of child

            //close this side of the pipe
            close(fd[1]);
            //waiting
            while (wait(0) != tmp)
                ;
            //when finish waiting read what the child has written in the pipe
            read(fd[0], buf, sizeof(buf));
            //print the result
            printf("read %s\n", buf);
            //get back the hand to the user
            continue;

        }else if (tmp==0){

        // child

        //close this side of the pipe
        close(fd[0]);
        //close stdout
        t=close(1);
        //make sur stdout is closed
        assert(t>=0);
        //open the pipe for writing in it instead of in the stdout
        FILE * sortie=fdopen(fd[1], O_WRONLY);
        //make sure it is ok
        assert(sortie!=NULL);

        //try to execute the command
        for (i = 0; dirs[i] != 0; i++) {
            snprintf(pathname, sizeof pathname, "%s/%s", dirs[i], mot[0]);
            execv(pathname, mot);

        }
        }

        // if exec was unsuccessful
        fprintf(stderr, "%s: not found\n", mot[0]);
        exit(1);

}

    printf("Bye\n");
    return 0;

}

void decouper(char * ligne, char * separ, char * mot[], int maxmot){
int i;

mot[0] = strtok(ligne, separ);
for(i = 1; mot[i - 1] != 0; i++){
if (i == maxmot){
  fprintf(stderr, "Erreur dans la fonction decouper: trop de mots\n");
  mot[i - 1] = 0;
 }
 mot[i] = strtok(NULL, separ);
}
}

there is a problem with this line FILE * sortie=fdopen(fd[1], O_WRONLY);

pipe1.c: In function ‘main’: pipe1.c:81:4: warning: passing argument 2 of ‘fdopen’ makes pointer from integer without a cast /usr/include/stdio.h:303:14: note: expected ‘const char *’ but argument is of type ‘int’

but how can I make the child to output in the pipe??? freopen doesn't work either

the result I get: ? ls read

which means of course nothing is read. What can I do I am really out of ideas now??? thank you very much in advance


A separate problem...

If the child writes a lot of output to the pipe, it'll block until the parent reads some. Pipes have limited capacity (laziness prevents me from looking up typical limit).

Your parent code doesn't do any reading until the child exits. But if the child blocks on pipe output, it'll never exit. Deadlock!


You are confusing the signature of fdopen with that of open. fdopen takes a const char* as its second parameter. Try

FILE * sortie=fdopen(fd[1], "w");

Reference:

  • http://linux.die.net/man/3/fdopen


EDIT: It appears that you are using fdopen for no valid reason. Specifically, I don't see any use of sortie after it is initialized.

I presume that you are trying to set up standard out for the exec'd program. If that is the case, you should use dup or dup2:

close(fd[0]);
close(1);
dup(fd[1]);
close(fd[1]);

//try to execute the command
... as before

Reference:

  • http://linux.die.net/man/2/dup
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜