Guest User

Fork exec double pipe by dino ciuffetti

a guest
Mar 6th, 2012
972
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.47 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <errno.h>
  4. #include <string.h>
  5. #include <unistd.h>
  6. #include <sys/time.h>
  7. #include <sys/types.h>
  8. #include <sys/wait.h>
  9. #include <sys/stat.h>
  10. #include <sys/select.h>
  11. #include <fcntl.h>
  12. #include <signal.h>
  13.  
  14. #define BUFLEN (6*1024)
  15. #define EXECFILE "/usr/bin/python"
  16.  
  17. char *itoa(int n, char *s, int b) {
  18.         static char digits[] = "0123456789abcdefghijklmnopqrstuvwxyz";
  19.         int i=0, sign;
  20.    
  21.         if ((sign = n) < 0)
  22.                 n = -n;
  23.  
  24.         do {
  25.                 s[i++] = digits[n % b];
  26.         } while ((n /= b) > 0);
  27.  
  28.         if (sign < 0)
  29.                 s[i++] = '-';
  30.         s[i] = '\0';
  31.  
  32.         return s;
  33. }
  34.  
  35. /*
  36. int set_nonblock(int sockfd) { // set socket to non blocking
  37.         int arg,i;
  38.  
  39.         if ((arg=fcntl(sockfd, F_GETFL, NULL)) < 0) {
  40.                 printf("error getting socket flag for fd %i: fcntl(..., F_GETFL): %i\n", sockfd, errno);
  41.                 return -1;
  42.         }
  43.         // set O_NONBLOCK flag
  44.         arg |= O_NONBLOCK;
  45.         if ((i=fcntl(sockfd, F_SETFL, arg)) < 0) {
  46.                 printf("error setting socket flag for fd %i: fcntl(..., F_SETFL): %i\n", sockfd, errno);
  47.                 return -1;
  48.         }
  49.         return i;
  50. }
  51.  
  52. int set_block(int sockfd) { // set socket to blocking
  53.         int arg,i;
  54.  
  55.         if ((arg=fcntl(sockfd, F_GETFL, NULL)) < 0) {
  56.                 printf("error getting socket flag for fd %i: fcntl(..., F_GETFL): %i\n", sockfd, errno);
  57.                 return -1;
  58.         }
  59.         // clean O_NONBLOCK flag
  60.         arg &= (~O_NONBLOCK);
  61.         if ((i=fcntl(sockfd, F_SETFL, arg)) < 0) {
  62.                 printf("error setting socket flag for fd %i: fcntl(..., F_SETFL): %i\n", sockfd, errno);
  63.                 return -1;
  64.         }
  65.         return i;
  66. }
  67. */
  68. int main() {
  69.         FILE *input;
  70.         char slice[BUFLEN];
  71.         int status = 0;
  72.         pid_t pid;
  73.         int err;
  74.         int newfd;
  75.         // if you want you can pass arguments to the program to execute
  76.         // char *const arguments[] = {EXECFILE, "-v", NULL};
  77.         char *const arguments[] = {EXECFILE,  NULL};
  78.         int father2child_pipefd[2];
  79.         int child2father_pipefd[2];
  80.         char *read_data = NULL;
  81.         FILE *retclam;
  82.         fd_set myset;
  83.         int x=1;
  84.  
  85.         signal(SIGPIPE, SIG_IGN);
  86.         newfd = dup(0);
  87.         input = fdopen(newfd, "r");
  88.  
  89.         pipe(father2child_pipefd); // Father speaking to child
  90.         pipe(child2father_pipefd); // Child speaking to father
  91.  
  92.         pid = fork();
  93.         if (pid > 0) { // Father
  94.                 close(father2child_pipefd[0]);
  95.                 close(child2father_pipefd[1]);
  96.  
  97.                 // Write to the pipe reading from stdin
  98.                 retclam = fdopen(child2father_pipefd[0], "r");
  99.  
  100.  
  101.                 // set the two fd non blocking
  102.                 //set_nonblock(0);
  103.                 //set_nonblock(child2father_pipefd[0]);
  104.                 //set_nonblock(fileno(retclam));
  105.  
  106.                 while(x==1) {
  107.                         // clear the file descriptor set
  108.                         FD_ZERO(&myset);
  109.                         // add the stdin to the set
  110.                         FD_SET(fileno(input), &myset);
  111.                         // add the child pipe to the set
  112.                         FD_SET(fileno(retclam), &myset);
  113.  
  114.                         // here we wait for data to arrive from stdin or from the child pipe. The last argument is a timeout, if you like
  115.                         err = select(fileno(retclam)+1, &myset, NULL, NULL, NULL);
  116.                         switch(err) {
  117.                         case -1:
  118.                                 // Problem with select(). The errno variable knows why
  119.                                 //exit(1);
  120.                                 x=0;
  121.                                 break;
  122.                         case 0:
  123.                                 // timeout on select(). Data did not arrived in time, only valid if the last attribute of select() was specified
  124.                                 break;
  125.                         default:
  126.                                 // data is ready to be read
  127.                                 bzero(slice, BUFLEN);
  128.                                 if (FD_ISSET(fileno(retclam), &myset)) { // data ready on the child
  129.                                         //set_block(fileno(retclam));
  130.                                         read_data = fgets(slice, BUFLEN, retclam); // read a line from the child (max BUFLEN bytes)
  131.                                         //set_nonblock(fileno(retclam));
  132.                                         if (read_data == NULL) {
  133.                                                 //exit(0);
  134.                                                 x=0;
  135.                                                 break;
  136.                                         }
  137.                                         // write data back to stdout
  138.                                         write (1, slice, strlen(slice));
  139.                                         if(feof(retclam)) {
  140.                                                 //exit(0);
  141.                                                 x=0;
  142.                                                 break;
  143.                                         }
  144.                                         break;
  145.                                 }
  146.                                 bzero(slice, BUFLEN);
  147.                                 if (FD_ISSET(fileno(input), &myset)) { // data ready on stdin
  148.                                         //printf("father\n");
  149.                                         //set_block(fileno(input));
  150.                                         read_data = fgets(slice, BUFLEN, input); // read a line from stdin (max BUFLEN bytes)
  151.                                         //set_nonblock(fileno(input));
  152.                                         if (read_data == NULL) {
  153.                                                 //exit (0);
  154.                                                 close(father2child_pipefd[1]);
  155.                                                 waitpid(pid, &status, 0);
  156.                                                 //fclose(input);
  157.                                                 break;
  158.                                         }
  159.                                         // write data to the child
  160.                                         write (father2child_pipefd[1], slice, strlen(slice));
  161.                                         /*
  162.                                         if(feof(input)) {
  163.                                                 exit(0);
  164.                                         }*/
  165.                                         break;
  166.                                 }
  167.                         }
  168.                 }
  169.  
  170.                 close(father2child_pipefd[1]);
  171.                 fclose(input);
  172.                 fsync(1);
  173.                 waitpid(pid, &status, 0);
  174.  
  175.                 // child process terminated
  176.                 fclose (retclam);
  177.  
  178.                 // Parse output data from child
  179.                 // write (1, "you can append somethind else on stdout if you like");
  180.                 if (WEXITSTATUS(status) == 0) {
  181.                         exit (0); // child process exited successfully
  182.                 }
  183.         }
  184.  
  185.         if (pid == 0) { // Child
  186.                 close (0); // stdin is not needed
  187.                 close (1); // stdout is not needed
  188.                 // Close the write side of this pipe
  189.                 close(father2child_pipefd[1]);
  190.                 // Close the read side of this pipe
  191.                 close(child2father_pipefd[0]);
  192.  
  193.                 // Let's read on stdin, but this stdin is associated to the read pipe
  194.                 dup2(father2child_pipefd[0], 0);
  195.                 // Let's speak on stdout, but this stdout is associated to the write pipe
  196.                 dup2(child2father_pipefd[1], 1);
  197.  
  198.                 // if you like you can put something back to the father before execve
  199.                 //write (child2father_pipefd[1], "something", 9);
  200.                 //fsync(child2father_pipefd[1]);
  201.                 err = execve(EXECFILE, arguments, NULL);
  202.  
  203.                 // we'll never be here again after execve succeeded!! So we get here only if the execve() failed
  204.                 //fprintf(stderr, "Problem executing file %s: %i: %s\n", EXECFILE, err, strerror(errno));
  205.                 exit (1);
  206.         }
  207.  
  208.         if (pid < 0) { // Error
  209.                 exit (1);
  210.         }
  211.  
  212.         fclose(input);
  213.  
  214.         return 0;
  215. }
Advertisement
Add Comment
Please, Sign In to add comment