static inline void _strtoupper(char *s)
{
do *s = toupper(*s); while (*s ++);
}
int main(void)
{
pid_t pid = 0;
char buf[BUFSIZ]; /* buffer de lecture */
int in[2], out[2]; /* les pipes */
fd_set fd;
struct timeval tmout;
int run = 20; /* nombre de tours */
int len = 0; /* retour de read */
/* ouvre les pipe d'input/output */
if (pipe(in) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
if (pipe(out) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
case 0: /* papa */
/* on veut ecrire dans l'input, et lire dans l'output (point de vue fiston) */
close(in[0]); close(out[1]);
if (dup2(out[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(in[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
/* ecrit un message d'initialisation au bout de cinq secondes */
sleep(5);
printf("salut fiston !");
fflush(stdout);
break;
default: /* fiston */
/* on veut lire dans l'input, et ecrire dans l'output */
close(in[1]); close(out[0]);
if (dup2(in[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(out[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
}
/* boucle de lecture/ecriture commune */
while (run --) {
/* une seconde de timeout */
tmout.tv_sec = 1;
tmout.tv_usec = 0;
/* c'est pas portable de faire ca avec le vrai stdin, mais la c'est notre pipe */
FD_SET(STDIN_FILENO, & fd);
[^] # Re: Details
Posté par JaguarWan . En réponse au message [C Posix] Histoire de fork de pipe et de select. Évalué à 2.
/* gcc -W -Wall -std=c99 -posix -pedantic posix.c */
#define _BSD_SOURCE
#define _ISOC99_SOURCE
#include <stdlib.h> /* libc */
#include <unistd.h> /* pipe(), fork(), *_FILENO ... */
#include <stdio.h> /* printf(), BUFSIZ, ... */
#include <ctype.h> /* toupper() */
#include <string.h> /* memset() */
#include <sys/types.h> /* pid_t, ... */
#include <sys/wait.h>
#define STRINGIFY(x) #x
#define STR(x) STRINGIFY(x)
#define ERR(c, f) #c "()::" #f "() @ " __FILE__ ":" STR(__LINE__)
static inline void _strtoupper(char *s)
{
do *s = toupper(*s); while (*s ++);
}
int main(void)
{
pid_t pid = 0;
char buf[BUFSIZ]; /* buffer de lecture */
int in[2], out[2]; /* les pipes */
fd_set fd;
struct timeval tmout;
int run = 20; /* nombre de tours */
int len = 0; /* retour de read */
/* ouvre les pipe d'input/output */
if (pipe(in) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
if (pipe(out) == -1) {
perror(ERR(main, pipe)); exit(EXIT_FAILURE);
}
/* pipe[0] = lecture, pipe[1] = ecriture */
switch ( (pid = fork()) ) {
case -1: /* failed */
close(in[0]); close(in[1]);
close(out[0]); close(out[1]);
exit(EXIT_FAILURE);
case 0: /* papa */
/* on veut ecrire dans l'input, et lire dans l'output (point de vue fiston) */
close(in[0]); close(out[1]);
if (dup2(out[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(in[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
/* ecrit un message d'initialisation au bout de cinq secondes */
sleep(5);
printf("salut fiston !");
fflush(stdout);
break;
default: /* fiston */
/* on veut lire dans l'input, et ecrire dans l'output */
close(in[1]); close(out[0]);
if (dup2(in[0], STDIN_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
if (dup2(out[1], STDOUT_FILENO) == -1) {
perror(ERR(main, dup2)); exit(EXIT_FAILURE);
}
}
/* boucle de lecture/ecriture commune */
while (run --) {
/* une seconde de timeout */
tmout.tv_sec = 1;
tmout.tv_usec = 0;
/* c'est pas portable de faire ca avec le vrai stdin, mais la c'est notre pipe */
FD_SET(STDIN_FILENO, & fd);
if (select(1, & fd, NULL, NULL, & tmout) == -1) {
perror(ERR(main, select)); exit(EXIT_FAILURE);
}
if (FD_ISSET(STDIN_FILENO, & fd)) {
memset(buf, '0円', sizeof(buf));
if ( (len = read(STDIN_FILENO, buf, sizeof(buf))) == -1) {
perror(ERR(main, read)); exit(EXIT_FAILURE);
}
if (len == 0) {
fprintf(stderr, "%s: connection morte\n", (pid) ? "fiston" : "papa");
break;
}
if (pid == 0) {
/* papa */
fprintf(stderr, "Le fiston a ecrit: %s\n", buf);
printf("met-moi ca en caps fiston...");
fflush(stdout);
} else {
/* fiston */
_strtoupper(buf);
printf("%s", buf);
fflush(stdout);
}
} else {
fprintf(stderr, "%s: j'ai rien a faire !\n", (pid) ? "fiston" : "papa");
}
}
/* normalement le fils creve toujours avant, mais soyons propre */
if (pid == 0) wait(NULL);
/* vu qu'on a branche les pipe sur stdin/out, cleanup automatique */
exit(EXIT_SUCCESS);
}