Advertisement
Guest User

Untitled

a guest
Oct 21st, 2019
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.08 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <assert.h>
  5. #include <string.h>
  6. #include <sys/wait.h>
  7. #include <errno.h>
  8. #include <sys/types.h>
  9. #include <dirent.h>
  10.  
  11. // search TODO to find the place you need to work on
  12.  
  13. void die(char *s)
  14. {
  15. fprintf(stderr, "Error: %s\n", s);
  16. if (errno)
  17. perror("errno");
  18. exit(EXIT_FAILURE);
  19. }
  20.  
  21. #define MAX_VALUE 1000
  22. #define MSG_BUF_SIZE 100
  23. #define PIPEFD_READ 0
  24. #define PIPEFD_WRITE 1
  25.  
  26. typedef struct {
  27. int v;
  28. int num_attempts;
  29. char message[MSG_BUF_SIZE];
  30. } gmn_t;
  31.  
  32. void gmn_init(gmn_t *pg, int seed)
  33. {
  34. srand(seed);
  35. pg->v = rand() % MAX_VALUE + 1;
  36. pg->num_attempts = 0;
  37. strcpy(pg->message, "You have not got the right number yet.\n");
  38. }
  39.  
  40. int gmn_check(gmn_t *pg, int guess)
  41. {
  42. pg->num_attempts ++;
  43. if (pg->v == guess) {
  44. snprintf(pg->message, MSG_BUF_SIZE,
  45. "It took you %d attempt(s) to guess the number %d.\n",
  46. pg->num_attempts, pg->v);
  47. return 0;
  48. }
  49. if (pg->v > guess)
  50. return 1;
  51. return -1;
  52. }
  53.  
  54. char * gmn_get_message(gmn_t *pg)
  55. {
  56. return pg->message;
  57. }
  58.  
  59. int gmn_get_max()
  60. {
  61. return MAX_VALUE;
  62. }
  63.  
  64. // this function runs the demo session
  65. // all gmn_ functions should be called in child process
  66. // and then send the result to the parent process
  67. void guess_my_number(int seed)
  68. {
  69. gmn_t gmn;
  70.  
  71. // initialize the game
  72. gmn_init(&gmn, seed);
  73.  
  74. int min = 1;
  75. int max = gmn_get_max();
  76. int result;
  77.  
  78. do {
  79. // make a guess
  80. int guess = (min + max)/2;
  81. printf("My guess: %d\n", guess);
  82.  
  83. // check
  84. result = gmn_check(&gmn, guess);
  85.  
  86. // if not correct, prepare for the next guess
  87. if(result > 0)
  88. min = guess + 1;
  89. else if(result < 0)
  90. max = guess - 1;
  91. } while (result != 0);
  92.  
  93. // print out the final message
  94. fputs(gmn_get_message(&gmn), stdout);
  95. }
  96.  
  97.  
  98. // Tasks for the child process.
  99. //
  100. // Parameters:
  101. // fdp: the pipe for parent to write and for child to read
  102. // fdc: the pipe for child to write and for parent to read
  103. // seed: seed for the random numer
  104. //
  105. // This function should not return.
  106. // This function does not print any characters, except for error messages.
  107. void child_main(int fdp[], int fdc[], int seed)
  108. {
  109. gmn_t gmn;
  110.  
  111. gmn_init(&gmn, seed);
  112.  
  113. // TODO
  114. // close unused file descriptors
  115. // send max value to the parent
  116. // repeat the following until guess from parent is correct
  117. // wait for a guess from parent
  118. // call gmn_check()
  119. // send the result to parent
  120. // send the final message back (as a string)
  121. // close all pipe file descriptors
  122.  
  123. close(fdp[PIPEFD_WRITE]);
  124. close(fdc[PIPEFD_READ]);
  125.  
  126. int max = MAX_VALUE;
  127. int guess, guess_result;
  128. //int message_size = MSG_BUF_SIZE;
  129. int message_size = 1000;
  130.  
  131. if(write(fdc[PIPEFD_WRITE], &max, sizeof(int)) == -1)
  132. die("write() fails");
  133.  
  134. while(guess_result != 0) {
  135.  
  136. if(read(fdp[PIPEFD_READ], &guess, sizeof(int)) == -1)
  137. die("read() fails");
  138.  
  139. guess_result = gmn_check(&gmn, guess);
  140.  
  141. write(fdc[PIPEFD_WRITE], &guess_result, sizeof(int));
  142. }
  143.  
  144. write(fdc[PIPEFD_WRITE], gmn_get_message(&gmn), MSG_BUF_SIZE);
  145.  
  146. close(fdp[PIPEFD_READ]);
  147. close(fdc[PIPEFD_WRITE]);
  148.  
  149. exit(EXIT_SUCCESS);
  150. }
  151.  
  152. void print_file_descriptors(int child);
  153.  
  154. int main(int argc, char *argv[])
  155. {
  156. int seed = 3100;
  157. int demo = 0;
  158. int lsof = 0;
  159.  
  160. // parse the command line arguments
  161.  
  162. for (int i = 1; i < argc; i ++) {
  163. if (! strcmp(argv[i], "demo")) {
  164. demo = 1;
  165. } else if (! strcmp(argv[i], "lsof")) {
  166. lsof = 1;
  167. } else if (! strcmp(argv[i], "-h")) {
  168. fprintf(stderr, "Usage: %s [<seed>] [demo] [lsof]\n", argv[0]);
  169. return 1;
  170. } else {
  171. seed = atoi(argv[i]);
  172. if (seed <= 0)
  173. die("seed must be a postive number.");
  174. }
  175. }
  176.  
  177. if (demo) {
  178. guess_my_number(seed);
  179. exit(0);
  180. }
  181.  
  182. // Now, we do it using two processes
  183. // The child generates a random number
  184. // The parent tries to guess the number.
  185. // The child tell the parent
  186.  
  187. // two pipes
  188. // fdp : parent writes
  189. // fdc : child writes
  190.  
  191. int fdp[2], fdc[2];
  192.  
  193. //pipe creation
  194. if (pipe(fdp) == -1)
  195. die("pipe() failed.");
  196.  
  197. if (pipe(fdc) == -1)
  198. die("pipe() failed.");
  199.  
  200. pid_t pid;
  201. pid = fork();
  202.  
  203. if (pid < 0)
  204. die("fork() failed.");
  205.  
  206. if(pid == 0)
  207. child_main(fdp, fdc, seed); // never returns
  208.  
  209. // parent continues
  210.  
  211. int min = 1;
  212. int max;
  213. int guess;
  214. int result;
  215. char final_message[MSG_BUF_SIZE];
  216. int message_size = MSG_BUF_SIZE;
  217.  
  218. // TODO
  219. // close unused pipe file descriptor
  220. // get max from the child
  221.  
  222. close(fdp[PIPEFD_READ]);
  223. close(fdc[PIPEFD_WRITE]);
  224.  
  225. read(fdc[PIPEFD_READ], &max, sizeof(int));
  226.  
  227. if (lsof) {
  228. print_file_descriptors(pid);
  229. print_file_descriptors(getpid());
  230. }
  231.  
  232. do {
  233. guess = (min + max)/2;
  234. printf("My guess: %d\n", guess);
  235.  
  236. // TODO
  237. // send guess to the child
  238. // wait for the result from the child
  239.  
  240. if(write(fdp[PIPEFD_WRITE], &guess, sizeof(int)) == -1)
  241. die("write() fails");
  242.  
  243. //wait(NULL);
  244.  
  245. if(read(fdc[PIPEFD_READ], &result, sizeof(int)) == -1)
  246. die("read() fails");
  247.  
  248. if (result > 0)
  249. min = guess + 1;
  250. else if (result < 0)
  251. max = guess - 1;
  252. } while (result != 0);
  253.  
  254. // flush stdout buffer
  255. fflush(stdout);
  256.  
  257. // TODO
  258. // receive the final message and print it to stdout
  259. // close all pipe file descriptors
  260. //wait for the child process to finish
  261. if(read(fdc[PIPEFD_READ], &final_message, message_size) == -1)
  262. die("read() fails");
  263.  
  264. printf("%s", final_message);
  265.  
  266. close(fdp[PIPEFD_WRITE]);
  267. close(fdc[PIPEFD_READ]);
  268.  
  269. wait(NULL);
  270. return 0;
  271. }
  272.  
  273. // This function prints the open file descriptors for a process
  274. // Works only on Linux like system
  275. // if pid is -1
  276. void print_file_descriptors(int pid)
  277. {
  278. char buf[64];
  279.  
  280. snprintf(buf, sizeof(buf), "/proc/%i/fd/", pid);
  281.  
  282. fprintf(stdout, "open FDs: ");
  283.  
  284. DIR *dir = opendir(buf);
  285. if (dir == NULL) {
  286. fprintf(stdout, "error\n");
  287. return;
  288. }
  289.  
  290. int thisfd = -1;
  291. if (pid == getpid()) {
  292. thisfd = dirfd(dir);
  293. }
  294.  
  295. struct dirent *entry;
  296.  
  297. while ((entry = readdir(dir)) != NULL) {
  298. if (entry->d_name[0] == '.')
  299. continue;
  300. if (atoi(entry->d_name) == thisfd)
  301. continue;
  302. fprintf(stdout, "%s ", entry->d_name);
  303. }
  304. fprintf(stdout, "\n");
  305. closedir(dir);
  306. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement