Advertisement
Guest User

Untitled

a guest
Jul 28th, 2017
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 39.52 KB | None | 0 0
  1. /* cracking program in c
  2. Mater and Slave */
  3.  
  4.  
  5. /* Master */
  6. #include <errno.h>
  7. #include <fcntl.h>
  8. #include <netdb.h>
  9. #include <netinet/in.h>
  10. #include <setjmp.h>
  11. #include <signal.h>
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <sys/socket.h>
  16. #include <sys/time.h>
  17. #include <sys/types.h>
  18. #include <sys/wait.h>
  19.  
  20. #ifndef FD_SET
  21. typedef int fd_set;
  22. #define FD_SET(fd,set) *set |= (1 << (fd))
  23. #define FD_CLR(fd,set) *set &= ~(1 << (fd))
  24. #define FD_ISSET(fd,set) (*set & (1 << (fd)))
  25. #define FD_ZERO(set) *set = 0
  26. #endif
  27.  
  28. #ifndef EINTR
  29. #define EINTR EAGAIN
  30. #endif
  31.  
  32. #define CHUNK_TIME 300         /* how big to make a chunk */
  33. #define WAIT_TIME 300          /* how long to make slaves wait */
  34. #define DEAD_TIME 5000         /* how long before a slave is dead */
  35. #define PERIOD_TIME 120        /* how often to do periodic stuff */
  36. #define REASSIGN_TIME 1800     /* how long to wait before redoing a chunk */
  37. #define SELECT_TIME 60         /* how long select should wait */
  38. #define MAX_SLAVES 300         /* maximum number of slaves */
  39. #define PROTO_TIME 20          /* timeout for protocol */
  40.  
  41. struct {
  42.   char pattern [49];
  43.   char goal [17];
  44. } globstruct = {
  45.   {
  46.     0x0e, 0x89, 0x94, 0xb8, 0xbf, 0x0e, 0xb9, 0x2e,
  47.     0x50, 0x44, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
  48.     '0',
  49.     0xaf, 0x84, 0xa7, 0x79, 0xf8, 0x13, 0x69, 0x20,
  50.     0x25, 0x9b, 0x53, 0xa0, 0x60, 0xae, 0x75, 0x51,
  51.     0xbf, 0xeb, 0x90, 0xf8, 0x2c, 0x0c, 0xe1, 0xea,
  52.     0x18, 0xac, 0x11, 0x4c, 0x83, 0x14, 0x21, 0xb6,
  53.   },
  54.   {
  55.     0x74,
  56.     0x0f, 0x32, 0x88, 0xcf, 0x1a, 0x22, 0xcd, 0x0a,
  57.     0xa4, 0x48, 0x76, 0xc1, 0x38, 0x12, 0x85, 0xa5,
  58.   }
  59. };
  60. char *glob = (char *) &globstruct;
  61. long globlen = sizeof (globstruct);
  62.  
  63. void usage (void)
  64. {
  65.   fprintf (stderr, "usage: master [-v|-V] socket begin end\n");
  66.   fprintf (stderr, "   or: master [-v|-V] socket -r\n");
  67.   exit (2);
  68. }
  69.  
  70. unsigned long start_point, end_point;
  71. unsigned long cur_point;
  72. char ckpname [6] = "ckp.0";
  73. int verbose = 0;
  74. int mysock;
  75. unsigned long start_date;
  76. int found = 0;
  77.  
  78. /* display messages depending on verbosity level */
  79. #define Verb1 if (verbose >= 1) printf
  80. #define Verb2 if (verbose >= 2) printf
  81.  
  82. void fatal (char *syscall)
  83. {
  84.   perror (syscall);
  85.   exit (3);
  86. }
  87.  
  88. void log (char *msg, unsigned long clientaddr)
  89. {
  90.   int i;
  91.   unsigned long adr = ntohl (clientaddr);
  92.  
  93.   fprintf (stderr, "%d.%d.%d.%d: %s\n", (adr >> 24) & 255, (adr >> 16) & 255,
  94.        (adr >> 8) & 255, adr & 255, msg);
  95. }
  96.  
  97. unsigned long get_date (void)
  98. {
  99.   struct timeval tv;
  100.   struct timezone tz;
  101.   int res;
  102.  
  103.   res = gettimeofday (&tv, &tz);
  104.   if (res != 0) fatal ("gettimeofday");
  105.   return tv.tv_sec;
  106. }
  107.  
  108. /* read the checkpoint files; find the most recent one */
  109. void recover (void)
  110. {
  111.   char i;
  112.   FILE *f;
  113.   unsigned long maxlow = 0;
  114.   unsigned long maxhigh, low, high;
  115.   int found = 0;
  116.  
  117.   for (i = '0'; i <= '9'; i++){
  118.     ckpname [4] = i;
  119.     f = fopen (ckpname, "r");
  120.     if (f == NULL) continue;
  121.     low = 0; high = 0;
  122.     fscanf (f, "%lx %lx\n", &low, &high);
  123.     Verb2 ("recover: file %c; low = %lx; high = %lx\n", i, low, high);
  124.     if (low >= maxlow){
  125.       maxlow = low;
  126.       maxhigh = high;
  127.     }
  128.     fclose (f);
  129.     found = 1;
  130.   }
  131.   if (!found) fatal ("cannot find any checkpoint file");
  132.   start_point = maxlow;
  133.   end_point = maxhigh;
  134.   Verb1 ("recover: start = %lx; end = %lx\n", start_point, end_point);
  135. }
  136.  
  137. void init_socket (int portnum)
  138. {
  139.   struct sockaddr_in myaddr;
  140.   int service_num = htons (portnum);
  141.   int opt;
  142.   int s;
  143.  
  144.   s = socket (AF_INET, SOCK_STREAM, 0);
  145.   if (s == -1) fatal ("socket");
  146.   if (s > 8 * sizeof (int)) fatal ("socket fd too high");
  147.   opt = 1;
  148.   setsockopt (s, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt));
  149.   myaddr.sin_family = AF_INET;
  150.   myaddr.sin_port = service_num;
  151.   myaddr.sin_addr.s_addr = INADDR_ANY;
  152.   if (bind (s, &myaddr, sizeof (myaddr)) == -1) fatal ("bind");
  153.   if (listen (s, 8) == -1) fatal ("listen");
  154.   mysock = s;
  155. }
  156.  
  157. typedef struct elem {
  158.   struct elem *next;
  159.   unsigned long start;
  160.   unsigned long end;
  161.   unsigned long date;
  162. } *elem;
  163.  
  164. struct elem run_head = { NULL, 0, 0, 0 };
  165. struct elem todo_head = { NULL, 0, 0, 0 };
  166. struct elem done_head = { NULL, 0, 0, 0 };
  167. elem run_list = &run_head;
  168. elem todo_list = &todo_head;
  169. elem done_list = &done_head;
  170.  
  171. elem new (void)
  172. {
  173.   elem result = (elem) malloc (sizeof (struct elem));
  174.   if (result == NULL) fatal ("malloc");
  175.   return result;
  176. }
  177.  
  178. elem first (elem list)
  179. {
  180.   return list->next;
  181. }
  182.  
  183. elem find (elem list, unsigned long st, unsigned long nd)
  184. {
  185.   elem prev, cur;
  186.  
  187.   prev = list;
  188.   while (1){
  189.     cur = prev->next;
  190.     if (cur == NULL || (st == cur->start && nd == cur->end)) break;
  191.     prev = cur;
  192.   }
  193.   return cur;
  194. }
  195.  
  196. void insert (elem list, elem e)
  197. {
  198.   elem prev, cur;
  199.  
  200.   prev = list;
  201.   while (1){
  202.     cur = prev->next;
  203.     if (cur == NULL || cur->date >= e->date){
  204.       e->next = cur;
  205.       prev->next = e;
  206.       return;
  207.     }
  208.     prev = cur;
  209.   }
  210. }
  211.  
  212. void delete (elem list, elem e)
  213. {
  214.   elem prev, cur;
  215.  
  216.   prev = list;
  217.   while (1){
  218.     cur = prev->next;
  219.     if (cur == NULL) return;
  220.     if (cur == e){
  221.       prev->next = cur->next;
  222.       return;
  223.     }
  224.     prev = cur;
  225.   }
  226. }
  227.  
  228. #if 0
  229. void enumerate (elem list, void (*f)(elem e))
  230. {
  231.   elem prev, cur;
  232.  
  233.   prev = list;
  234.   while (1){
  235.     cur = prev->next;
  236.     if (cur == NULL) return;
  237.     (*f) (cur);
  238.     prev = cur;
  239.   }
  240. }
  241. #endif
  242.  
  243. struct machine {
  244.   unsigned long addr;
  245.   unsigned long date;
  246.   unsigned long speed;
  247.   unsigned long nproc;
  248.   char status;
  249. };
  250.  
  251. struct machine slaves [MAX_SLAVES];
  252. int num_slaves;
  253.  
  254. void update_slave (unsigned long addr, unsigned long date, char status,
  255.            unsigned long speed, unsigned long nproc)
  256. {
  257.   int i;
  258.   for (i = 0; i < num_slaves; i++){
  259.     if (slaves [i].addr == addr){
  260.       if (date != 0) slaves [i].date = date;
  261.       if (status != '?') slaves [i].status = status;
  262.       if (speed != 0) slaves [i].speed = speed;
  263.       if (nproc != 0) slaves [i].nproc = nproc;
  264.       return;
  265.     }
  266.   }
  267.   if (num_slaves >= MAX_SLAVES) return;
  268.   slaves [num_slaves].addr = addr;
  269.   slaves [num_slaves].date = date;
  270.   slaves [num_slaves].status = status;
  271.   slaves [num_slaves].speed = speed;
  272.   slaves [num_slaves].nproc = nproc;
  273.   ++num_slaves;
  274. }
  275.  
  276. enum chunk_reply { Interval, Wait, Done };
  277.  
  278. int get_chunk (unsigned long clientaddr, unsigned long speed,
  279.            unsigned long *p_start, unsigned long *p_end)
  280. {
  281.   float tg = (float) speed * CHUNK_TIME / 4096;         /* 5 mn */
  282.   unsigned long togive;
  283.   elem e = first (todo_list);
  284.  
  285.   if (tg < 1) tg = 1;
  286.   if (tg > end_point - start_point) tg = end_point - start_point;
  287.   togive = tg;
  288.   update_slave (clientaddr, 0, '?', speed, 0);
  289.   if (e != NULL){
  290.     Verb2 ("first chunk to do: from %lx to %lx\n", e->start, e->end);
  291.     if (e->end - e->start > togive){
  292.       elem e2 = new ();
  293.       e2->start = e->start;
  294.       e2->end = e->start + togive;
  295.       e->start = e2->end;
  296.       e->date = e->start;          /* to get the sorting right */
  297.       if (e2->end > end_point || e2->end <= e2->start){
  298.     e2->end = end_point;
  299.     delete (todo_list, e);
  300.     free (e);
  301.       }
  302.       e = e2;
  303.     }else{
  304.       delete (todo_list, e);
  305.     }
  306.     /* e is what we want to give to the process */
  307.     *p_start = e->start;
  308.     *p_end = e->end;
  309.     e->date = get_date ();
  310.     insert (run_list, e);
  311.     return Interval;
  312.   }else{
  313.     /* no more work to do */
  314.     if (first (run_list) == NULL){
  315.       return Done;
  316.     }else{
  317.       return Wait;
  318.     }
  319.   }
  320. }
  321.  
  322. void get_status (unsigned long clientaddr, char status, unsigned long nproc)
  323. {
  324.   update_slave (clientaddr, get_date (), status, 0, nproc);
  325. }
  326.  
  327. void get_result (unsigned long clientaddr, unsigned long st, unsigned long nd,
  328.          unsigned long len, char *buf)
  329. {
  330.   elem e = find (run_list, st, nd);
  331.   long res;
  332.   FILE *f;
  333.  
  334.   if (e == NULL) return;
  335.   f = fopen ("log", "a");
  336.   if (f != NULL){
  337.     fprintf (f, "%8.8lx %8.8lx%s\n", st, nd, (len != 0) ? " *" : "");
  338.     fclose (f);
  339.   }
  340.   if (len > 0){
  341.     f = fopen ("results", "a");
  342.     if (f == NULL) fatal ("fopen");
  343.     res = fwrite (buf, 1, len, f);
  344.     if (res != len) fatal ("fwrite");
  345.     fclose (f);
  346.     log ("got result", clientaddr);
  347.     found = 1;
  348.     todo_list->next = NULL;
  349.     cur_point = e->start;
  350.   }
  351.   delete (run_list, e);
  352.   e->date = e->start;
  353.   insert (done_list, e);
  354.   while (1){
  355.     e = first (done_list);
  356.     if (e == NULL || e->start > cur_point) break;
  357.     cur_point = e->end;
  358.     delete (done_list, e);
  359.     free (e);
  360.   }
  361. }
  362.  
  363. jmp_buf jump_timeout;
  364.  
  365. void alarm_handler (void)
  366. {
  367.   longjmp (jump_timeout, 1);
  368. }
  369.  
  370. void protocol (int fd, unsigned long clientaddr)
  371. {
  372.   int c;
  373.   unsigned long param1, param2, param3;
  374.   int res;
  375.   char *buf;
  376.   FILE *in, *out;
  377.   char paramc;
  378.  
  379.   in = fdopen (fd, "r");
  380.   out = fdopen (fd, "w");
  381.   if (in == NULL || out == NULL) fatal ("fdopen");
  382.   signal (SIGALRM, (void *) alarm_handler);
  383.   if (setjmp (jump_timeout) == 0){
  384.     alarm (PROTO_TIME);
  385.     while (1){
  386.       c = getc (in);
  387.       switch (c){
  388.       case 'g':
  389.     fscanf (in, " %lx", &param1);
  390.     c = getc (in);   /* eat the end-of-line */
  391.     if (c == ' '){
  392.       fscanf (in, "%lx", &clientaddr);
  393.       getc (in);
  394.       clientaddr = htonl (clientaddr);
  395.     }
  396.     Verb2 ("got command: g %lx %lx\n", param1, clientaddr);
  397.     res = get_chunk (clientaddr, param1, &param2, &param3);
  398.     switch (res){
  399.     case Interval:
  400.       fprintf (out, "I %lx %lx %lx\n", param2, param3, globlen);
  401.       fwrite (glob, 1, globlen, out);
  402.       break;
  403.     case Wait:
  404.       fprintf (out, "W %lx\n", WAIT_TIME);
  405.       break;
  406.     case Done: default:
  407.       fprintf (out, "F\n");
  408.       break;
  409.     }
  410.     fflush (out);
  411.     break;
  412.       case 's':
  413.     fscanf (in, " %c", &paramc);
  414.     c = getc (in);   /* eat the end-of-line */
  415.     param1 = 1;
  416.     if (c == ' '){
  417.       fscanf (in, "%lx %lx", &clientaddr, &param1);
  418.       getc (in);
  419.       clientaddr = htonl (clientaddr);
  420.     }
  421.     Verb2 ("got command: s %c %lx %lx\n", paramc, clientaddr, param1);
  422.     get_status (clientaddr, paramc, param1);
  423.     break;
  424.       case 'r':
  425.     res = fscanf (in, " %lx %lx %lx", &param1, &param2, &param3);
  426.     Verb2 ("got command: r %lx %lx %lx\n", param1, param2, param3);
  427.     getc (in);   /* eat the end-of-line */
  428.     if (res != 3){
  429.       log ("ill-formed result code", clientaddr);
  430.       goto protocol_done;
  431.     }
  432.     if (param3 != 0){
  433.       Verb2 ("got result, size = %ld\n", param3);
  434.       buf = malloc (param3);
  435.       if (buf == NULL){
  436.         log ("out of memory for result string", clientaddr);
  437.         goto protocol_done;
  438.       }
  439.       res = fread (buf, 1, param3, in);
  440.       if (res != param3){
  441.         log ("truncated result", clientaddr);
  442.         goto protocol_done;
  443.       }
  444.     }
  445.     get_result (clientaddr, param1, param2, param3, buf);
  446.     break;
  447.       case '\n': case '\r': case ' ': break;
  448.       case EOF: goto protocol_done;
  449.       default:
  450.     log ("protocol error", clientaddr);
  451.     goto protocol_done;
  452.       }
  453.     }
  454.   protocol_done: ;
  455.   }else{
  456.     Verb1 ("time-out in protocol\n");
  457.   }
  458.   alarm (0);
  459.   fclose (in);
  460.   fclose (out);
  461.   return;
  462. }
  463.  
  464. char cur_ckp = '0';
  465. unsigned long last_check = 0;
  466.  
  467. void periodic (void)
  468. {
  469.   elem e, e2;
  470.   FILE *ckp_file;
  471.   unsigned long total_speed;
  472.   unsigned long now;
  473.   int i;
  474.  
  475.   now = get_date ();
  476.   if (now - last_check < PERIOD_TIME) return;
  477.   last_check = now;
  478.   while (1){
  479.     e = first (run_list);
  480.     if (e == NULL || now - e->date <= REASSIGN_TIME) break;
  481.     Verb2 ("reassigning interval: %lx..%lx\n", e->start, e->end);
  482.     delete (run_list, e);
  483.     e2 = new ();
  484.     e2->start = e->start;
  485.     e2->end = e->end;
  486.     e2->date = e2->start;
  487.     insert (todo_list, e2);
  488.   }
  489.   ckpname [4] = cur_ckp;
  490.   ++cur_ckp;
  491.   if (cur_ckp > '9') cur_ckp = '0';
  492.   Verb2 ("writing checkpoint to file %s\n", ckpname);
  493.   ckp_file = fopen (ckpname, "w");
  494.   if (ckp_file == NULL){
  495.     log ("cannot write checkpoint file", 0);
  496.   }else{
  497.     fprintf (ckp_file, "%lx %lx\n", cur_point, end_point);
  498.     fclose (ckp_file);
  499.   }
  500.   /* display stats and slave list */
  501.   {
  502.     time_t date = get_date ();
  503.     printf ("*************************** %s", ctime (&date));
  504.   }
  505.   printf ("name                 address         status    speed processes\n");
  506.   total_speed = 0;
  507.   for (i = 0; i < num_slaves; i++){
  508.     char isdead;
  509.     unsigned long a;
  510.     struct hostent *host;
  511.     char *name;
  512.    
  513.     a = ntohl (slaves [i].addr);
  514.     host = gethostbyaddr (&(slaves [i].addr), 4, AF_INET);
  515.     if (host != NULL){
  516.       name = host->h_name;
  517.     }else{
  518.       name = "?";
  519.     }
  520.     isdead = ' ';
  521.     if (now - slaves [i].date > DEAD_TIME) isdead = '*';
  522.     if (slaves [i].status == 'r' && isdead == ' '){
  523.       total_speed += slaves [i].speed * slaves [i].nproc;
  524.     }
  525.     printf ("%-20.20s %3.3d.%3.3d.%3.3d.%3.3d   %c%c   %8d   %3d\n",
  526.         name, (a>>24)&255, (a>>16)&255, (a>>8)&255, a&255,
  527.         slaves [i].status, isdead, slaves [i].speed, slaves [i].nproc);
  528.   }
  529.  
  530.   {
  531.     float avg_speed;
  532.     printf ("\ntotal peak speed = %lu\n", total_speed);
  533.     if (now - start_date != 0){
  534.       avg_speed = 4096.0 * (cur_point - start_point) / (now - start_date);
  535.       printf ("average speed = %.0f\n", avg_speed);
  536.     }
  537.     printf ("current point = %lx\n", cur_point);
  538.     printf ("%.1f%% done;      ", cur_point * 100.0 / end_point);
  539.     if (avg_speed > 1){
  540.       printf ("estimated time to completion = %.1f days\n",
  541.           4096.0 * (end_point - cur_point) / avg_speed / 86400);
  542.     }else{
  543.       printf ("\n");
  544.     }
  545.     if (found) printf ("**** result found ****\n");
  546.   }
  547. }
  548.  
  549. void dispatch (void)
  550. {
  551.   fd_set readfds;
  552.   struct timeval timeout;
  553.   int res;
  554.   struct sockaddr_in clientaddr;
  555.   int clientaddrlen;
  556.   int clientsocket;
  557.  
  558.   while (1){
  559.     Verb1 ("waiting for connection\n");
  560.     FD_ZERO (&readfds);
  561.     FD_SET (mysock, &readfds);
  562.     timeout.tv_sec = SELECT_TIME;
  563.     timeout.tv_usec = 0;
  564.     res = select (8*sizeof(int), (void *) &readfds, NULL, NULL, &timeout);
  565.     if (res == 1 && FD_ISSET (mysock, &readfds)){
  566.       clientaddrlen = sizeof (clientaddr);
  567.       clientsocket = accept (mysock, &clientaddr, &clientaddrlen);
  568.       if (clientsocket == -1){
  569.     log ("accept failed", 0);
  570.     continue;
  571.       }
  572.       Verb2 ("got connection from %lx\n", clientaddr.sin_addr.s_addr);
  573.       protocol (clientsocket, clientaddr.sin_addr.s_addr);
  574.       close (clientsocket);
  575.     }else if (res != 0){
  576.       if (errno != EINTR) fatal ("select");
  577.     }
  578.     Verb2 ("doing periodic action\n");
  579.     periodic ();
  580.   }
  581. }
  582.  
  583. void init_lists (unsigned long st, unsigned long nd)
  584. {
  585.   elem e = new ();
  586.   e->start = st;
  587.   e->end = nd;
  588.   e->date = st;
  589.   insert (todo_list, e);
  590. }
  591.  
  592. int main (int argc, char **argv)
  593. {
  594.   int portnum;
  595.  
  596.   if (argc > 1){
  597.     if (!strcmp (argv [1], "-v")){
  598.       verbose = 1;
  599.       --argc;
  600.       ++argv;
  601.     }else if (!strcmp (argv [1], "-V")){
  602.       verbose = 2;
  603.       --argc;
  604.       ++argv;
  605.     }
  606.   }
  607.   if (argc < 2) usage ();
  608.   portnum = 0;
  609.   sscanf (argv [1], "%d", &portnum);
  610.   if (portnum == 0) usage ();
  611.   if (argc == 3 && !strcmp (argv [2], "-r")){
  612.     recover ();
  613.   }else{
  614.     char i;
  615.     for (i = '0'; i <= '9'; i++){
  616.       ckpname [4] = i;
  617.       unlink (ckpname);
  618.     }
  619.     sscanf (argv [2], "%lx", &start_point);
  620.     sscanf (argv [3], "%lx", &end_point);
  621.   }
  622.   Verb1 ("main: start = %lx; end = %lx\n", start_point, end_point);
  623.   init_socket (portnum);
  624.   init_lists (start_point, end_point);
  625.   start_date = get_date ();
  626.   cur_point = start_point;
  627.   dispatch ();
  628. }
  629.  
  630.  
  631.  
  632. /* slave */
  633.  
  634. #if OBSOLETE
  635. #include <sys/types.h>
  636. #include <sys/time.h>
  637.  
  638. #include <sys/dir.h>
  639. #define dirent direct
  640. #include <errno.h>
  641. extern int errno;
  642. #include <netdb.h>
  643. #include <netinet/in.h>
  644. #include <signal.h>
  645. #include <stdio.h>
  646. char *malloc ();
  647. #include <string.h>
  648. #include <sys/resource.h>
  649. #include <sys/socket.h>
  650. #include <sys/stat.h>
  651. #include <sys/wait.h>
  652. #include <time.h>
  653. #ifndef LONG_MAX
  654. #define LONG_MAX 0x7fffffffL
  655. #endif
  656.  
  657. #else
  658.  
  659. #include <sys/types.h>
  660. #include <sys/time.h>
  661.  
  662. #include <dirent.h>
  663. #include <errno.h>
  664. #include <limits.h>
  665. #include <netdb.h>
  666. #include <netinet/in.h>
  667. #include <signal.h>
  668. #include <stdio.h>
  669. #include <stdlib.h>
  670. #include <string.h>
  671. #include <sys/resource.h>
  672. #include <sys/socket.h>
  673. #include <sys/stat.h>
  674. #include <sys/wait.h>
  675. #include <time.h>
  676. #if SYSV
  677. #include <sys/times.h>
  678. #include <unistd.h>
  679. #endif
  680. #endif /* OBSOLETE */
  681.  
  682. #ifndef SIGCHLD
  683. #define SIGCHLD SIGCLD
  684. #endif
  685.  
  686. #define VERSION 10              /* version of this file */
  687.  
  688. #define MAX_DEVICES 1000       /* max number of devices to watch */
  689. #define IDLE_TIME 240          /* time since users touched ttys */
  690. #define INIT_TIME 20           /* time to wait before starting work */
  691. #define RUN_TIME 10            /* period of checking for users when running */
  692. #define STOP_TIME 300          /* period of checking when stopped */
  693. #define HALT_TIME 3600         /* period of checking for halted procs */
  694. #define WAIT_TIME 300          /* period of checking for waiting procs */
  695. #define REPORT_TIME 1800       /* max period of status reports */
  696. #define RETRY_TIME 120         /* how often to retry connections */
  697. #define MEASURE_TIME 60        /* period to measure CPU percentage */
  698. #define MIN_PERCENT 60         /* min percentage of CPU consumed */
  699. #define TEST_TIME 5            /* time to run for speed test */
  700.  
  701. char *dev_names [] = {
  702.   "/dev/kbd",
  703.   "/dev/keyboard",
  704.   "/dev/mouse",
  705.   "/dev/console",
  706.   "/dev/lightpen",
  707.   "/dev/hilkbd"
  708. };
  709.  
  710. struct {
  711.   unsigned char pattern [49];
  712.   unsigned char goal [17];
  713. } globstruct;
  714.  
  715. char *glob = (char *) &globstruct;
  716. long globlen = sizeof (globstruct);
  717. char globstatus = 's';
  718. int verbose = 0;
  719. int ignore_ttys = 0;       /* ignore /dev/tty* */
  720. int ignore_devs = 0;       /* ignore other devices */
  721. char *progname;
  722. unsigned long my_speed;
  723. unsigned long my_addr;
  724. unsigned long nproc = 1, nlive = 0;
  725.  
  726. void usage (void)
  727. {
  728.   fprintf (stderr, "usage: slave [-vVtw] [-n nproc] machine socket\n");
  729.   exit (2);
  730. }
  731.  
  732. /* display messages depending on verbosity level */
  733. #define Verb1 if (verbose >= 1) printf
  734. #define Verb2 if (verbose >= 2) printf
  735.  
  736. void fatal (char *syscall)
  737. {
  738.   perror (syscall);
  739.   exit ('f');
  740. }
  741.  
  742. unsigned long get_date (void)
  743. {
  744.   struct timeval tv;
  745.   struct timezone tz;
  746.   int res;
  747.  
  748.   res = gettimeofday (&tv, &tz);
  749.   if (res != 0) fatal ("gettimeofday");
  750.   return tv.tv_sec;
  751. }
  752.  
  753. int portnum;
  754. struct hostent serverhost;
  755.  
  756. int open_socket (void)
  757. {
  758.   struct sockaddr_in serveraddr;
  759.   int s;
  760.   int res;
  761.  
  762.   memset (&serveraddr, 0, sizeof (serveraddr));
  763.   serveraddr.sin_family = serverhost.h_addrtype;
  764.   serveraddr.sin_port = portnum;
  765.   memcpy (&serveraddr.sin_addr, serverhost.h_addr, serverhost.h_length);
  766.   s = socket (AF_INET, SOCK_STREAM, 0);
  767.   if (s == -1) fatal ("socket");
  768.   res = connect (s, (void *) &serveraddr, sizeof (serveraddr));
  769.   if (res == -1){
  770.     Verb1 ("connect failed, errno = %d\n", errno);
  771.     return -1;
  772.   }
  773.   return s;
  774. }
  775.  
  776. float cpu_time (void)
  777. {
  778. #if SYSV
  779.   struct tms ru;
  780.   times (&ru);
  781.   return (float) (ru.tms_utime + ru.tms_stime) / sysconf (_SC_CLK_TCK);
  782. #else
  783.   struct rusage ru;
  784.   getrusage (RUSAGE_SELF, &ru);
  785.   return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0
  786.          + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1000000.0;
  787. #endif /*SYSV*/
  788. }
  789.  
  790. float time_before;
  791.  
  792. void start_measures (void)
  793. {
  794.   time_before = cpu_time ();
  795. }
  796.  
  797. void end_measures (void)
  798. {
  799.   float time_after;
  800.  
  801.   time_after = cpu_time ();
  802.   if (time_after - time_before < MIN_PERCENT * MEASURE_TIME / 100){
  803.     exit ('h');
  804.   }
  805. }
  806.  
  807. enum chunk_reply { Work, Wait };
  808.  
  809. int get_chunk (int sock, unsigned long *start, unsigned long *end)
  810. {
  811.   FILE *in, *out;
  812.   int c;
  813.   int res;
  814.   unsigned long globsize;
  815.  
  816.   in = fdopen (sock, "r");
  817.   out = fdopen (sock, "w");
  818.   if (in == NULL || out == NULL) fatal ("fdopen");
  819.   Verb1 ("worker: getting chunk\n");
  820.   fprintf (out, "g %lx %lx\n", my_speed, my_addr);
  821.   fflush (out);
  822.   c = getc (in);
  823.   Verb1 ("worker: got %c\n", c);
  824.   switch (c){
  825.   case 'I':
  826.     res = fscanf (in, " %lx %lx %lx", start, end, &globsize);
  827.     if (res != 3 || globsize != globlen){
  828.       Verb2 ("protocol error: res = %d, globsize = %ul, globlen = %d\n",
  829.          res, globsize, globlen);
  830.       /* we certainly got a time-out in the protocol because some other
  831.      process is preventing us from running. */
  832.       *start = HALT_TIME;
  833.       return Wait;
  834.     }
  835.     getc (in);
  836.     res = fread (glob, 1, globlen, in);
  837.     if (res != globlen) fatal ("protocol error");
  838.     fclose (out);
  839.     fclose (in);
  840.     return Work;
  841.   case 'W': default:
  842.     res = fscanf (in, " %lx", start);
  843.     if (res != 1) fatal ("protocol error");
  844.     fclose (out);
  845.     fclose (in);
  846.     return Wait;
  847.   case 'F':
  848.     exit ('d');
  849.   }
  850. }
  851.  
  852. void send_result (int sock, unsigned long start, unsigned long end,
  853.           int reslen, char *result)
  854. {
  855.   FILE *out;
  856.  
  857.   out = fdopen (sock, "w");
  858.   if (out == NULL) fatal ("fdopen");
  859.   Verb1 ("sending result for %lx %lx\n", start, end);
  860.   fprintf (out, "r %lx %lx %lx\n", start, end, reslen);
  861.   fwrite (result, 1, reslen, out);
  862.   fclose (out);
  863. }
  864.  
  865. #if __alpha || __ksr__
  866. #define UINT4 unsigned int
  867. #else
  868. #define UINT4 unsigned long
  869. #endif
  870. #define S11 7
  871. #define S12 12
  872. #define S13 17
  873. #define S14 22
  874. #define S21 5
  875. #define S22 9
  876. #define S23 14
  877. #define S24 20
  878. #define S31 4
  879. #define S32 11
  880. #define S33 16
  881. #define S34 23
  882. #define S41 6
  883. #define S42 10
  884. #define S43 15
  885. #define S44 21
  886. #define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
  887. #define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
  888. #define H(x, y, z) ((x) ^ (y) ^ (z))
  889. #define I(x, y, z) ((y) ^ ((x) | (~z)))
  890. #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
  891. #define FF(a, b, c, d, x, s, ac) { \
  892.  t = (a) + F ((b), (c), (d)) + (x) + (UINT4)(ac); \
  893.  (a) = (b) + ROTATE_LEFT (t, (s)); \
  894. }
  895. #define GG(a, b, c, d, x, s, ac) { \
  896.  t = (a) + G ((b), (c), (d)) + (x) + (UINT4)(ac); \
  897.  (a) = (b) + ROTATE_LEFT (t, (s)); \
  898. }
  899. #define HH(a, b, c, d, x, s, ac) { \
  900.  t = (a) + H ((b), (c), (d)) + (x) + (UINT4)(ac); \
  901.  (a) = (b) + ROTATE_LEFT (t, (s)); \
  902. }
  903. #define II(a, b, c, d, x, s, ac) { \
  904.  t = (a) + I ((b), (c), (d)) + (x) + (UINT4)(ac); \
  905.  (a) = (b) + ROTATE_LEFT (t, (s)); \
  906. }
  907.  
  908. int rc4initstate [256];
  909.  
  910. void init_inner_loop (void)
  911. {
  912.   int i;
  913.  
  914.   for (i = 0; i < 256; i++){
  915.     rc4initstate [i] = i;
  916.   }
  917. }
  918.  
  919. /* This is the function that we should optimize to death.
  920.    returns the low 12 bits of the key, or -1 if not found.
  921. */
  922. long inner_loop (unsigned long stpoint)
  923. {
  924.   register UINT4 x2, x3, a, b, c, d;
  925.   int rc4state [256];
  926.   register int i;
  927.  
  928.   /* set up the block of data */
  929. #define x0 0xb894890e
  930. #define x1 0x2eb90ebf
  931.   x2 = 0x00074450 + ((~stpoint << 4) & 0xff000000);
  932. #define x4 0xa784af30
  933. #define x5 0x6913f879
  934. #define x6 0x539b2520
  935. #define x7 0x75ae60a0
  936. #define x8 0x90ebbf51
  937. #define x9 0xe10c2cf8
  938. #define x10 0x11ac18ea
  939. #define x11 0x2114834c
  940. #define x12 0x000080b6
  941. #define x13 0x00000000
  942. #define x14 0x00000188
  943. #define x15 0x00000000
  944.  
  945.   for (i = 0; i < 4096; i++){
  946.     { /* MD5 */
  947.       register unsigned long t;
  948.  
  949.       x3 = ((stpoint << 12) & 0xfffff000) + i;
  950.       a = 0x67452301;
  951.       b = 0xefcdab89;
  952.       c = 0x98badcfe;
  953.       d = 0x10325476;
  954.       FF (a, b, c, d, x0, S11, 0xd76aa478); /* 1 */
  955.       FF (d, a, b, c, x1, S12, 0xe8c7b756); /* 2 */
  956.       FF (c, d, a, b, x2, S13, 0x242070db); /* 3 */
  957.       FF (b, c, d, a, x3, S14, 0xc1bdceee); /* 4 */
  958.       FF (a, b, c, d, x4, S11, 0xf57c0faf); /* 5 */
  959.       FF (d, a, b, c, x5, S12, 0x4787c62a); /* 6 */
  960.       FF (c, d, a, b, x6, S13, 0xa8304613); /* 7 */
  961.       FF (b, c, d, a, x7, S14, 0xfd469501); /* 8 */
  962.       FF (a, b, c, d, x8, S11, 0x698098d8); /* 9 */
  963.       FF (d, a, b, c, x9, S12, 0x8b44f7af); /* 10 */
  964.       FF (c, d, a, b, x10, S13, 0xffff5bb1); /* 11 */
  965.       FF (b, c, d, a, x11, S14, 0x895cd7be); /* 12 */
  966.       FF (a, b, c, d, x12, S11, 0x6b901122); /* 13 */
  967.       FF (d, a, b, c, x13, S12, 0xfd987193); /* 14 */
  968.       FF (c, d, a, b, x14, S13, 0xa679438e); /* 15 */
  969.       FF (b, c, d, a, x15, S14, 0x49b40821); /* 16 */
  970.  
  971.       /* Round 2 */
  972.       GG (a, b, c, d, x1, S21, 0xf61e2562); /* 17 */
  973.       GG (d, a, b, c, x6, S22, 0xc040b340); /* 18 */
  974.       GG (c, d, a, b, x11, S23, 0x265e5a51); /* 19 */
  975.       GG (b, c, d, a, x0, S24, 0xe9b6c7aa); /* 20 */
  976.       GG (a, b, c, d, x5, S21, 0xd62f105d); /* 21 */
  977.       GG (d, a, b, c, x10, S22,  0x2441453); /* 22 */
  978.       GG (c, d, a, b, x15, S23, 0xd8a1e681); /* 23 */
  979.       GG (b, c, d, a, x4, S24, 0xe7d3fbc8); /* 24 */
  980.       GG (a, b, c, d, x9, S21, 0x21e1cde6); /* 25 */
  981.       GG (d, a, b, c, x14, S22, 0xc33707d6); /* 26 */
  982.       GG (c, d, a, b, x3, S23, 0xf4d50d87); /* 27 */
  983.       GG (b, c, d, a, x8, S24, 0x455a14ed); /* 28 */
  984.       GG (a, b, c, d, x13, S21, 0xa9e3e905); /* 29 */
  985.       GG (d, a, b, c, x2, S22, 0xfcefa3f8); /* 30 */
  986.       GG (c, d, a, b, x7, S23, 0x676f02d9); /* 31 */
  987.       GG (b, c, d, a, x12, S24, 0x8d2a4c8a); /* 32 */
  988.  
  989.       /* Round 3 */
  990.       HH (a, b, c, d, x5, S31, 0xfffa3942); /* 33 */
  991.       HH (d, a, b, c, x8, S32, 0x8771f681); /* 34 */
  992.       HH (c, d, a, b, x11, S33, 0x6d9d6122); /* 35 */
  993.       HH (b, c, d, a, x14, S34, 0xfde5380c); /* 36 */
  994.       HH (a, b, c, d, x1, S31, 0xa4beea44); /* 37 */
  995.       HH (d, a, b, c, x4, S32, 0x4bdecfa9); /* 38 */
  996.       HH (c, d, a, b, x7, S33, 0xf6bb4b60); /* 39 */
  997.       HH (b, c, d, a, x10, S34, 0xbebfbc70); /* 40 */
  998.       HH (a, b, c, d, x13, S31, 0x289b7ec6); /* 41 */
  999.       HH (d, a, b, c, x0, S32, 0xeaa127fa); /* 42 */
  1000.       HH (c, d, a, b, x3, S33, 0xd4ef3085); /* 43 */
  1001.       HH (b, c, d, a, x6, S34,  0x4881d05); /* 44 */
  1002.       HH (a, b, c, d, x9, S31, 0xd9d4d039); /* 45 */
  1003.       HH (d, a, b, c, x12, S32, 0xe6db99e5); /* 46 */
  1004.       HH (c, d, a, b, x15, S33, 0x1fa27cf8); /* 47 */
  1005.       HH (b, c, d, a, x2, S34, 0xc4ac5665); /* 48 */
  1006.  
  1007.       /* Round 4 */
  1008.       II (a, b, c, d, x0, S41, 0xf4292244); /* 49 */
  1009.       II (d, a, b, c, x7, S42, 0x432aff97); /* 50 */
  1010.       II (c, d, a, b, x14, S43, 0xab9423a7); /* 51 */
  1011.       II (b, c, d, a, x5, S44, 0xfc93a039); /* 52 */
  1012.       II (a, b, c, d, x12, S41, 0x655b59c3); /* 53 */
  1013.       II (d, a, b, c, x3, S42, 0x8f0ccc92); /* 54 */
  1014.       II (c, d, a, b, x10, S43, 0xffeff47d); /* 55 */
  1015.       II (b, c, d, a, x1, S44, 0x85845dd1); /* 56 */
  1016.       II (a, b, c, d, x8, S41, 0x6fa87e4f); /* 57 */
  1017.       II (d, a, b, c, x15, S42, 0xfe2ce6e0); /* 58 */
  1018.       II (c, d, a, b, x6, S43, 0xa3014314); /* 59 */
  1019.       II (b, c, d, a, x13, S44, 0x4e0811a1); /* 60 */
  1020.       II (a, b, c, d, x4, S41, 0xf7537e82); /* 61 */
  1021.       II (d, a, b, c, x11, S42, 0xbd3af235); /* 62 */
  1022.       II (c, d, a, b, x2, S43, 0x2ad7d2bb); /* 63 */
  1023.       II (b, c, d, a, x9, S44, 0xeb86d391); /* 64 */
  1024.  
  1025.       a += 0x67452301;
  1026.       b += 0xefcdab89;
  1027.       c += 0x98badcfe;
  1028.       d += 0x10325476;
  1029.     } /* The rc4 key is a.b.c.d, in little-endian format. */
  1030.     { /* RC4 key schedule */
  1031.       register unsigned int t;
  1032. #define Swap(x,y) { t = (x); (x) = (y); (y) = t; }
  1033.       register int x, y = 0;
  1034.  
  1035.       memcpy (rc4state, rc4initstate, sizeof (rc4state));
  1036.       for (x = 0; x < 256; x+=16){
  1037.     y = (y + rc4state [x] + (a & 0xff)) & 0xff;
  1038.     Swap (rc4state [x], rc4state [y]);
  1039.     y = (y + rc4state [x+1] + ((a >> 8) & 0xff)) & 0xff;
  1040.     Swap (rc4state [x+1], rc4state [y]);
  1041.     y = (y + rc4state [x+2] + ((a >> 16) & 0xff)) & 0xff;
  1042.     Swap (rc4state [x+2], rc4state [y]);
  1043.     y = (y + rc4state [x+3] + ((a >> 24) & 0xff)) & 0xff;
  1044.     Swap (rc4state [x+3], rc4state [y]);
  1045.     y = (y + rc4state [x+4] + (b & 0xff)) & 0xff;
  1046.     Swap (rc4state [x+4], rc4state [y]);
  1047.     y = (y + rc4state [x+5] + ((b >> 8) & 0xff)) & 0xff;
  1048.     Swap (rc4state [x+5], rc4state [y]);
  1049.     y = (y + rc4state [x+6] + ((b >> 16) & 0xff)) & 0xff;
  1050.     Swap (rc4state [x+6], rc4state [y]);
  1051.     y = (y + rc4state [x+7] + ((b >> 24) & 0xff)) & 0xff;
  1052.     Swap (rc4state [x+7], rc4state [y]);
  1053.     y = (y + rc4state [x+8] + (c & 0xff)) & 0xff;
  1054.     Swap (rc4state [x+8], rc4state [y]);
  1055.     y = (y + rc4state [x+9] + ((c >> 8) & 0xff)) & 0xff;
  1056.     Swap (rc4state [x+9], rc4state [y]);
  1057.     y = (y + rc4state [x+10] + ((c >> 16) & 0xff)) & 0xff;
  1058.     Swap (rc4state [x+10], rc4state [y]);
  1059.     y = (y + rc4state [x+11] + ((c >> 24) & 0xff)) & 0xff;
  1060.     Swap (rc4state [x+11], rc4state [y]);
  1061.     y = (y + rc4state [x+12] + (d & 0xff)) & 0xff;
  1062.     Swap (rc4state [x+12], rc4state [y]);
  1063.     y = (y + rc4state [x+13] + ((d >> 8) & 0xff)) & 0xff;
  1064.     Swap (rc4state [x+13], rc4state [y]);
  1065.     y = (y + rc4state [x+14] + ((d >> 16) & 0xff)) & 0xff;
  1066.     Swap (rc4state [x+14], rc4state [y]);
  1067.     y = (y + rc4state [x+15] + ((d >> 24) & 0xff)) & 0xff;
  1068.     Swap (rc4state [x+15], rc4state [y]);
  1069.       }
  1070.     }
  1071.  
  1072.     { /* RC4 encoding */
  1073.       register int matches = 0;
  1074.       register int j, stx, sty;
  1075.       register int x = 0, y = 0;
  1076.      
  1077.       for (j = 0; j < 16; j++){
  1078.     ++x;
  1079.     stx = rc4state [x];
  1080.     y = (y + stx) & 0xff;
  1081.     sty = rc4state [y];
  1082.     rc4state [x] = sty;
  1083.     rc4state [y] = stx;
  1084.       }
  1085.       for (j = 0; j < 17; j++){
  1086.     ++x;
  1087.     stx = rc4state [x];
  1088.     y = (y + stx) & 0xff;
  1089.     sty = rc4state [y];
  1090.     rc4state [x] = sty;
  1091.     rc4state [y] = stx;
  1092.     if (globstruct.goal [j] == rc4state [(stx + sty) & 0xff]) ++matches;
  1093.       }
  1094.       if (matches >= 10){
  1095.     Verb1 ("matches = %d\n", matches);
  1096.     return i;
  1097.       }
  1098.     }
  1099.   }
  1100.   return -1;
  1101. }
  1102.  
  1103. int do_work (unsigned long start, unsigned long end, char *result)
  1104. {
  1105.   unsigned long i;
  1106.   int res;
  1107.  
  1108.   if (verbose >= 2){
  1109.     Verb2 ("Current goal is: ");
  1110.     for (i = 0; i < 17; i++){
  1111.       Verb2 ("%2.2x", (int) globstruct.goal[i]);
  1112.     }
  1113.     Verb2 ("\n");
  1114.   }
  1115.  
  1116.   for (i = start; i < end; i++){
  1117.     res = inner_loop (i);
  1118.     if (res != -1){
  1119.       int low32 = (i << 12) + res;
  1120.       sprintf (result, "%2.2x %2.2x %2.2x %2.2x %2.2x\n", ~(i >> 20) & 0xff,
  1121.            low32 & 0xff, (low32 >> 8) & 0xff, (low32 >> 16) & 0xff,
  1122.            (low32 >> 24) & 0xff);
  1123.       return strlen (result);
  1124.     }
  1125.   }
  1126.   return 0;
  1127. }
  1128.  
  1129. void worker (void)
  1130. {
  1131.   int sock;
  1132.   unsigned long start, end;
  1133.   int reslen;
  1134.   char result [1000];
  1135.   int w;
  1136.  
  1137.   strcpy (progname, "worker");
  1138.   nice (40);
  1139.   while (1){
  1140.     sock = open_socket ();
  1141.     if (sock == -1){
  1142.       Verb1 ("worker: cannot get chunk\n");
  1143.       exit ('w');
  1144.     }
  1145.     w = get_chunk (sock, &start, &end);
  1146.     close (sock);   /* redundant close cannot hurt */
  1147.     if (w == Wait){
  1148.       sleep (start);
  1149.     }else{
  1150.       start_measures ();
  1151.       signal (SIGALRM, (void *) end_measures);
  1152.       alarm (MEASURE_TIME);
  1153.       reslen = do_work (start, end, result);
  1154.       sock = open_socket ();
  1155.       if (sock == -1){
  1156.     Verb1 ("worker: cannot send result\n");
  1157.     exit ('w');
  1158.       }
  1159.       send_result (sock, start, end, reslen, result);
  1160.       close (sock);   /* redundant close cannot hurt */
  1161.     }
  1162.   }
  1163. }
  1164.  
  1165. int *worker_pids;
  1166. char *worker_status;
  1167. unsigned long *worker_time;    /* time of next wake-up */
  1168.  
  1169. void bury_child (void)
  1170. {
  1171.   int chldstat;
  1172.   long pid;
  1173.   int i;
  1174.   char st;
  1175.   unsigned long now = get_date ();
  1176.  
  1177.   Verb1 ("SIGCHLD received\n");
  1178.   while (1){
  1179.     pid = wait3 ((void *) &chldstat, WNOHANG, NULL);
  1180.     if (pid <= 0) break;
  1181.     Verb2 ("got child: %ld\n", pid);
  1182.     for (i = 0; i < nproc; i++){
  1183.       if (worker_pids [i] == pid) goto found;
  1184.     }
  1185.     break;
  1186.   found:
  1187.     if ((chldstat & 0xff) == 0x7f){
  1188.       Verb1 ("child stopped\n");
  1189.     }else if ((chldstat & 0x7f) == SIGINT){
  1190.       Verb1 ("child killed by SIGINT\n");
  1191.       worker_pids [i] = 0;
  1192.       worker_status [i] = 'h';
  1193.       worker_time [i] = now + HALT_TIME;
  1194.       -- nlive;
  1195.     }else if (chldstat & 0xff){
  1196.       Verb1 ("child killed by signal\n");
  1197.       worker_pids [i] = 0;
  1198.       worker_status [i] = 'w';
  1199.       worker_time [i] = now + HALT_TIME;
  1200.       -- nlive;
  1201.     }else{
  1202.       st = (chldstat >> 8) &0xff;   /* 'w'ait, 'h'alt, 'd'one, 'f'atal */
  1203.       worker_pids [i] = 0;
  1204.       worker_status [i] = st;
  1205.       switch (st){
  1206.       case 'w': worker_time [i] = now + WAIT_TIME; break;
  1207.       case 'h': default: worker_time [i] = now + HALT_TIME; break;
  1208.       case 'd':
  1209.       case 'f': worker_time [i] = LONG_MAX; break;
  1210.       }
  1211.       -- nlive;
  1212.     }
  1213.   }
  1214. #if SYSV
  1215.   signal (SIGCHLD, (void *) bury_child);
  1216. #endif
  1217. }
  1218.  
  1219. char *devices [MAX_DEVICES];
  1220. int num_devices;
  1221.  
  1222. void init_devices (void)
  1223. {
  1224.   int i;
  1225.   DIR *d;
  1226.   struct dirent *dp;
  1227.   char *buf;
  1228.   struct stat stbuf;
  1229.  
  1230.   num_devices = 0;
  1231.   if (!ignore_devs){    /* first look at keyboards, mice, consoles, etc. */
  1232.     for (i = 0; i < sizeof (dev_names) / sizeof (dev_names [0]); i++){
  1233.       if (stat (dev_names [i], &stbuf) == 0){
  1234.     Verb2 ("found device %s\n", dev_names [i]);
  1235.     if (num_devices >= MAX_DEVICES) fatal ("too many devices");
  1236.     devices [num_devices] = dev_names [i];
  1237.     ++num_devices;
  1238.       }
  1239.     }
  1240.   }
  1241.   if (!ignore_ttys){    /* then look at ttys */
  1242.     d = opendir ("/dev");
  1243.     if (d == NULL) fatal ("opendir");
  1244.     while (1){
  1245.       errno = 0;
  1246.       dp = readdir (d);
  1247.       if (dp == NULL) break;
  1248.       if (!strncmp (dp->d_name, "tty", 3) && dp->d_namlen != 3){
  1249.     buf = malloc (dp->d_namlen + 6);
  1250.     if (buf == NULL) fatal ("malloc");
  1251.     strcpy (buf, "/dev/");
  1252.     strncat (buf, dp->d_name, dp->d_namlen);
  1253.     buf [dp->d_namlen + 5] = '\0';
  1254.     Verb2 ("found device %s\n", buf);
  1255.     if (num_devices >= MAX_DEVICES) fatal ("too many devices");
  1256.     devices [num_devices] = buf;
  1257.     ++num_devices;
  1258.       }
  1259.     }
  1260.     if (errno) fatal ("readdir");
  1261.   }
  1262. }
  1263.  
  1264. enum {
  1265.   Idle,
  1266.   Users
  1267. };
  1268.  
  1269. int after_hours_only = 0;
  1270.  
  1271. int check_devices (void)
  1272. {
  1273.   int i;
  1274.   struct stat st;
  1275.   unsigned long now = get_date ();
  1276.   int res;
  1277.  
  1278.   if (after_hours_only){
  1279.     time_t now = get_date ();
  1280.     struct tm *loctm = localtime (&now);
  1281.     if (loctm == NULL) fatal ("localtime");
  1282.     if (loctm->tm_hour < 21 && loctm->tm_hour > 9){
  1283.       Verb1 ("working hours\n");
  1284.       return Users;
  1285.     }
  1286.   }
  1287.   for (i = 0; i < num_devices; i++){
  1288.     res = stat (devices [i], &st);
  1289.     if (res != 0) fatal ("stat");
  1290.     if (now - st.st_atime < IDLE_TIME || now - st.st_mtime < IDLE_TIME
  1291.     || now - st.st_ctime < IDLE_TIME){
  1292.       Verb1 ("device %s is active\n", devices [i]);
  1293.       return Users;
  1294.     }
  1295.   }
  1296.   return Idle;
  1297. }
  1298.  
  1299. void relaunch_workers (void)
  1300. {
  1301.   int i;
  1302.   unsigned long now = get_date ();
  1303.  
  1304.   for (i = 0; i < nproc; i++){
  1305.     if (worker_pids [i] != 0){
  1306.       kill (worker_pids [i], SIGCONT);
  1307.     }else if (worker_time [i] <= now){
  1308.       worker_pids [i] = fork ();
  1309.       switch (worker_pids [i]){
  1310.       case 0:
  1311.     worker ();
  1312.     Verb1 ("unexpected return from worker\n");
  1313.     exit ('w');
  1314.     break;
  1315.       case -1:
  1316.     worker_pids [i] = 0;
  1317.     Verb1 ("fork failed\n");
  1318.     break;
  1319.       default:
  1320.     ++ nlive;
  1321.     worker_status [i] = 'r';
  1322.     sleep (1);
  1323.     break;
  1324.       }
  1325.     }
  1326.   }
  1327. }
  1328.  
  1329. void stop_workers (int sig)
  1330. {
  1331.   int i;
  1332.  
  1333.   for (i = 0; i < nproc; i++){
  1334.     if (worker_pids [i] != 0) kill (worker_pids [i], sig);
  1335.   }
  1336. }
  1337.  
  1338. void send_status (void)
  1339. {
  1340.   unsigned long now = get_date ();
  1341.   static unsigned long last_date = 0;
  1342.   static char last_stat = 'r';
  1343.   int sock;
  1344.   int c;
  1345.   FILE *out;
  1346.   char my_status;
  1347.   int i;
  1348.  
  1349.   if (globstatus == 's'){
  1350.     my_status = 's';
  1351.   }else{
  1352.     my_status = 'h';
  1353.     for (i = 0; i < nproc; i++){
  1354.       switch (worker_status [i]){
  1355.       case 'r': my_status = 'r'; break;
  1356.       case 'w': if (my_status != 'r') my_status = 'w'; break;
  1357.       case 'd': if (my_status == 'h') my_status = 'd'; break;
  1358.       case 'h': default: break;
  1359.       }
  1360.     }
  1361.   }
  1362.   if (now - last_date > REPORT_TIME || last_stat != my_status){
  1363.     Verb2 ("opening socket\n");
  1364.     sock = open_socket ();
  1365.     if (sock == -1){
  1366.       Verb1 ("cannot send status\n");
  1367.       last_date = now + RETRY_TIME - REPORT_TIME;
  1368.       return;
  1369.     }
  1370.     Verb2 ("socket open\n");
  1371.     out = fdopen (sock, "w");
  1372.     if (out == NULL) fatal ("fdopen");
  1373.     Verb1 ("sending status %c\n", my_status);
  1374.     fprintf (out, "s %c %lx %lx\n", my_status, my_addr, nlive);
  1375.     fflush (out);
  1376.     Verb2 ("status sent\n");
  1377.     last_date = now;
  1378.     last_stat = my_status;
  1379.     fclose (out);
  1380.     close (sock);    /* redundant close cannot hurt */
  1381.   }
  1382. }
  1383.  
  1384. void supervisor (void)
  1385. {
  1386.   unsigned long waittime = INIT_TIME;
  1387.   int res;
  1388.  
  1389.   strcpy (progname, "nicer ");
  1390.   res = (int) (long) signal (SIGCHLD, (void *) bury_child);
  1391.   if (res == -1) fatal ("signal");
  1392.   send_status ();
  1393.   while (1){
  1394.     Verb1 ("supervisor waiting for %ld s, state = %c.\n", waittime, globstatus);
  1395.     sleep (waittime);
  1396.     if (check_devices () == Idle){
  1397.       globstatus = 'r';
  1398.     }else{
  1399.       globstatus = 's';
  1400.     }
  1401.     switch (globstatus){
  1402.     case 'r':
  1403.       relaunch_workers ();
  1404.       break;
  1405.     case 's':
  1406.       stop_workers (SIGSTOP);
  1407.       sleep (1);
  1408.       break;
  1409.     }
  1410.     send_status ();
  1411.     switch (globstatus){
  1412.     default:
  1413.     case 'r': waittime = RUN_TIME; break;
  1414.     case 's': waittime = STOP_TIME; break;
  1415.     }
  1416.   }
  1417. }
  1418.  
  1419. char testgoal [17] = {
  1420.   0x2f, 0x2b, 0xb7, 0x0c, 0x07, 0xf9, 0x12, 0x4e,
  1421.   0xb9, 0x99, 0x53, 0x29, 0xbd, 0xff, 0xf9, 0x7c,
  1422.   0x26
  1423. };
  1424.  
  1425. void sanity_check (void)
  1426. {
  1427.   int res;
  1428.  
  1429.   memcpy (globstruct.goal, testgoal, 17);
  1430.   res = inner_loop (0x0100452);
  1431.   Verb2 ("res = %x\n", res);
  1432.   if (res != 0x301) fatal ("failed sanity check");
  1433. }
  1434.  
  1435. void speed_test (void)
  1436. {
  1437.   float start_time, end_time;
  1438.   unsigned long n = 1;
  1439.   int res;
  1440.   char result [1000];
  1441.  
  1442.   Verb1 ("performing speed test...\n");
  1443.   strcpy ((char *) globstruct.goal, "                ");
  1444.   while (1){
  1445.     Verb1 ("n = %d\n", n);
  1446.     start_time = cpu_time ();
  1447.     res = do_work (0, n, result);
  1448.     if (res != 0) fatal ("key found during speed test !");
  1449.     end_time = cpu_time ();
  1450.     if (end_time - start_time >= TEST_TIME) break;
  1451.     if (n > 1000) break;
  1452.     n *= 2;
  1453.   }
  1454.   if (end_time - start_time == 0) fatal ("speed test failed");
  1455.   my_speed = n * 4096.0 / (end_time - start_time);
  1456.   Verb1 ("speed = %d keys/s\n", my_speed);
  1457. }
  1458.  
  1459. int main (int argc, char **argv)
  1460. {
  1461.   struct hostent *entry;
  1462.   char my_name [200];
  1463.  
  1464.   setvbuf (stdout, NULL, _IOLBF, 0);
  1465.   setvbuf (stderr, NULL, _IOLBF, 0);
  1466.  
  1467.   init_inner_loop ();
  1468.   if (argc < 1 || strlen (argv [0]) < 6){
  1469.     fprintf (stderr, "argv[0] is too short\n");
  1470.     exit (2);
  1471.   }
  1472.   progname = argv [0];
  1473.   if (argc < 3) usage ();
  1474.   while (argc > 3){
  1475.     if (!strcmp (argv [1], "-v")){
  1476.       verbose = 1;
  1477.       -- argc;
  1478.       ++ argv;
  1479.     }else if (!strcmp (argv [1], "-V")){
  1480.       verbose = 2;
  1481.       -- argc;
  1482.       ++ argv;
  1483.     }else if (!strcmp (argv [1], "-t")){
  1484.       ignore_ttys = 1;
  1485.       -- argc;
  1486.       ++ argv;
  1487.     }else if (!strcmp (argv [1], "-d")){
  1488.       ignore_devs = 1;
  1489.       -- argc;
  1490.       ++ argv;
  1491.     }else if (!strcmp (argv [1], "-n")){
  1492.       nproc = 0;
  1493.       sscanf (argv [2], "%lu", &nproc);
  1494.       if (nproc == 0) usage ();
  1495.       argc -= 2;
  1496.       argv += 2;
  1497.     }else if (!strcmp (argv [1], "-w")){
  1498.       after_hours_only = 1;
  1499.       -- argc;
  1500.       ++ argv;
  1501.     }else{
  1502.       usage ();
  1503.     }
  1504.   }
  1505.   Verb1 ("version = %d\n", VERSION);
  1506.  
  1507.   worker_pids = (int *) malloc (nproc * sizeof (int));
  1508.   if (worker_pids == NULL) fatal ("malloc");
  1509.   memset (worker_pids, 0, nproc * sizeof (int));
  1510.  
  1511.   worker_status = (char *) malloc (nproc);
  1512.   if (worker_status == NULL) fatal ("malloc");
  1513.   memset (worker_status, 'x', nproc);
  1514.  
  1515.   worker_time = (unsigned long *) malloc (nproc * sizeof (unsigned long));
  1516.   if (worker_time == NULL) fatal ("malloc");
  1517.   memset (worker_time, 0, nproc * sizeof (unsigned long));
  1518.  
  1519.   if (argc != 3 || argv [1][0] == '-') usage ();
  1520.   portnum = htons (atoi (argv [2]));
  1521.  
  1522.   if (gethostname (my_name, 200) == -1) fatal ("gethostname");
  1523.   entry = gethostbyname (my_name);
  1524.   if (entry == NULL) fatal ("gethostbyname");
  1525.   if (entry->h_length != 4) fatal ("wrong address len");
  1526.   my_addr = ntohl (* (UINT4 *) entry->h_addr);
  1527.   Verb1 ("my_addr = %lx\n", my_addr);
  1528.  
  1529.   entry = gethostbyname (argv [1]);
  1530.   if (entry == NULL) fatal ("gethostbyname");
  1531.   memcpy (&serverhost, entry, sizeof (serverhost));
  1532.  
  1533.   sanity_check ();
  1534.   speed_test ();
  1535.   init_devices ();
  1536.   supervisor ();
  1537. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement