Question 5

A colleague has written a procedure that tries to crack an encoded message held in a string. Its syntax is:
   int code_cracker(char *input, char *output);
Input is a NULL-terminated character string. Output is a 1001 element character array. Code_cracker() returns when it has cracked the code, and the cracked code is in output.

Your job is to write the procedure:

char *crack_10(char *s);
Crack10 allows code_cracker() to run on an input string s for ten seconds. If it finishes before the 10 second have expired, you return the output string. It if doesn't, you return NULL.

Do not use threads for this.


Question 6

Part A: Explain precisely what the following piece of code does. Don't explain every line to me -- give me a functional description of what it does to its inputs and output.
code(int a, int b, int c)
{
  fd_set master, cp;  int i, j, bytes, to_do, width;  char buf[10];

  width = a; 
  if (b > width) width = b;
  if (c > width) width = c;
  width++;

  FD_ZERO(&master);
  FD_SET(a, &master); FD_SET(b, &master); FD_SET(c, &master);

  for (i = 0; i < 3; i++) {
    memcpy(&master, &cp, sizeof(fd_set));
    if (select(width, &cp, NULL, NULL, NULL) < 0) {
      perror("select);
      exit(1);
    }
    if (FD_ISSET(a, &cp)) to_do = a;
    if (FD_ISSET(b, &cp)) to_do = b;
    if (FD_ISSET(c, &cp)) to_do = c;
    bytes = 0;
    while (bytes < 10) {
      j = read(to_do, buf+bytes, 10-bytes);
      if (j <= 0) {
        bytes = 10;
      } else {
        bytes += j;
      }
    }
    fwrite(buf, 1, 10, stdout);
    FD_CLR(to_do, &master);
  }
}

Part B: Suppose you wanted to use threads instead of select(). Would you need to have a mutex in your code? Why or why not? Give this one some thought.