fork download
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. #include <string.h>
  7. #include <sys/types.h>
  8. #include <errno.h>
  9.  
  10. #define CLIENT_FIFO "./client_%d"
  11.  
  12. struct Word
  13. {
  14. int Amount;
  15. char* Text;
  16. };
  17.  
  18. int wordComp(const void* e1, const void* e2)
  19. {
  20. int a1 = ((struct Word*)e1)->Amount;
  21. int a2 = ((struct Word*)e2)->Amount;
  22. if(a1 < a2) return 1;
  23. if(a1 > a2) return -1;
  24. return 0;
  25. }
  26.  
  27. void SendData(int fd, char* filename)
  28. {
  29. // prepare the file processing with the all words list
  30. int in = open(filename, O_RDONLY);
  31.  
  32. char word[4096];
  33. char c = 0;
  34. int i = 0;
  35.  
  36. int wordsSize = 0, wordsCount = 10;
  37. struct Word* words = (struct Word*)malloc(wordsCount * sizeof(struct Word));
  38.  
  39. // read char by char the input file
  40. int len = 0;
  41. while((len = read(in, &c, sizeof(char))) >= 1)
  42. {
  43. // if it's not a valid char it's interpreted as end of word
  44. if(c == '\n' || c == ',' || c == '.' || c == '\t' || c == '\r' || c == ' ')
  45. {
  46. // if the current word is empty skip the char
  47. if(i <= 0)
  48. continue;
  49.  
  50. word[i] = '\0';
  51.  
  52. // compare the current word with all the stored ones
  53. int founded = 0;
  54. for(int j = 0; j < wordsSize; ++j)
  55. {
  56. // if a word matches simply increase the counter
  57. if(strcmp(words[j].Text, word) == 0)
  58. {
  59. founded = 1;
  60. words[j].Amount++;
  61. break;
  62. }
  63. }
  64.  
  65. // if the word is new it will be inserted in the list
  66. if(founded == 0)
  67. {
  68. // if the words list capability is not enough, increase the size
  69. if(wordsSize == wordsCount - 1)
  70. {
  71. struct Word* prevData = words;
  72. words = (struct Word*)malloc(wordsCount * 2 * sizeof(struct Word));
  73. memcpy(words, prevData, wordsCount * sizeof(struct Word));
  74. wordsCount *= 2;
  75. }
  76.  
  77. // build a new string to be stored
  78. int len = strlen(word);
  79. char* newStr = (char*)malloc(len + 1);
  80. memcpy(newStr, word, len);
  81. newStr[len] = '\0';
  82.  
  83. // store the new string with amount 1
  84. words[wordsSize].Text = newStr;
  85. words[wordsSize++].Amount = 1;
  86. }
  87.  
  88. i = 0;
  89. }
  90. else
  91. {
  92. // if the character is valid it will be added to the current word
  93. word[i++] = c;
  94. }
  95. }
  96.  
  97. // sort all the words by the amount
  98. qsort(words, wordsSize, sizeof(struct Word), wordComp);
  99.  
  100. // send the words:
  101. // 1. send the total amount size
  102. // 2. for each word:
  103. // -- write the amount
  104. // -- write the text size
  105. // -- write the text chars
  106. write(fd, &wordsSize, sizeof(int));
  107. for(i = 0; i < wordsSize; ++i)
  108. {
  109. struct Word* w = &words[i];
  110. write(fd, &w->Amount, sizeof(int));
  111.  
  112. int len = strlen(w->Text);
  113. write(fd, &len, sizeof(int));
  114. write(fd, w->Text, len);
  115. }
  116.  
  117. close(in);
  118. }
  119.  
  120. void HandleClient(char* clientFifoName, char* filename)
  121. {
  122. printf("Client Handling!\n");
  123.  
  124. // open the channel with the client
  125. int clientFifo = -1;
  126. if((clientFifo = open(clientFifoName, O_WRONLY)) == -1)
  127. {
  128. printf("Client handle error!\n");
  129. printf("Errno: %d\n", errno);
  130. return;
  131. }
  132.  
  133. // handle the input file
  134. SendData(clientFifo, filename);
  135.  
  136. close(clientFifo);
  137. }
  138.  
  139. void Server(char* publicFifo)
  140. {
  141. printf("Init Server!\n");
  142.  
  143. // make public fifo
  144. if(mkfifo(publicFifo, 0666) == -1)
  145. {
  146. printf("Server error [MKFIFO]!\n");
  147. printf("Errno: %d\n", errno);
  148. return;
  149. }
  150.  
  151. // open it in read only mode
  152. int fifo = -1;
  153. if((fifo = open(publicFifo, O_RDONLY)) == -1)
  154. {
  155. printf("Server error [OPEN FIFO]!\n");
  156. printf("Errno: %d\n", errno);
  157. return;
  158. }
  159.  
  160. printf("Server is running and waiting for clients...\n");
  161.  
  162. char clientInfo[4096];
  163. char clientFifo[4096];
  164. char filename[4096];
  165.  
  166. // begin to listen
  167. while (1)
  168. {
  169. // if someone writes something
  170. if (read(fifo, clientInfo, 4096) > 0)
  171. {
  172. // split the information in client fifo name and input filename
  173. int len = strlen(clientInfo);
  174. memcpy(clientFifo, clientInfo, len + 1);
  175.  
  176. len = strlen(clientInfo + len + 1);
  177. memcpy(filename, clientInfo + len + 1, len);
  178.  
  179. // begin to fork to handle the client
  180. pid_t pid = fork();
  181. if (pid == 0)
  182. {
  183. HandleClient(clientFifo, filename);
  184. exit(0);
  185. }
  186. else if (pid < 0)
  187. {
  188. printf("Failed to fork process\n");
  189. printf("Errno: %d\n", errno);
  190. }
  191. }
  192. }
  193.  
  194. close(fifo);
  195. unlink(publicFifo);
  196. }
  197.  
  198. void Client(char* publicFifo, char* filename)
  199. {
  200. printf("Init Client!\n");
  201.  
  202. // build the client fifo name based on the client pid
  203. char clientFifo[4096];
  204. snprintf(clientFifo, 4096, CLIENT_FIFO, getpid());
  205.  
  206. // make the client fifo
  207. if(mkfifo(clientFifo, 0666) == -1)
  208. {
  209. printf("Client error [MKFIFO]!\n");
  210. printf("Errno: %d\n", errno);
  211. return;
  212. }
  213.  
  214. // open the public fifo
  215. int fifo = -1;
  216. if((fifo = open(publicFifo, O_WRONLY)) == -1)
  217. {
  218. printf("Client error [OPEN FIFO]!\n");
  219. printf("Errno: %d\n", errno);
  220. return;
  221. }
  222.  
  223. // build the data for the server:
  224. // 1. clientFifo name
  225. // 2. input filename
  226. int clientLen = strlen(clientFifo), fileLen = strlen(filename);
  227. char* data = (char*)malloc(clientLen + 1 + fileLen + 1);
  228. memcpy(data, clientFifo, clientLen);
  229. data[clientLen] = '\0';
  230. memcpy(data + clientLen + 1, filename, fileLen);
  231. data[clientLen + fileLen + 1] = '\0';
  232.  
  233. // send the data
  234. write(fifo, data, clientLen + 1 + fileLen + 1);
  235. close(fifo);
  236.  
  237. printf("Client connected!\n");
  238.  
  239. // open the client fifo
  240. int cFifo = -1;
  241. if ((cFifo = open(clientFifo, O_RDONLY)) == -1)
  242. {
  243. printf("Client error [OPEN CLIENT FIFO]!\n");
  244. printf("Errno: %d\n", errno);
  245. return;
  246. }
  247.  
  248. // begin to read the server's data
  249.  
  250. // raed the total amount size of words
  251. int size = 0;
  252. read(cFifo, &size, sizeof(int));
  253.  
  254. // foreach word read the amount and the string
  255. for(int i = 0; i < size; ++i)
  256. {
  257. int amount = 0, len = 0;
  258. read(cFifo, &amount, sizeof(int));
  259. read(cFifo, &len, sizeof(int));
  260.  
  261. char* text = (char*)malloc(len + 1);
  262. read(cFifo, text, len);
  263. text[len] = '\0';
  264.  
  265. // print the result
  266. printf("%d: %s\n", amount, text);
  267. }
  268.  
  269. close(cFifo);
  270. unlink(clientFifo);
  271. }
  272.  
  273. int main(int argc, char* argv[])
  274. {
  275. int p = fork();
  276. if(p == 0)
  277. Server("/tmp/publicFifo2");
  278. else
  279. Client("/tmp/publicFifo2", "input.txt");
  280.  
  281. return 0;
  282. }
  283.  
Success #stdin #stdout 0s 5256KB
stdin
Standard input is empty
stdout
Init Client!
Client error [MKFIFO]!
Errno: 13
Init Server!
Server error [MKFIFO]!
Errno: 13