#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#define PIPE_R 0
#define PIPE_W 1
#define MAX(a,b) ((a>b)?(a):(b))
/* map the appropriate ends of the pipes to stdin and stdout */
/* then start the 'vi' process to edit a file */
void server ( int cli2ser[2], int ser2cli[2] ) {
int res;
char *cmd[] = { "/bin/vi", "tmp", NULL };
int to_client = ser2cli[PIPE_W];
int from_client = cli2ser[PIPE_R];
close( cli2ser[PIPE_W] );
close( ser2cli[PIPE_R] );
close( STDIN_FILENO );
res = dup( from_client ); /* stdin reopened as one end of a pipe */
if ( res == -1 ) {
perror( "dup 1" );
} else {
fprintf( stderr, "Duped %d\n", res );
}
close( STDOUT_FILENO );
res = dup( to_client ); /* stdout reopened as one end of a pipe */
if ( res == -1 ) {
perror( "dup 2" );
} else {
fprintf( stderr, "Duped %d\n", res );
}
res = execv( cmd[0], cmd );
perror( "exec failed" );
}
/* in_fd and out_fd are the connections to the outside world */
/* cli2ser and ser2cli are the pipes to the server */
/* this function loops, copying data between the server and the outside world */
void client ( int in_fd, int out_fd, int cli2ser[2], int ser2cli[2], pid_t server_pid ) {
char buff[BUFSIZ];
int to_server = cli2ser[PIPE_W];
int from_server = ser2cli[PIPE_R];
fd_set master_read_fds;
fd_set read_fds;
int max_fd;
close( cli2ser[PIPE_R] );
close( ser2cli[PIPE_W] );
/* select needs the maximum fd + 1 */
printf( "FD's=%d,%d,%d,%d\n", in_fd, out_fd, to_server, from_server );
max_fd = in_fd;
max_fd = MAX(max_fd,from_server);
max_fd++;
FD_ZERO( &master_read_fds );
FD_SET( in_fd, &master_read_fds );
FD_SET( from_server, &master_read_fds );
while ( 1 ) {
int n;
read_fds = master_read_fds;
n = select( max_fd, &read_fds, NULL, NULL, NULL ); /* wait for something to happen */
if(0)fprintf( stderr, "Select returned %d\n", n );
if ( n == -1 ) {
perror( "select" );
break; /* escape from infinity */
}
if ( FD_ISSET( in_fd, &read_fds ) ) {
ssize_t amount;
amount = read( in_fd, buff, BUFSIZ );
if(0)fprintf( stderr, "%d bytes from input to server\n", amount );
if ( amount == 0 ) {
fprintf( stderr, "EOF from input" );
break;
}
if ( amount == -1 ) {
perror( "error reading input" );
break;
}
if ( amount != write( to_server, buff, amount ) ) {
perror( "write to server error" );
}
}
if ( FD_ISSET( from_server, &read_fds ) ) {
ssize_t amount;
amount = read( from_server, buff, BUFSIZ );
if(0)fprintf( stderr, "%d bytes from server to output\n", amount );
if ( amount == 0 ) {
fprintf( stderr, "EOF from server" );
break;
}
if ( amount == -1 ) {
perror( "error reading server" );
break;
}
if ( amount != write( out_fd, buff, amount ) ) {
perror( "write to out error" );
}
}
}
}
int main ( ) {
int client_to_server[2];
int server_to_client[2];
int status;
pid_t pid;
status = pipe( client_to_server );
if ( status == -1 ) {
perror( "Cant create client_to_server pipes" );
return EXIT_FAILURE;
}
printf( "client_to_server pipe FD's=%d,%d\n", client_to_server[0], client_to_server[1] );
status = pipe( server_to_client );
if ( status == -1 ) {
perror( "Cant create server_to_client pipes" );
return EXIT_FAILURE;
}
printf( "server_to_client pipe FD's=%d,%d\n", server_to_client[0], server_to_client[1] );
pid = fork();
if ( pid == (pid_t)-1 ) {
perror( "Cant create process" );
return EXIT_FAILURE;
}
if ( pid == 0 ) {
/* child */
server( client_to_server, server_to_client );
} else {
/* parent */
client( STDIN_FILENO, STDOUT_FILENO, client_to_server, server_to_client, pid );
}
return 0;
}