#include #include #include #include #include #include #include #include void sigpipe (int sig) { char * s = "Client terminated prematurly\n"; write (2, s, strlen (s)); _exit (1); } int readline (char * buf, int len) { int i=0; int cridx = -1; assert (len > 3); while (i < len-1) { int ret = read (0, buf+i, 1); if (ret < 0) { perror ("read"); exit (1); } if (ret == 0) { fprintf (stderr, "At least they could say goodbye\n"); exit (1); } i++; if (buf[i-1] == '\n') break; if (cridx < 0 || buf[i-1] == '\r') cridx = i-1; } buf[i] = 0; if (i < 2 || buf[i-1] != '\n' || buf[i-2] != '\r') { return 0; } if (cridx != i-2) { return 0; } return 1; } void writeline (char * buf) { int len = strlen (buf); assert (len >= 2 && buf[len-1] == '\n' && buf[len-2] == '\r'); while (len) { int off = 1+rand()%5; if (off > len) off = len; int done = write (1, buf, off); if (done < 0) { perror ("write"); exit (1); } len -= done; buf += done; yield(); } } int main () { static char buf[1000]; static char code[20]; static int cols[20]; int colmax, lenmax; int len, col, unique; int running = 0; int i; struct sigaction act; act.sa_flags = 0; sigemptyset (&act.sa_mask); act.sa_handler = sigpipe; if (sigaction (SIGPIPE, &act, NULL) < 0) { perror ("sigaction"); exit (1); } srand (time(0) + getpid ()); colmax = 3+rand()%10; lenmax = 3+rand()%10; sprintf (buf, "200 MMSERVER colmax=%d lenmax=%d\r\n", colmax, lenmax); writeline (buf); while (1) { int ret = readline (buf, 1000); if (!ret) { writeline ("300 Line Format Error\r\n"); continue; } if (strncasecmp (buf, "GAME ", 5) == 0) { char * p = buf+5; int add; if (running) { writeline ("400 Game already running\r\n"); continue; } unique = -1; if (strncasecmp (p, "UNIQUE ", 7) == 0) { unique = 1; p += 7; } else if (strncasecmp (p, "FREE ", 5) == 0) { unique = 0; p += 5; } if (unique < 0) { writeline ("301 FREE/UNIQUE missing\r\n"); continue; } if (sscanf (p, "%d %d%n", &col, &len, &add) < 2) { writeline ("302 Can't parse col/len\r\n"); continue; } p += add; if (col>colmax || len>lenmax || col<1 || len<1) { writeline ("500 Parameters out of range\r\n"); continue; } if (unique && col < len) { writeline ("501 Impossible parameters\r\n"); continue; } if (p[0] != '\r' || p[1] != '\n') { writeline ("303 Chunk at end of line\r\n"); continue; } running = 1; for (i=0; i= col) { badc = 1; break; } if (unique && mcol[c]) { badun = 1; break; } mcol[c]++; if (code[i] == 'A' + c) blacks++; } if (badc) { writeline ("502 Colour out of range\r\n"); continue; } if (badun) { writeline ("503 Colours not unique\r\n"); continue; } whites = 0; for (i=0; i= 0); if (blacks == len) { writeline ("205 Congratulations\r\n"); running = 0; continue; } sprintf (buf, "206 Blacks=%d Whites=%d\r\n",blacks, whites); writeline (buf); continue; } if (strcasecmp (buf, "QUIT\r\n") == 0) { yield(); yield(); yield(); writeline ("207 Good Bye\r\n"); exit (0); } writeline ("310 Unknown command\r\n"); } return 0; }