>>12
Open sauce...
Btw. As i said this, is a assignment in a OS course im taking,
so this stuff is not really usefull for much.
As you might also se im currently not doing any wait() since im not sure how to implement that in this crappy solution.
The main code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include "digenv_helper.h"
int setup_piping( char* greparg )
{
int to_printenv[2] = { -1, -1 };
int from_printenv[2] = { -1, -1 };
int from_grep[2] = { -1, -1 };
int from_sort[2] = { -1, -1 };
char* cmd_arg1[] = { "printenv", NULL };
char* cmd_arg2[] = { "grep", greparg, NULL };
char* cmd_arg3[] = { "sort", NULL };
char* cmd_arg4[] = { "less", NULL };
create_pipe( to_printenv );
create_pipe( from_printenv );
create_pipe( from_grep );
create_pipe( from_sort );
pipe_exec( cmd_arg1, to_printenv, from_printenv);
pipe_exec( cmd_arg2, from_printenv, from_grep );
pipe_exec( cmd_arg3, from_grep, from_sort );
/* The end of the last pipe is stdin */
dup2( from_sort[0], 0 );
close( to_printenv[0] );
/* LESS */
execvp( cmd_arg4[0], cmd_arg4 );
return 0;
}
int main( int argc, char** argv )
{
char* greparg;
if( argc > 1 )
greparg = argv[1];
else
greparg = "";
if( setup_piping( greparg ) < 0 )
fprintf( stderr, "The pipes are no more..." );
return 0;
}
------------------------------------------
The helper module:
#include "digenv_helper.h"
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
/** Prints an error message based on the value of errno and exits.
** @param src Description of the action that failed.
**/
void error(char* src)
{
fprintf(stderr, "%s failed with error: %s \n", src, strerror(errno));
exit(1);
}
/** Waits for a process to exit and prints a message if exitstatus was non-zero.
**/
void waitfor(int pid) {
int status;
if (waitpid(pid, &status, 0) == -1) error("waitpid");
if (status != 0) {
fprintf(stderr, "process with pid %d returned exitstatus: %d", pid, status);
exit(1);
}
}
/**
** Spawn a new daemon and connect pipes to it's stdin and stdout.
**
** @param stdin The child's new stdin.
** @param stdout The child's new stdout.
** @return If all went well the return in the parent process is the pid \\
** of the child and zero in the child process. If something went wrong \\
** the value returned is -1. This is the value returned from fork().
**/
int spawn( int* to_pipe, int* from_pipe )
{
int pid = fork();
if( pid == 0 )
{ /* This process is the child */
/* Attach the new stdout/pipe */
if( from_pipe[0] != 1 )
{
dup2( from_pipe[1], 1 );
close( from_pipe[1] );
}
/* Attach the new stdin/pipe */
if( to_pipe[1] != 0 )
{
dup2( to_pipe[0], 0 );
close( to_pipe[0] );
}
close( to_pipe[1] );
close( from_pipe[0] );
} else { /* Parent */
/* Close the unused file descriptors */
close( to_pipe[0] );
close( from_pipe[1] );
}
return pid;
}
/**
** Create a pipe.
**
** @param fd An array of two integers. The first element will be the file descriptor \\
** for the read end of the pipe and the second will be for the write end.
** @return Returns zero if successful and -1 otherwise.
**/
void create_pipe( int* fd )
{
fd[0] = -1;
fd[1] = -1;
if(pipe( fd ) == -1) error("pipe");
}
/**
** Run a process as daemon with stdin and stdout redirected. Uses the file descriptors in to_pipe and from_pipe.
**
** @param cmd_arg The command and arguments as an array of strings. \\
The first element is the command and the last a NULL pointer.
** @param to_pipe The write end of the child's standard input for cmd.
** @param from_pipe The read end of the child's standard output for cmd.
** @return Returns the child's pid to the parent, zero to the child and -1 if something went wrong.
**/
int pipe_exec( char** cmd_arg, int* to_pipe, int* from_pipe )
{
int pid = 0;
if( pid = spawn( to_pipe, from_pipe ), pid < 0 )
{
error("pipe_exec");
} else if( pid == 0 ) { /* This block is run in the child only. */
execvp( cmd_arg[0], cmd_arg );
}
return pid;
}