Advertisement
cmiN

scfifo

May 29th, 2013
334
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 4.70 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4.  
  5. #include <unistd.h>
  6. #include <fcntl.h>
  7. #include <sys/stat.h>
  8. #include <sys/types.h>
  9. #include <sys/wait.h>
  10.  
  11.  
  12. #define SV 1
  13. #define CL 2
  14.  
  15. #define BUFL 128
  16.  
  17. #define check(a, b) !strcmp(a, b)
  18.  
  19.  
  20. static inline int str_comp(const void * first, const void * second)
  21. {
  22.     return strcmp(*((char * *)first), *((char * *)second));
  23. }
  24.  
  25.  
  26. void process_file(char * fname, char * lines)
  27. {
  28.     /* open the file, read and sort all lines,
  29.        then write the first 3 of them to `lines` buffer */
  30.  
  31.     int linesLen = 0;
  32.     char * * linesVec = NULL;
  33.  
  34.     FILE * file = fopen(fname, "r");
  35.     while (1) {
  36.         char line[BUFL];
  37.         fgets(line, BUFL, file);
  38.         if (feof(file))
  39.             break;
  40.  
  41.         linesVec = realloc(linesVec, ++linesLen * sizeof(char *));
  42.         linesVec[linesLen - 1] = malloc((strlen(line) + 1) * sizeof(char));
  43.         strcpy(linesVec[linesLen - 1], line);
  44.     }
  45.     fclose(file);
  46.  
  47.     qsort(linesVec, linesLen, sizeof(char *), str_comp);
  48.    
  49.     strcpy(lines, linesVec[0]);
  50.     strcat(lines, linesVec[1]);
  51.     strcat(lines, linesVec[2]);
  52.  
  53.     for (int i = 0; i < linesLen; ++i)
  54.         free(linesVec[i]);
  55.     free(linesVec);
  56. }
  57.  
  58.  
  59. int main(int argc, char * argv[])
  60. {
  61.     if (argc < 3) {
  62.         printf("Usage: %s OPTION (NAME...|NAME FILE)\n", argv[0]);
  63.         puts("Open a server or client using named pipes communication for processing a file.\n\
  64. \n\
  65. Options:\n\
  66.    -s, --server    open for serving\n\
  67.    -c, --client    open for sending\n\
  68. \n\
  69. Parameters:\n\
  70.    NAME            path name(s) for FIFO(s)\n\
  71.    FILE            file path for lines reading");
  72.         return 1;
  73.     }
  74.  
  75.     int whoami = 0;
  76.     if (check(argv[1], "-s") || check(argv[1], "--server"))
  77.         whoami = SV;
  78.     else if (check(argv[1], "-c") || check(argv[1], "--client"))
  79.         whoami = CL;
  80.  
  81.     if (whoami == SV) {
  82.         // make FIFOs
  83.         int fifoLen = argc - 2;
  84.         // for input/output
  85.         char * * fifoIn = malloc(sizeof(char *) * fifoLen);
  86.         char * * fifoOut = malloc(sizeof(char *) * fifoLen);
  87.  
  88.         for (int i = 2; i < 2 + fifoLen; ++i) {
  89.             int ind = i - 2;
  90.             int len = sizeof(char) * (strlen(argv[i]) + 2);
  91.             fifoIn[ind] = malloc(len);
  92.             fifoOut[ind] = malloc(len);
  93.            
  94.             strcpy(fifoIn[ind], argv[i]);
  95.             strcpy(fifoOut[ind], argv[i]);
  96.             strcat(fifoIn[ind], "i");
  97.             strcat(fifoOut[ind], "o");
  98.  
  99.             // rw-rw-rw-
  100.             mkfifo(fifoIn[ind], 0666);
  101.             mkfifo(fifoOut[ind], 0666);
  102.  
  103.         }
  104.  
  105.         // wait for messages, process them, then send the response
  106.         for (int i = 0; i < fifoLen; ++i) {
  107.             pid_t pid = fork();
  108.             if (pid == 0) {
  109.                 // the child
  110.  
  111.                 // open the pipe for reading
  112.                 int fin = open(fifoIn[i], O_RDONLY);
  113.                 char fname[BUFL] = {0};
  114.                 read(fin, fname, BUFL);
  115.                 close(fin);
  116.  
  117.                 // read the filename, open and process it
  118.                 printf("Process %s on channel %s\n", fname, argv[i + 2]);
  119.                 char lines[3 * BUFL] = {0};
  120.                 process_file(fname, lines);
  121.  
  122.                 // send the lines back to client
  123.                 int fout = open(fifoOut[i], O_WRONLY);
  124.                 write(fout, lines, strlen(lines));
  125.                 close(fout);
  126.  
  127.                 return 0;
  128.             }
  129.         }
  130.         // wait processes to finish
  131.         for (int i = 0; i < fifoLen; ++i)
  132.             wait(NULL);
  133.  
  134.         // free resources
  135.         for (int i = 0; i < fifoLen; ++i) {
  136.             unlink(fifoIn[i]);
  137.             unlink(fifoOut[i]);
  138.             free(fifoIn[i]);
  139.             free(fifoOut[i]);
  140.         }
  141.         free(fifoIn);
  142.         free(fifoOut);
  143.     } else if (whoami == CL) {
  144.         // prepare pipe names for i/o
  145.         int len = sizeof(char) * (strlen(argv[2]) + 2);
  146.         char * fifoIn = malloc(len);
  147.         char * fifoOut = malloc(len);
  148.         strcpy(fifoIn, argv[2]);
  149.         strcat(fifoIn, "i");
  150.         strcpy(fifoOut, argv[2]);
  151.         strcat(fifoOut, "o");
  152.  
  153.         // open server's input for writing
  154.         int fout = open(fifoIn, O_WRONLY);
  155.         write(fout, argv[3], strlen(argv[3]));
  156.         close(fout);
  157.  
  158.         // now receive the response
  159.         int fin = open(fifoOut, O_RDONLY);
  160.         char lines[3 * BUFL] = {0};
  161.         read(fin, lines, 3 * BUFL);
  162.         close(fin);
  163.  
  164.         puts(lines);
  165.  
  166.         free(fifoIn);
  167.         free(fifoOut);
  168.     } else {
  169.         fputs("Invalid or no option selected\n", stderr);
  170.         return 2;
  171.     }
  172.  
  173.     return 0;
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement