/* This code is in the public domain. It is provided with no strings attached, and absolutely no guarantees. */ #if OBSOLETE #include #include #include #define dirent direct #include extern int errno; #include #include #include #include char *malloc (); #include #include #include #include #include #include #ifndef LONG_MAX #define LONG_MAX 0x7fffffffL #endif #else #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if SYSV #include #include #endif #endif /* OBSOLETE */ #ifndef SIGCHLD #define SIGCHLD SIGCLD #endif #define VERSION 10 /* version of this file */ #define MAX_DEVICES 1000 /* max number of devices to watch */ #define IDLE_TIME 240 /* time since users touched ttys */ #define INIT_TIME 20 /* time to wait before starting work */ #define RUN_TIME 10 /* period of checking for users when running */ #define STOP_TIME 300 /* period of checking when stopped */ #define HALT_TIME 3600 /* period of checking for halted procs */ #define WAIT_TIME 300 /* period of checking for waiting procs */ #define REPORT_TIME 1800 /* max period of status reports */ #define RETRY_TIME 120 /* how often to retry connections */ #define MEASURE_TIME 60 /* period to measure CPU percentage */ #define MIN_PERCENT 60 /* min percentage of CPU consumed */ #define TEST_TIME 5 /* time to run for speed test */ char *dev_names [] = { "/dev/kbd", "/dev/keyboard", "/dev/mouse", "/dev/console", "/dev/lightpen", "/dev/hilkbd" }; struct { unsigned char pattern [49]; unsigned char goal [17]; } globstruct; char *glob = (char *) &globstruct; long globlen = sizeof (globstruct); char globstatus = 's'; int verbose = 0; int ignore_ttys = 0; /* ignore /dev/tty* */ int ignore_devs = 0; /* ignore other devices */ char *progname; unsigned long my_speed; unsigned long my_addr; unsigned long nproc = 1, nlive = 0; void usage (void) { fprintf (stderr, "usage: slave [-vVtw] [-n nproc] machine socket\n"); exit (2); } /* display messages depending on verbosity level */ #define Verb1 if (verbose >= 1) printf #define Verb2 if (verbose >= 2) printf void fatal (char *syscall) { perror (syscall); exit ('f'); } unsigned long get_date (void) { struct timeval tv; struct timezone tz; int res; res = gettimeofday (&tv, &tz); if (res != 0) fatal ("gettimeofday"); return tv.tv_sec; } int portnum; struct hostent serverhost; int open_socket (void) { struct sockaddr_in serveraddr; int s; int res; memset (&serveraddr, 0, sizeof (serveraddr)); serveraddr.sin_family = serverhost.h_addrtype; serveraddr.sin_port = portnum; memcpy (&serveraddr.sin_addr, serverhost.h_addr, serverhost.h_length); s = socket (AF_INET, SOCK_STREAM, 0); if (s == -1) fatal ("socket"); res = connect (s, (void *) &serveraddr, sizeof (serveraddr)); if (res == -1){ Verb1 ("connect failed, errno = %d\n", errno); return -1; } return s; } float cpu_time (void) { #if SYSV struct tms ru; times (&ru); return (float) (ru.tms_utime + ru.tms_stime) / sysconf (_SC_CLK_TCK); #else struct rusage ru; getrusage (RUSAGE_SELF, &ru); return ru.ru_utime.tv_sec + ru.ru_utime.tv_usec / 1000000.0 + ru.ru_stime.tv_sec + ru.ru_stime.tv_usec / 1000000.0; #endif /*SYSV*/ } float time_before; void start_measures (void) { time_before = cpu_time (); } void end_measures (void) { float time_after; time_after = cpu_time (); if (time_after - time_before < MIN_PERCENT * MEASURE_TIME / 100){ exit ('h'); } } enum chunk_reply { Work, Wait }; int get_chunk (int sock, unsigned long *start, unsigned long *end) { FILE *in, *out; int c; int res; unsigned long globsize; in = fdopen (sock, "r"); out = fdopen (sock, "w"); if (in == NULL || out == NULL) fatal ("fdopen"); Verb1 ("worker: getting chunk\n"); fprintf (out, "g %lx %lx\n", my_speed, my_addr); fflush (out); c = getc (in); Verb1 ("worker: got %c\n", c); switch (c){ case 'I': res = fscanf (in, " %lx %lx %lx", start, end, &globsize); if (res != 3 || globsize != globlen){ Verb2 ("protocol error: res = %d, globsize = %ul, globlen = %d\n", res, globsize, globlen); /* we certainly got a time-out in the protocol because some other process is preventing us from running. */ *start = HALT_TIME; return Wait; } getc (in); res = fread (glob, 1, globlen, in); if (res != globlen) fatal ("protocol error"); fclose (out); fclose (in); return Work; case 'W': default: res = fscanf (in, " %lx", start); if (res != 1) fatal ("protocol error"); fclose (out); fclose (in); return Wait; case 'F': exit ('d'); } } void send_result (int sock, unsigned long start, unsigned long end, int reslen, char *result) { FILE *out; out = fdopen (sock, "w"); if (out == NULL) fatal ("fdopen"); Verb1 ("sending result for %lx %lx\n", start, end); fprintf (out, "r %lx %lx %lx\n", start, end, reslen); fwrite (result, 1, reslen, out); fclose (out); } #if __alpha || __ksr__ #define UINT4 unsigned int #else #define UINT4 unsigned long #endif #define S11 7 #define S12 12 #define S13 17 #define S14 22 #define S21 5 #define S22 9 #define S23 14 #define S24 20 #define S31 4 #define S32 11 #define S33 16 #define S34 23 #define S41 6 #define S42 10 #define S43 15 #define S44 21 #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n)))) #define FF(a, b, c, d, x, s, ac) { \ t = (a) + F ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = (b) + ROTATE_LEFT (t, (s)); \ } #define GG(a, b, c, d, x, s, ac) { \ t = (a) + G ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = (b) + ROTATE_LEFT (t, (s)); \ } #define HH(a, b, c, d, x, s, ac) { \ t = (a) + H ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = (b) + ROTATE_LEFT (t, (s)); \ } #define II(a, b, c, d, x, s, ac) { \ t = (a) + I ((b), (c), (d)) + (x) + (UINT4)(ac); \ (a) = (b) + ROTATE_LEFT (t, (s)); \ } int rc4initstate [256]; void init_inner_loop (void) { int i; for (i = 0; i < 256; i++){ rc4initstate [i] = i; } } /* This is the function that we should optimize to death. returns the low 12 bits of the key, or -1 if not found. */ long inner_loop (unsigned long stpoint) { register UINT4 x2, x3, a, b, c, d; int rc4state [256]; register int i; /* set up the block of data */ #define x0 0xb894890e #define x1 0x2eb90ebf x2 = 0x00074450 + ((~stpoint << 4) & 0xff000000); #define x4 0xa784af30 #define x5 0x6913f879 #define x6 0x539b2520 #define x7 0x75ae60a0 #define x8 0x90ebbf51 #define x9 0xe10c2cf8 #define x10 0x11ac18ea #define x11 0x2114834c #define x12 0x000080b6 #define x13 0x00000000 #define x14 0x00000188 #define x15 0x00000000 for (i = 0; i < 4096; i++){ { /* MD5 */ register unsigned long t; x3 = ((stpoint << 12) & 0xfffff000) + i; a = 0x67452301; b = 0xefcdab89; c = 0x98badcfe; d = 0x10325476; FF (a, b, c, d, x0, S11, 0xd76aa478); /* 1 */ FF (d, a, b, c, x1, S12, 0xe8c7b756); /* 2 */ FF (c, d, a, b, x2, S13, 0x242070db); /* 3 */ FF (b, c, d, a, x3, S14, 0xc1bdceee); /* 4 */ FF (a, b, c, d, x4, S11, 0xf57c0faf); /* 5 */ FF (d, a, b, c, x5, S12, 0x4787c62a); /* 6 */ FF (c, d, a, b, x6, S13, 0xa8304613); /* 7 */ FF (b, c, d, a, x7, S14, 0xfd469501); /* 8 */ FF (a, b, c, d, x8, S11, 0x698098d8); /* 9 */ FF (d, a, b, c, x9, S12, 0x8b44f7af); /* 10 */ FF (c, d, a, b, x10, S13, 0xffff5bb1); /* 11 */ FF (b, c, d, a, x11, S14, 0x895cd7be); /* 12 */ FF (a, b, c, d, x12, S11, 0x6b901122); /* 13 */ FF (d, a, b, c, x13, S12, 0xfd987193); /* 14 */ FF (c, d, a, b, x14, S13, 0xa679438e); /* 15 */ FF (b, c, d, a, x15, S14, 0x49b40821); /* 16 */ /* Round 2 */ GG (a, b, c, d, x1, S21, 0xf61e2562); /* 17 */ GG (d, a, b, c, x6, S22, 0xc040b340); /* 18 */ GG (c, d, a, b, x11, S23, 0x265e5a51); /* 19 */ GG (b, c, d, a, x0, S24, 0xe9b6c7aa); /* 20 */ GG (a, b, c, d, x5, S21, 0xd62f105d); /* 21 */ GG (d, a, b, c, x10, S22, 0x2441453); /* 22 */ GG (c, d, a, b, x15, S23, 0xd8a1e681); /* 23 */ GG (b, c, d, a, x4, S24, 0xe7d3fbc8); /* 24 */ GG (a, b, c, d, x9, S21, 0x21e1cde6); /* 25 */ GG (d, a, b, c, x14, S22, 0xc33707d6); /* 26 */ GG (c, d, a, b, x3, S23, 0xf4d50d87); /* 27 */ GG (b, c, d, a, x8, S24, 0x455a14ed); /* 28 */ GG (a, b, c, d, x13, S21, 0xa9e3e905); /* 29 */ GG (d, a, b, c, x2, S22, 0xfcefa3f8); /* 30 */ GG (c, d, a, b, x7, S23, 0x676f02d9); /* 31 */ GG (b, c, d, a, x12, S24, 0x8d2a4c8a); /* 32 */ /* Round 3 */ HH (a, b, c, d, x5, S31, 0xfffa3942); /* 33 */ HH (d, a, b, c, x8, S32, 0x8771f681); /* 34 */ HH (c, d, a, b, x11, S33, 0x6d9d6122); /* 35 */ HH (b, c, d, a, x14, S34, 0xfde5380c); /* 36 */ HH (a, b, c, d, x1, S31, 0xa4beea44); /* 37 */ HH (d, a, b, c, x4, S32, 0x4bdecfa9); /* 38 */ HH (c, d, a, b, x7, S33, 0xf6bb4b60); /* 39 */ HH (b, c, d, a, x10, S34, 0xbebfbc70); /* 40 */ HH (a, b, c, d, x13, S31, 0x289b7ec6); /* 41 */ HH (d, a, b, c, x0, S32, 0xeaa127fa); /* 42 */ HH (c, d, a, b, x3, S33, 0xd4ef3085); /* 43 */ HH (b, c, d, a, x6, S34, 0x4881d05); /* 44 */ HH (a, b, c, d, x9, S31, 0xd9d4d039); /* 45 */ HH (d, a, b, c, x12, S32, 0xe6db99e5); /* 46 */ HH (c, d, a, b, x15, S33, 0x1fa27cf8); /* 47 */ HH (b, c, d, a, x2, S34, 0xc4ac5665); /* 48 */ /* Round 4 */ II (a, b, c, d, x0, S41, 0xf4292244); /* 49 */ II (d, a, b, c, x7, S42, 0x432aff97); /* 50 */ II (c, d, a, b, x14, S43, 0xab9423a7); /* 51 */ II (b, c, d, a, x5, S44, 0xfc93a039); /* 52 */ II (a, b, c, d, x12, S41, 0x655b59c3); /* 53 */ II (d, a, b, c, x3, S42, 0x8f0ccc92); /* 54 */ II (c, d, a, b, x10, S43, 0xffeff47d); /* 55 */ II (b, c, d, a, x1, S44, 0x85845dd1); /* 56 */ II (a, b, c, d, x8, S41, 0x6fa87e4f); /* 57 */ II (d, a, b, c, x15, S42, 0xfe2ce6e0); /* 58 */ II (c, d, a, b, x6, S43, 0xa3014314); /* 59 */ II (b, c, d, a, x13, S44, 0x4e0811a1); /* 60 */ II (a, b, c, d, x4, S41, 0xf7537e82); /* 61 */ II (d, a, b, c, x11, S42, 0xbd3af235); /* 62 */ II (c, d, a, b, x2, S43, 0x2ad7d2bb); /* 63 */ II (b, c, d, a, x9, S44, 0xeb86d391); /* 64 */ a += 0x67452301; b += 0xefcdab89; c += 0x98badcfe; d += 0x10325476; } /* The rc4 key is a.b.c.d, in little-endian format. */ { /* RC4 key schedule */ register unsigned int t; #define Swap(x,y) { t = (x); (x) = (y); (y) = t; } register int x, y = 0; memcpy (rc4state, rc4initstate, sizeof (rc4state)); for (x = 0; x < 256; x+=16){ y = (y + rc4state [x] + (a & 0xff)) & 0xff; Swap (rc4state [x], rc4state [y]); y = (y + rc4state [x+1] + ((a >> 8) & 0xff)) & 0xff; Swap (rc4state [x+1], rc4state [y]); y = (y + rc4state [x+2] + ((a >> 16) & 0xff)) & 0xff; Swap (rc4state [x+2], rc4state [y]); y = (y + rc4state [x+3] + ((a >> 24) & 0xff)) & 0xff; Swap (rc4state [x+3], rc4state [y]); y = (y + rc4state [x+4] + (b & 0xff)) & 0xff; Swap (rc4state [x+4], rc4state [y]); y = (y + rc4state [x+5] + ((b >> 8) & 0xff)) & 0xff; Swap (rc4state [x+5], rc4state [y]); y = (y + rc4state [x+6] + ((b >> 16) & 0xff)) & 0xff; Swap (rc4state [x+6], rc4state [y]); y = (y + rc4state [x+7] + ((b >> 24) & 0xff)) & 0xff; Swap (rc4state [x+7], rc4state [y]); y = (y + rc4state [x+8] + (c & 0xff)) & 0xff; Swap (rc4state [x+8], rc4state [y]); y = (y + rc4state [x+9] + ((c >> 8) & 0xff)) & 0xff; Swap (rc4state [x+9], rc4state [y]); y = (y + rc4state [x+10] + ((c >> 16) & 0xff)) & 0xff; Swap (rc4state [x+10], rc4state [y]); y = (y + rc4state [x+11] + ((c >> 24) & 0xff)) & 0xff; Swap (rc4state [x+11], rc4state [y]); y = (y + rc4state [x+12] + (d & 0xff)) & 0xff; Swap (rc4state [x+12], rc4state [y]); y = (y + rc4state [x+13] + ((d >> 8) & 0xff)) & 0xff; Swap (rc4state [x+13], rc4state [y]); y = (y + rc4state [x+14] + ((d >> 16) & 0xff)) & 0xff; Swap (rc4state [x+14], rc4state [y]); y = (y + rc4state [x+15] + ((d >> 24) & 0xff)) & 0xff; Swap (rc4state [x+15], rc4state [y]); } } { /* RC4 encoding */ register int matches = 0; register int j, stx, sty; register int x = 0, y = 0; for (j = 0; j < 16; j++){ ++x; stx = rc4state [x]; y = (y + stx) & 0xff; sty = rc4state [y]; rc4state [x] = sty; rc4state [y] = stx; } for (j = 0; j < 17; j++){ ++x; stx = rc4state [x]; y = (y + stx) & 0xff; sty = rc4state [y]; rc4state [x] = sty; rc4state [y] = stx; if (globstruct.goal [j] == rc4state [(stx + sty) & 0xff]) ++matches; } if (matches >= 10){ Verb1 ("matches = %d\n", matches); return i; } } } return -1; } int do_work (unsigned long start, unsigned long end, char *result) { unsigned long i; int res; if (verbose >= 2){ Verb2 ("Current goal is: "); for (i = 0; i < 17; i++){ Verb2 ("%2.2x", (int) globstruct.goal[i]); } Verb2 ("\n"); } for (i = start; i < end; i++){ res = inner_loop (i); if (res != -1){ int low32 = (i << 12) + res; sprintf (result, "%2.2x %2.2x %2.2x %2.2x %2.2x\n", ~(i >> 20) & 0xff, low32 & 0xff, (low32 >> 8) & 0xff, (low32 >> 16) & 0xff, (low32 >> 24) & 0xff); return strlen (result); } } return 0; } void worker (void) { int sock; unsigned long start, end; int reslen; char result [1000]; int w; strcpy (progname, "worker"); nice (40); while (1){ sock = open_socket (); if (sock == -1){ Verb1 ("worker: cannot get chunk\n"); exit ('w'); } w = get_chunk (sock, &start, &end); close (sock); /* redundant close cannot hurt */ if (w == Wait){ sleep (start); }else{ start_measures (); signal (SIGALRM, (void *) end_measures); alarm (MEASURE_TIME); reslen = do_work (start, end, result); sock = open_socket (); if (sock == -1){ Verb1 ("worker: cannot send result\n"); exit ('w'); } send_result (sock, start, end, reslen, result); close (sock); /* redundant close cannot hurt */ } } } int *worker_pids; char *worker_status; unsigned long *worker_time; /* time of next wake-up */ void bury_child (void) { int chldstat; long pid; int i; char st; unsigned long now = get_date (); Verb1 ("SIGCHLD received\n"); while (1){ pid = wait3 ((void *) &chldstat, WNOHANG, NULL); if (pid <= 0) break; Verb2 ("got child: %ld\n", pid); for (i = 0; i < nproc; i++){ if (worker_pids [i] == pid) goto found; } break; found: if ((chldstat & 0xff) == 0x7f){ Verb1 ("child stopped\n"); }else if ((chldstat & 0x7f) == SIGINT){ Verb1 ("child killed by SIGINT\n"); worker_pids [i] = 0; worker_status [i] = 'h'; worker_time [i] = now + HALT_TIME; -- nlive; }else if (chldstat & 0xff){ Verb1 ("child killed by signal\n"); worker_pids [i] = 0; worker_status [i] = 'w'; worker_time [i] = now + HALT_TIME; -- nlive; }else{ st = (chldstat >> 8) &0xff; /* 'w'ait, 'h'alt, 'd'one, 'f'atal */ worker_pids [i] = 0; worker_status [i] = st; switch (st){ case 'w': worker_time [i] = now + WAIT_TIME; break; case 'h': default: worker_time [i] = now + HALT_TIME; break; case 'd': case 'f': worker_time [i] = LONG_MAX; break; } -- nlive; } } #if SYSV signal (SIGCHLD, (void *) bury_child); #endif } char *devices [MAX_DEVICES]; int num_devices; void init_devices (void) { int i; DIR *d; struct dirent *dp; char *buf; struct stat stbuf; num_devices = 0; if (!ignore_devs){ /* first look at keyboards, mice, consoles, etc. */ for (i = 0; i < sizeof (dev_names) / sizeof (dev_names [0]); i++){ if (stat (dev_names [i], &stbuf) == 0){ Verb2 ("found device %s\n", dev_names [i]); if (num_devices >= MAX_DEVICES) fatal ("too many devices"); devices [num_devices] = dev_names [i]; ++num_devices; } } } if (!ignore_ttys){ /* then look at ttys */ d = opendir ("/dev"); if (d == NULL) fatal ("opendir"); while (1){ errno = 0; dp = readdir (d); if (dp == NULL) break; if (!strncmp (dp->d_name, "tty", 3) && dp->d_namlen != 3){ buf = malloc (dp->d_namlen + 6); if (buf == NULL) fatal ("malloc"); strcpy (buf, "/dev/"); strncat (buf, dp->d_name, dp->d_namlen); buf [dp->d_namlen + 5] = '\0'; Verb2 ("found device %s\n", buf); if (num_devices >= MAX_DEVICES) fatal ("too many devices"); devices [num_devices] = buf; ++num_devices; } } if (errno) fatal ("readdir"); } } enum { Idle, Users }; int after_hours_only = 0; int check_devices (void) { int i; struct stat st; unsigned long now = get_date (); int res; if (after_hours_only){ time_t now = get_date (); struct tm *loctm = localtime (&now); if (loctm == NULL) fatal ("localtime"); if (loctm->tm_hour < 21 && loctm->tm_hour > 9){ Verb1 ("working hours\n"); return Users; } } for (i = 0; i < num_devices; i++){ res = stat (devices [i], &st); if (res != 0) fatal ("stat"); if (now - st.st_atime < IDLE_TIME || now - st.st_mtime < IDLE_TIME || now - st.st_ctime < IDLE_TIME){ Verb1 ("device %s is active\n", devices [i]); return Users; } } return Idle; } void relaunch_workers (void) { int i; unsigned long now = get_date (); for (i = 0; i < nproc; i++){ if (worker_pids [i] != 0){ kill (worker_pids [i], SIGCONT); }else if (worker_time [i] <= now){ worker_pids [i] = fork (); switch (worker_pids [i]){ case 0: worker (); Verb1 ("unexpected return from worker\n"); exit ('w'); break; case -1: worker_pids [i] = 0; Verb1 ("fork failed\n"); break; default: ++ nlive; worker_status [i] = 'r'; sleep (1); break; } } } } void stop_workers (int sig) { int i; for (i = 0; i < nproc; i++){ if (worker_pids [i] != 0) kill (worker_pids [i], sig); } } void send_status (void) { unsigned long now = get_date (); static unsigned long last_date = 0; static char last_stat = 'r'; int sock; int c; FILE *out; char my_status; int i; if (globstatus == 's'){ my_status = 's'; }else{ my_status = 'h'; for (i = 0; i < nproc; i++){ switch (worker_status [i]){ case 'r': my_status = 'r'; break; case 'w': if (my_status != 'r') my_status = 'w'; break; case 'd': if (my_status == 'h') my_status = 'd'; break; case 'h': default: break; } } } if (now - last_date > REPORT_TIME || last_stat != my_status){ Verb2 ("opening socket\n"); sock = open_socket (); if (sock == -1){ Verb1 ("cannot send status\n"); last_date = now + RETRY_TIME - REPORT_TIME; return; } Verb2 ("socket open\n"); out = fdopen (sock, "w"); if (out == NULL) fatal ("fdopen"); Verb1 ("sending status %c\n", my_status); fprintf (out, "s %c %lx %lx\n", my_status, my_addr, nlive); fflush (out); Verb2 ("status sent\n"); last_date = now; last_stat = my_status; fclose (out); close (sock); /* redundant close cannot hurt */ } } void supervisor (void) { unsigned long waittime = INIT_TIME; int res; strcpy (progname, "nicer "); res = (int) (long) signal (SIGCHLD, (void *) bury_child); if (res == -1) fatal ("signal"); send_status (); while (1){ Verb1 ("supervisor waiting for %ld s, state = %c.\n", waittime, globstatus); sleep (waittime); if (check_devices () == Idle){ globstatus = 'r'; }else{ globstatus = 's'; } switch (globstatus){ case 'r': relaunch_workers (); break; case 's': stop_workers (SIGSTOP); sleep (1); break; } send_status (); switch (globstatus){ default: case 'r': waittime = RUN_TIME; break; case 's': waittime = STOP_TIME; break; } } } char testgoal [17] = { 0x2f, 0x2b, 0xb7, 0x0c, 0x07, 0xf9, 0x12, 0x4e, 0xb9, 0x99, 0x53, 0x29, 0xbd, 0xff, 0xf9, 0x7c, 0x26 }; void sanity_check (void) { int res; memcpy (globstruct.goal, testgoal, 17); res = inner_loop (0x0100452); Verb2 ("res = %x\n", res); if (res != 0x301) fatal ("failed sanity check"); } void speed_test (void) { float start_time, end_time; unsigned long n = 1; int res; char result [1000]; Verb1 ("performing speed test...\n"); strcpy ((char *) globstruct.goal, " "); while (1){ Verb1 ("n = %d\n", n); start_time = cpu_time (); res = do_work (0, n, result); if (res != 0) fatal ("key found during speed test !"); end_time = cpu_time (); if (end_time - start_time >= TEST_TIME) break; if (n > 1000) break; n *= 2; } if (end_time - start_time == 0) fatal ("speed test failed"); my_speed = n * 4096.0 / (end_time - start_time); Verb1 ("speed = %d keys/s\n", my_speed); } int main (int argc, char **argv) { struct hostent *entry; char my_name [200]; setvbuf (stdout, NULL, _IOLBF, 0); setvbuf (stderr, NULL, _IOLBF, 0); init_inner_loop (); if (argc < 1 || strlen (argv [0]) < 6){ fprintf (stderr, "argv[0] is too short\n"); exit (2); } progname = argv [0]; if (argc < 3) usage (); while (argc > 3){ if (!strcmp (argv [1], "-v")){ verbose = 1; -- argc; ++ argv; }else if (!strcmp (argv [1], "-V")){ verbose = 2; -- argc; ++ argv; }else if (!strcmp (argv [1], "-t")){ ignore_ttys = 1; -- argc; ++ argv; }else if (!strcmp (argv [1], "-d")){ ignore_devs = 1; -- argc; ++ argv; }else if (!strcmp (argv [1], "-n")){ nproc = 0; sscanf (argv [2], "%lu", &nproc); if (nproc == 0) usage (); argc -= 2; argv += 2; }else if (!strcmp (argv [1], "-w")){ after_hours_only = 1; -- argc; ++ argv; }else{ usage (); } } Verb1 ("version = %d\n", VERSION); worker_pids = (int *) malloc (nproc * sizeof (int)); if (worker_pids == NULL) fatal ("malloc"); memset (worker_pids, 0, nproc * sizeof (int)); worker_status = (char *) malloc (nproc); if (worker_status == NULL) fatal ("malloc"); memset (worker_status, 'x', nproc); worker_time = (unsigned long *) malloc (nproc * sizeof (unsigned long)); if (worker_time == NULL) fatal ("malloc"); memset (worker_time, 0, nproc * sizeof (unsigned long)); if (argc != 3 || argv [1][0] == '-') usage (); portnum = htons (atoi (argv [2])); if (gethostname (my_name, 200) == -1) fatal ("gethostname"); entry = gethostbyname (my_name); if (entry == NULL) fatal ("gethostbyname"); if (entry->h_length != 4) fatal ("wrong address len"); my_addr = ntohl (* (UINT4 *) entry->h_addr); Verb1 ("my_addr = %lx\n", my_addr); entry = gethostbyname (argv [1]); if (entry == NULL) fatal ("gethostbyname"); memcpy (&serverhost, entry, sizeof (serverhost)); sanity_check (); speed_test (); init_devices (); supervisor (); }