|
|
1.1 ! root 1: /* ! 2: * Hunt ! 3: * Copyright (c) 1985 Conrad C. Huang, Gregory S. Couch, Kenneth C.R.C. Arnold ! 4: * San Francisco, California ! 5: * ! 6: * Copyright (c) 1985 Regents of the University of California. ! 7: * All rights reserved. The Berkeley software License Agreement ! 8: * specifies the terms and conditions for redistribution. ! 9: */ ! 10: ! 11: # include <errno.h> ! 12: # include <curses.h> ! 13: # include "hunt.h" ! 14: # include <signal.h> ! 15: # include <ctype.h> ! 16: # include <sys/stat.h> ! 17: ! 18: FLAG Last_player = FALSE; ! 19: # ifdef MONITOR ! 20: FLAG Am_monitor = FALSE; ! 21: # endif MONITOR ! 22: FLAG Query_driver = FALSE; ! 23: ! 24: char Buf[BUFSIZ]; ! 25: ! 26: int Master_pid; ! 27: int Socket; ! 28: # ifdef INTERNET ! 29: char *Sock_host; ! 30: # endif INTERNET ! 31: ! 32: SOCKET Daemon; ! 33: # ifdef INTERNET ! 34: # define DAEMON_SIZE (sizeof Daemon) ! 35: # else INTERNET ! 36: # define DAEMON_SIZE (sizeof Daemon - 1) ! 37: # endif INTERNET ! 38: ! 39: char map_key[256]; /* what to map keys to */ ! 40: ! 41: static char name[NAMELEN]; ! 42: ! 43: extern int cur_row, cur_col, _putchar(); ! 44: extern char *tgoto(); ! 45: ! 46: /* ! 47: * main: ! 48: * Main program for local process ! 49: */ ! 50: main(ac, av) ! 51: int ac; ! 52: char **av; ! 53: { ! 54: char *term; ! 55: extern int errno; ! 56: extern int Otto_mode; ! 57: int dumpit(), intr(), sigterm(), sigemt(), tstp(); ! 58: ! 59: for (ac--, av++; ac > 0 && av[0][0] == '-'; ac--, av++) { ! 60: switch (av[0][1]) { ! 61: ! 62: case 'l': /* rsh compatibility */ ! 63: case 'n': ! 64: if (ac <= 1) ! 65: goto usage; ! 66: ac--, av++; ! 67: (void) strcpy(name, av[0]); ! 68: break; ! 69: case 'o': ! 70: # ifndef OTTO ! 71: fputs("The -o flag is reserved for future use.\n", ! 72: stderr); ! 73: goto usage; ! 74: # else OTTO ! 75: Otto_mode = TRUE; ! 76: break; ! 77: # endif OTTO ! 78: # ifdef MONITOR ! 79: case 'm': ! 80: Am_monitor = TRUE; ! 81: break; ! 82: # endif MONITOR ! 83: # ifdef INTERNET ! 84: case 'q': /* query whether hunt is running */ ! 85: Query_driver = TRUE; ! 86: break; ! 87: case 'h': ! 88: if (ac <= 1) ! 89: goto usage; ! 90: ac--, av++; ! 91: Sock_host = av[0]; ! 92: break; ! 93: # endif INTERNET ! 94: default: ! 95: usage: ! 96: # ifdef INTERNET ! 97: # ifdef MONITOR ! 98: # define USAGE "usage: hunt [-q] [-n name] [-h host] [-m]\n" ! 99: # else MONITOR ! 100: # define USAGE "usage: hunt [-q] [-n name] [-h host]\n" ! 101: # endif MONITOR ! 102: # else INTERNET ! 103: # ifdef MONITOR ! 104: # define USAGE "usage: hunt [-n name] [-m]\n" ! 105: # else MONITOR ! 106: # define USAGE "usage: hunt [-n name]\n" ! 107: # endif MONITOR ! 108: # endif INTERNET ! 109: fputs(USAGE, stderr); ! 110: # undef USAGE ! 111: exit(1); ! 112: } ! 113: } ! 114: # ifdef INTERNET ! 115: if (ac > 1) ! 116: goto usage; ! 117: else if (ac > 0) ! 118: Sock_host = av[0]; ! 119: # else INTERNET ! 120: if (ac > 0) ! 121: goto usage; ! 122: # endif INTERNET ! 123: ! 124: # ifdef INTERNET ! 125: if (Query_driver) { ! 126: find_driver(FALSE); ! 127: if (Daemon.sin_port != 0) { ! 128: struct hostent *hp; ! 129: ! 130: hp = gethostbyaddr(&Daemon.sin_addr, ! 131: sizeof Daemon.sin_addr, AF_INET); ! 132: fprintf(stderr, "HUNT!! found on %s\n", hp != NULL ! 133: ? hp->h_name : inet_ntoa(Daemon.sin_addr)); ! 134: } ! 135: exit(Daemon.sin_port == 0); ! 136: } ! 137: # endif INTERNET ! 138: # ifdef OTTO ! 139: if (Otto_mode) ! 140: (void) strcpy(name, "otto"); ! 141: else ! 142: # endif OTTO ! 143: env_init(); ! 144: ! 145: (void) fflush(stdout); ! 146: if (!isatty(0) || (term = getenv("TERM")) == NULL) { ! 147: fprintf(stderr, "no terminal type\n"); ! 148: exit(1); ! 149: } ! 150: _tty_ch = 0; ! 151: gettmode(); ! 152: setterm(term); ! 153: noecho(); ! 154: cbreak(); ! 155: _puts(TI); ! 156: _puts(VS); ! 157: clear_screen(); ! 158: (void) signal(SIGINT, intr); ! 159: (void) signal(SIGTERM, sigterm); ! 160: (void) signal(SIGEMT, sigemt); ! 161: (void) signal(SIGQUIT, dumpit); ! 162: (void) signal(SIGPIPE, SIG_IGN); ! 163: (void) signal(SIGTSTP, tstp); ! 164: ! 165: do { ! 166: # ifdef INTERNET ! 167: find_driver(TRUE); ! 168: ! 169: do { ! 170: int msg; ! 171: ! 172: # ifndef OLDIPC ! 173: Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0); ! 174: # else OLDIPC ! 175: Socket = socket(SOCK_STREAM, 0, 0, 0); ! 176: # endif OLDIPC ! 177: if (Socket < 0) { ! 178: perror("socket"); ! 179: exit(1); ! 180: } ! 181: # ifndef OLDIPC ! 182: msg = 1; ! 183: if (setsockopt(Socket, SOL_SOCKET, SO_USELOOPBACK, ! 184: &msg, sizeof msg) < 0) ! 185: perror("setsockopt loopback"); ! 186: # endif OLDIPC ! 187: errno = 0; ! 188: if (connect(Socket, (struct sockaddr *) &Daemon, ! 189: DAEMON_SIZE) < 0) { ! 190: if (errno != ECONNREFUSED) { ! 191: perror("connect"); ! 192: leave(1, "connect"); ! 193: } ! 194: } ! 195: else ! 196: break; ! 197: sleep(1); ! 198: } while (close(Socket) == 0); ! 199: # else INTERNET ! 200: /* ! 201: * set up a socket ! 202: */ ! 203: ! 204: if ((Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0)) < 0) { ! 205: perror("socket"); ! 206: exit(1); ! 207: } ! 208: ! 209: /* ! 210: * attempt to connect the socket to a name; if it fails that ! 211: * usually means that the driver isn't running, so we start ! 212: * up the driver. ! 213: */ ! 214: ! 215: Daemon.sun_family = SOCK_FAMILY; ! 216: (void) strcpy(Daemon.sun_path, Sock_name); ! 217: if (connect(Socket, &Daemon, DAEMON_SIZE) < 0) { ! 218: if (errno != ENOENT) { ! 219: perror("connect"); ! 220: leave(1, "connect2"); ! 221: } ! 222: start_driver(); ! 223: ! 224: do { ! 225: (void) close(Socket); ! 226: if ((Socket = socket(SOCK_FAMILY, SOCK_STREAM, 0)) < 0) { ! 227: perror("socket"); ! 228: exit(1); ! 229: } ! 230: sleep(2); ! 231: } while (connect(Socket, &Daemon, DAEMON_SIZE) < 0); ! 232: } ! 233: # endif INTERNET ! 234: ! 235: do_connect(name); ! 236: playit(); ! 237: } while (!quit()); ! 238: leave(0, NULL); ! 239: /* NOTREACHED */ ! 240: } ! 241: ! 242: # ifdef INTERNET ! 243: # ifdef BROADCAST ! 244: broadcast_vec(s, vector) ! 245: int s; /* socket */ ! 246: struct sockaddr **vector; ! 247: { ! 248: char if_buf[BUFSIZ]; ! 249: struct ifconf ifc; ! 250: struct ifreq *ifr; ! 251: int n; ! 252: int vec_cnt; ! 253: ! 254: *vector = NULL; ! 255: ifc.ifc_len = sizeof if_buf; ! 256: ifc.ifc_buf = if_buf; ! 257: if (ioctl(s, SIOCGIFCONF, (char *) &ifc) < 0) ! 258: return 0; ! 259: vec_cnt = 0; ! 260: n = ifc.ifc_len / sizeof (struct ifreq); ! 261: *vector = (struct sockaddr *) malloc(n * sizeof (struct sockaddr)); ! 262: for (ifr = ifc.ifc_req; n > 0; n--, ifr++) ! 263: if (ioctl(s, SIOCGIFBRDADDR, ifr) >= 0) ! 264: bcopy(&ifr->ifr_addr, &(*vector)[vec_cnt++], ! 265: sizeof (struct sockaddr)); ! 266: return vec_cnt; ! 267: } ! 268: # endif BROADCAST ! 269: ! 270: find_driver(do_startup) ! 271: FLAG do_startup; ! 272: { ! 273: int msg; ! 274: static SOCKET test; ! 275: int test_socket; ! 276: int namelen; ! 277: char local_name[80]; ! 278: static initial = TRUE; ! 279: static struct in_addr local_address; ! 280: register struct hostent *hp; ! 281: int (*oldsigalrm)(), sigalrm(); ! 282: extern int errno; ! 283: # ifdef BROADCAST ! 284: static int brdc; ! 285: static SOCKET *brdv; ! 286: int i; ! 287: # endif BROADCAST ! 288: ! 289: if (Sock_host != NULL) { ! 290: if (!initial) ! 291: return; /* Daemon address already valid */ ! 292: initial = FALSE; ! 293: if ((hp = gethostbyname(Sock_host)) == NULL) { ! 294: leave(1, "Unknown host"); ! 295: /* NOTREACHED */ ! 296: } ! 297: Daemon.sin_family = SOCK_FAMILY; ! 298: Daemon.sin_port = htons(Sock_port); ! 299: Daemon.sin_addr = *((struct in_addr *) hp->h_addr); ! 300: if (!Query_driver) ! 301: return; ! 302: } ! 303: ! 304: ! 305: if (initial) { /* do one time initialization */ ! 306: # ifndef BROADCAST ! 307: sethostent(1); /* don't bother to close host file */ ! 308: # endif BROADCAST ! 309: if (gethostname(local_name, sizeof local_name) < 0) { ! 310: leave(1, "Sorry, I have no name."); ! 311: /* NOTREACHED */ ! 312: } ! 313: if ((hp = gethostbyname(local_name)) == NULL) { ! 314: leave(1, "Can't find myself."); ! 315: /* NOTREACHED */ ! 316: } ! 317: local_address = * ((struct in_addr *) hp->h_addr); ! 318: ! 319: test.sin_family = SOCK_FAMILY; ! 320: test.sin_addr = local_address; ! 321: test.sin_port = htons(Test_port); ! 322: } ! 323: ! 324: # ifndef OLDIPC ! 325: test_socket = socket(SOCK_FAMILY, SOCK_DGRAM, 0); ! 326: # else OLDIPC ! 327: test_socket = socket(SOCK_DGRAM, 0, 0, 0); ! 328: # endif OLCIPC ! 329: if (test_socket < 0) { ! 330: perror("socket"); ! 331: leave(1, "socket system call failed"); ! 332: /* NOTREACHED */ ! 333: } ! 334: ! 335: msg = 1; ! 336: if (Query_driver && Sock_host != NULL) { ! 337: test.sin_family = SOCK_FAMILY; ! 338: test.sin_addr = Daemon.sin_addr; ! 339: test.sin_port = htons(Test_port); ! 340: # ifndef OLDIPC ! 341: (void) sendto(test_socket, (char *) &msg, sizeof msg, 0, ! 342: (struct sockaddr *) &test, DAEMON_SIZE); ! 343: # else OLDIPC ! 344: (void) send(test_socket, (struct sockaddr *) &test, ! 345: (char *) &msg, sizeof msg); ! 346: # endif OLDIPC ! 347: goto get_response; ! 348: } ! 349: ! 350: if (!initial) { ! 351: /* favor host of previous session by broadcasting to it first */ ! 352: test.sin_addr = Daemon.sin_addr; ! 353: test.sin_port = htons(Test_port); ! 354: (void) sendto(test_socket, (char *) &msg, sizeof msg, 0, ! 355: (struct sockaddr *) &test, DAEMON_SIZE); ! 356: } ! 357: ! 358: ! 359: # ifdef BROADCAST ! 360: if (initial) ! 361: brdc = broadcast_vec(test_socket, &brdv); ! 362: ! 363: if (brdc <= 0) { ! 364: Daemon.sin_family = SOCK_FAMILY; ! 365: Daemon.sin_addr = local_address; ! 366: Daemon.sin_port = htons(Sock_port); ! 367: initial = FALSE; ! 368: return; ! 369: } ! 370: ! 371: if (setsockopt(test_socket, SOL_SOCKET, SO_BROADCAST, ! 372: (int) &msg, sizeof msg) < 0) { ! 373: perror("setsockopt broadcast"); ! 374: leave(1, "setsockopt broadcast"); ! 375: /* NOTREACHED */ ! 376: } ! 377: ! 378: /* send broadcast packets on all interfaces */ ! 379: for (i = 0; i < brdc; i++) { ! 380: bcopy(&brdv[i], &test, sizeof (SOCKET)); ! 381: test.sin_port = htons(Test_port); ! 382: if (sendto(test_socket, (char *) &msg, sizeof msg, 0, ! 383: (struct sockaddr *) &test, DAEMON_SIZE) < 0) { ! 384: perror("sendto"); ! 385: leave(1, "sendto"); ! 386: /* NOTREACHED */ ! 387: } ! 388: } ! 389: # else BROADCAST ! 390: /* loop thru all hosts on local net and send msg to them. */ ! 391: sethostent(0); /* rewind host file */ ! 392: while (hp = gethostent()) { ! 393: if (inet_netof(test.sin_addr) ! 394: == inet_netof(* ((struct in_addr *) hp->h_addr))) { ! 395: test.sin_addr = * ((struct in_addr *) hp->h_addr); ! 396: # ifndef OLDIPC ! 397: (void) sendto(test_socket, (char *) &msg, sizeof msg, 0, ! 398: (struct sockaddr *) &test, DAEMON_SIZE); ! 399: # else OLDIPC ! 400: (void) send(test_socket, (struct sockaddr *) &test, ! 401: (char *) &msg, sizeof msg); ! 402: # endif OLDIPC ! 403: } ! 404: } ! 405: # endif BROADCAST ! 406: ! 407: get_response: ! 408: namelen = DAEMON_SIZE; ! 409: oldsigalrm = signal(SIGALRM, sigalrm); ! 410: errno = 0; ! 411: (void) alarm(1); ! 412: # ifndef OLDIPC ! 413: if (recvfrom(test_socket, (char *) &msg, sizeof msg, 0, ! 414: (struct sockaddr *) &Daemon, &namelen) < 0) ! 415: # else OLDIPC ! 416: if (receive(test_socket, (struct sockaddr *) &Daemon, &msg, ! 417: sizeof msg) < 0) ! 418: # endif OLDIPC ! 419: { ! 420: if (errno != EINTR) { ! 421: perror("recvfrom"); ! 422: leave(1, "recvfrom"); ! 423: /* NOTREACHED */ ! 424: } ! 425: (void) alarm(0); ! 426: (void) signal(SIGALRM, oldsigalrm); ! 427: Daemon.sin_family = SOCK_FAMILY; ! 428: Daemon.sin_port = htons(Sock_port); ! 429: Daemon.sin_addr = local_address; ! 430: if (!do_startup) ! 431: Daemon.sin_port = 0; ! 432: else ! 433: start_driver(); ! 434: } ! 435: else { ! 436: (void) alarm(0); ! 437: (void) signal(SIGALRM, oldsigalrm); ! 438: Daemon.sin_port = htons(Sock_port); ! 439: } ! 440: (void) close(test_socket); ! 441: initial = FALSE; ! 442: } ! 443: # endif INTERNET ! 444: ! 445: start_driver() ! 446: { ! 447: register int procid; ! 448: ! 449: # ifdef MONITOR ! 450: if (Am_monitor) { ! 451: leave(1, "No one playing."); ! 452: /* NOTREACHED */ ! 453: } ! 454: # endif MONITOR ! 455: ! 456: # ifdef INTERNET ! 457: if (Sock_host != NULL) { ! 458: sleep(3); ! 459: return 0; ! 460: } ! 461: # endif INTERNET ! 462: ! 463: mvcur(cur_row, cur_col, 23, 0); ! 464: cur_row = 23; ! 465: cur_col = 0; ! 466: put_str("Starting..."); ! 467: fflush(stdout); ! 468: procid = vfork(); ! 469: if (procid == -1) { ! 470: perror("fork"); ! 471: leave(1, "fork failed."); ! 472: } ! 473: if (procid == 0) { ! 474: (void) signal(SIGINT, SIG_IGN); ! 475: (void) close(Socket); ! 476: execl(Driver, "HUNT", NULL); ! 477: /* only get here if exec failed */ ! 478: kill(getppid(), SIGEMT); /* tell mom */ ! 479: _exit(1); ! 480: } ! 481: mvcur(cur_row, cur_col, 23, 0); ! 482: cur_row = 23; ! 483: cur_col = 0; ! 484: put_str("Connecting..."); ! 485: fflush(stdout); ! 486: return 0; ! 487: } ! 488: ! 489: /* ! 490: * bad_con: ! 491: * We had a bad connection. For the moment we assume that this ! 492: * means the game is full. ! 493: */ ! 494: bad_con() ! 495: { ! 496: leave(1, "The game is full. Sorry."); ! 497: /* NOTREACHED */ ! 498: } ! 499: ! 500: /* ! 501: * dumpit: ! 502: * Handle a core dump signal by not dumping core, just leaving, ! 503: * so we end up with a core dump from the driver ! 504: */ ! 505: dumpit() ! 506: { ! 507: (void) kill(Master_pid, SIGQUIT); ! 508: (void) chdir("coredump"); ! 509: abort(); ! 510: } ! 511: ! 512: /* ! 513: * sigterm: ! 514: * Handle a terminate signal ! 515: */ ! 516: sigterm() ! 517: { ! 518: leave(0, NULL); ! 519: /* NOTREACHED */ ! 520: } ! 521: ! 522: ! 523: /* ! 524: * sigemt: ! 525: * Handle a emt signal - shouldn't happen on vaxes(?) ! 526: */ ! 527: sigemt() ! 528: { ! 529: leave(1, "Unable to start driver. Try again."); ! 530: /* NOTREACHED */ ! 531: } ! 532: ! 533: # ifdef INTERNET ! 534: /* ! 535: * sigalrm: ! 536: * Handle an alarm signal ! 537: */ ! 538: sigalrm() ! 539: { ! 540: return; ! 541: } ! 542: # endif INTERNET ! 543: ! 544: /* ! 545: * rmnl: ! 546: * Remove a '\n' at the end of a string if there is one ! 547: */ ! 548: rmnl(s) ! 549: char *s; ! 550: { ! 551: register char *cp; ! 552: char *rindex(); ! 553: ! 554: cp = rindex(s, '\n'); ! 555: if (cp != NULL) ! 556: *cp = '\0'; ! 557: } ! 558: ! 559: /* ! 560: * intr: ! 561: * Handle a interrupt signal ! 562: */ ! 563: intr() ! 564: { ! 565: register int ch; ! 566: register int explained; ! 567: register int y, x; ! 568: ! 569: (void) signal(SIGINT, SIG_IGN); ! 570: y = cur_row; ! 571: x = cur_col; ! 572: mvcur(cur_row, cur_col, 23, 0); ! 573: cur_row = 23; ! 574: cur_col = 0; ! 575: put_str("Really quit? "); ! 576: clear_eol(); ! 577: fflush(stdout); ! 578: explained = FALSE; ! 579: for (;;) { ! 580: ch = getchar(); ! 581: if (isupper(ch)) ! 582: ch = tolower(ch); ! 583: if (ch == 'y') { ! 584: (void) write(Socket, "q", 1); ! 585: (void) close(Socket); ! 586: leave(0, NULL); ! 587: } ! 588: else if (ch == 'n') { ! 589: (void) signal(SIGINT, intr); ! 590: mvcur(cur_row, cur_col, y, x); ! 591: cur_row = y; ! 592: cur_col = x; ! 593: fflush(stdout); ! 594: return; ! 595: } ! 596: if (!explained) { ! 597: put_str("(Y or N) "); ! 598: fflush(stdout); ! 599: explained = TRUE; ! 600: } ! 601: (void) putchar(CTRL(G)); ! 602: (void) fflush(stdout); ! 603: } ! 604: } ! 605: ! 606: /* ! 607: * leave: ! 608: * Leave the game somewhat gracefully, restoring all current ! 609: * tty stats. ! 610: */ ! 611: leave(eval, mesg) ! 612: int eval; ! 613: char *mesg; ! 614: { ! 615: mvcur(cur_row, cur_col, 23, 0); ! 616: if (mesg == NULL) ! 617: clear_eol(); ! 618: else { ! 619: put_str(mesg); ! 620: clear_eol(); ! 621: putchar('\n'); ! 622: fflush(stdout); /* flush in case VE changes pages */ ! 623: } ! 624: resetty(); ! 625: _puts(VE); ! 626: _puts(TE); ! 627: exit(eval); ! 628: } ! 629: ! 630: /* ! 631: * tstp: ! 632: * Handle stop and start signals ! 633: */ ! 634: tstp() ! 635: { ! 636: static struct sgttyb tty; ! 637: int y, x; ! 638: ! 639: tty = _tty; ! 640: y = cur_row; ! 641: x = cur_col; ! 642: mvcur(cur_row, cur_col, 23, 0); ! 643: cur_row = 23; ! 644: cur_col = 0; ! 645: _puts(VE); ! 646: _puts(TE); ! 647: (void) fflush(stdout); ! 648: resetty(); ! 649: (void) kill(getpid(), SIGSTOP); ! 650: (void) signal(SIGTSTP, tstp); ! 651: _tty = tty; ! 652: (void) stty(_tty_ch, &_tty); ! 653: _puts(TI); ! 654: _puts(VS); ! 655: cur_row = y; ! 656: cur_col = x; ! 657: _puts(tgoto(CM, cur_row, cur_col)); ! 658: redraw_screen(); ! 659: fflush(stdout); ! 660: } ! 661: ! 662: env_init() ! 663: { ! 664: register int i; ! 665: char *envp, *envname, *s, *index(); ! 666: ! 667: for (i = 0; i < 256; i++) ! 668: map_key[i] = (char) i; ! 669: ! 670: envname = NULL; ! 671: if ((envp = getenv("HUNT")) != NULL) { ! 672: while ((s = index(envp, '=')) != NULL) { ! 673: if (strncmp(envp, "name=", s - envp + 1) == 0) { ! 674: envname = s + 1; ! 675: if ((s = index(envp, ',')) == NULL) { ! 676: *envp = '\0'; ! 677: break; ! 678: } ! 679: *s = '\0'; ! 680: envp = s + 1; ! 681: } /* must be last option */ ! 682: else if (strncmp(envp, "mapkey=", s - envp + 1) == 0) { ! 683: for (s = s + 1; *s != '\0'; s += 2) { ! 684: map_key[(unsigned int) *s] = *(s + 1); ! 685: if (*(s + 1) == '\0') { ! 686: break; ! 687: } ! 688: } ! 689: *envp = '\0'; ! 690: break; ! 691: } else { ! 692: *s = '\0'; ! 693: printf("unknown option %s\n", envp); ! 694: if ((s = index(envp, ',')) == NULL) { ! 695: *envp = '\0'; ! 696: break; ! 697: } ! 698: envp = s + 1; ! 699: } ! 700: } ! 701: if (*envp != '\0') ! 702: if (envname == NULL) ! 703: envname = envp; ! 704: else ! 705: printf("unknown option %s\n", envp); ! 706: } ! 707: if (envname != NULL) { ! 708: (void) strcpy(name, envname); ! 709: printf("Entering as '%s'\n", envname); ! 710: } ! 711: else if (name[0] == '\0') { ! 712: printf("Enter your code name: "); ! 713: if (fgets(name, sizeof name, stdin) == NULL) ! 714: exit(1); ! 715: } ! 716: rmnl(name); ! 717: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.