home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / games / volume1 / gr / gr.c < prev    next >
C/C++ Source or Header  |  1987-04-22  |  17KB  |  777 lines

  1. /*
  2.  *                  GR - A  G A M E   R E G U L A T O R
  3.  *                          for Berkeley UNIX
  4.  *
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: gr.c,v 1.32 86/12/02 20:26:57 mcooper Locked $";
  9. #endif
  10.  
  11. /*
  12.  *------------------------------------------------------------------
  13.  *
  14.  * $Source: /big/src/usc/bin/gr/RCS/gr.c,v $
  15.  * $Revision: 1.32 $
  16.  * $Date: 86/12/02 20:26:57 $
  17.  * $State: Exp $
  18.  * $Author: mcooper $
  19.  * $Locker: mcooper $
  20.  *
  21.  *------------------------------------------------------------------
  22.  *
  23.  * Michael A. Cooper (mcooper@oberon.USC.EDU)
  24.  * University Computing Services,
  25.  * University of Southern California
  26.  *
  27.  *------------------------------------------------------------------
  28.  * $Log:    gr.c,v $
  29.  * Revision 1.32  86/12/02  20:26:57  mcooper
  30.  * #ifdef'd all dprintf's.
  31.  * 
  32.  * Revision 1.31  86/08/06  20:07:55  mcooper
  33.  * Yet another attempt at fixing the setuid
  34.  * problem.  Think I got it this time!
  35.  * 
  36.  * Revision 1.30  86/08/05  12:54:22  mcooper
  37.  * Fixed setuid() problem (again).
  38.  * 
  39.  * Revision 1.29  86/07/30  12:22:30  mcooper
  40.  * If DEBUG is defined, use a SLEEPTIME of 5
  41.  * to speed things up.
  42.  * 
  43.  * Revision 1.28  86/07/17  16:13:04  mcooper
  44.  * All fatal errors now use fatal().
  45.  * 
  46.  * Revision 1.27  86/07/17  14:49:21  mcooper
  47.  * - Fixed bug in freettys() that caused
  48.  *   was_freettys to be TRUE when there
  49.  *   where exactly cf->cf_nofreettys free.
  50.  * - Tweaked was_freettys user message a bit.
  51.  * 
  52.  * Revision 1.26  86/07/15  14:53:36  mcooper
  53.  * Determine user name in setup() instead of
  54.  * everytime logfile() is called.
  55.  * 
  56.  * Revision 1.25  86/07/14  19:03:45  mcooper
  57.  * Log more info to a log file.
  58.  * 
  59.  * Revision 1.24  86/07/14  15:53:53  mcooper
  60.  * Moved most of the compile time configuration
  61.  * options to the control file.
  62.  * 
  63.  * Revision 1.23  86/07/03  15:54:41  mcooper
  64.  * Now checks for NOGAMING file along with the
  65.  * other tests in case game playing is turn off
  66.  * while we're playing.
  67.  * 
  68.  * Revision 1.22  86/07/03  14:25:07  mcooper
  69.  * - Major work on "special" ttys.  
  70.  *   - Bug fix in deltty().
  71.  *   - Changed are #define macros.
  72.  *   - Added findtty() (in findtty.c) to try and
  73.  *     determine the users real tty.  (4.2bsd)
  74.  * - Added debug mode.
  75.  * - Misc. - Can't remember them all.
  76.  * 
  77.  * Revision 1.21  86/06/18  13:46:47  mcooper
  78.  * Implemented BAD_TTYS - Check to see if
  79.  * the user is on a BAD_TTYS.  If so, game
  80.  * playing is not permited at all.  Also
  81.  * cleaned up #ifdef TOD stuff.
  82.  * 
  83.  * Revision 1.20  86/06/04  12:21:23  mcooper
  84.  * Use SP_NAME for name of special ttys when
  85.  * printing messages to the user.
  86.  * 
  87.  * Revision 1.19  86/06/02  13:31:53  mcooper
  88.  * More cleanup on SP_TTYS.
  89.  * 
  90.  * Revision 1.18  86/05/30  21:33:10  mcooper
  91.  * Added support for "special" ttys.  i.e. only a limited
  92.  * number of SP_TTYS.
  93.  * 
  94.  * Revision 1.17  86/05/14  16:08:44  mcooper
  95.  * Cleaned up and somewhat de-linted.
  96.  * 
  97.  *------------------------------------------------------------------
  98.  */
  99.  
  100. #include <stdio.h>
  101. #include <pwd.h>
  102. #include <signal.h>
  103. #include <sys/wait.h>
  104. #include <sys/types.h>
  105. #include <sys/stat.h>
  106. #include <sys/time.h>
  107. #include <sys/resource.h>
  108. #include <sys/file.h>
  109. #include <utmp.h>
  110. #include <nlist.h>
  111.  
  112. #include <sys/vm.h>
  113. #include <machine/pte.h>
  114.  
  115. #include "gr.h"
  116.  
  117. #ifdef DEBUG
  118. int sleeptime = 5;
  119. #else
  120. int sleeptime = SLEEPTIME;
  121. #endif
  122.  
  123. int hastried = 0;
  124.  
  125. int Fswap;
  126. int Fpmem;
  127. int Fkmem;
  128. int Futmp;
  129.  
  130. char *mytty;
  131. char *user;
  132. char *prog = "GR";
  133.  
  134. static char *badtty;
  135. #ifdef FINDTTY
  136. struct pte *usrptmap, *usrpt;    /* Hold values of _Usrptmap & _usrpt */
  137. int i_proc, i_nproc;            /* Hold values of _proc & _nproc */
  138. #endif
  139.  
  140. int was_freettys;
  141. int was_badttys;
  142. int was_tod;
  143. int was_load;
  144. int was_nogames;
  145. int was_users;
  146.  
  147. static double avenrun[3];
  148. static char *game;
  149. char mbuf[BUFSIZ];
  150.  
  151.  
  152. char *warnmesg1 = "to save your game.  If you do not leave\r\nthe game ";
  153. char *warnmesg2 = "within this period, your game will be terminated.";
  154.  
  155. char *warntime[3] = {
  156.     "4 minutes ",
  157.     "2 minutes ",
  158.     "1 minute "
  159. };
  160.  
  161.  
  162. static struct utmp buf;
  163. static struct nlist nl[] = {
  164. #define N_AVENRUN    0
  165.     { "_avenrun" },
  166. #ifdef FINDTTY
  167. #define N_PROC        1                /* Address of process table */
  168.     { "_proc" },
  169. #define N_NPROC        2                /* Length of process table */
  170.     { "_nproc" },
  171. #define N_USRPTMAP     3
  172.     { "_Usrptmap" },
  173. #define N_USRPT     4
  174.     { "_usrpt" },
  175. #endif
  176.     { "" },
  177. };
  178.  
  179. char *rindex();
  180. char *deltty();
  181. char *gettyname();
  182. char *getaline();
  183. long time();
  184.  
  185. int debug = 0;
  186. struct cfinfo *cf, *parse();
  187.  
  188. /*VARARGS*/
  189. main(argc, argv)
  190. int argc;
  191. char **argv;
  192. {
  193.     game = rindex(argv[0], '/');
  194.     if (game == 0)
  195.         game = argv[0];
  196.     else
  197.         game++;    /* Skip the '/' */
  198.  
  199.     if (strcmp(game, "debug") == 0)
  200.         debug = 1;
  201.  
  202.     if (debug) {
  203.         setbuf(stdout, 0);
  204. #ifdef DEBUG
  205.         dprintf("debug is ON\n");
  206. #endif DEBUG
  207.         sleeptime = 5;
  208.     }
  209.  
  210.     setup(game);
  211.  
  212.     if (checkfor(cf->cf_nogames) || tod() || badttys() || freettys() || 
  213.       users() || load()) {
  214.         fprintf(stderr, "Sorry, no games now.\n");
  215.         if (was_nogames)
  216.             fprintf(stderr, getaline(cf->cf_nogames));
  217.         if (was_freettys)
  218.             fprintf(stderr, "There %s not %d %s tty%c available.\n",
  219.                 (cf->cf_nofreettys > 1) ? "are" : "is", cf->cf_nofreettys,
  220.                 cf->cf_spname, (cf->cf_nofreettys > 1) ? 's' : 0);
  221.         if (was_badttys)
  222.             fprintf(stderr, 
  223.             "Game playing is not permitted on tty%s at any time.\n",
  224.                 badtty);
  225.         if (was_load)
  226.             fprintf(stderr, 
  227.                 "The system load is greater than %.2lf.\n",
  228.                 cf->cf_load);
  229.         if (was_users)
  230.             fprintf(stderr, 
  231.                 "There are more than %d users logged in.\n",
  232.                 cf->cf_users);
  233.         if (was_tod)
  234.             fprintf(stderr, 
  235. "Game playing is not permitted between %d00 and %d00 hours on weekdays.\n", 
  236.                 cf->cf_todmorn, cf->cf_todeven);
  237.         exit(1);
  238.     }
  239.     if (cf->cf_logfile[0]) {
  240.         sprintf(mbuf, "startup of %s (%d)", game, getpid());
  241.         logfile(mbuf, cf->cf_logfile);
  242.     }
  243.     play(game, argv);
  244. }
  245.  
  246. play(game, args)
  247. char *game;
  248. char **args;
  249. {
  250.     int pid;
  251.     char tmp[BUFSIZ];
  252.  
  253.     switch (pid = fork()) {
  254.         case -1:
  255.             fprintf(stderr, "Cannot fork.\n");
  256.             exit(1);
  257.         case 0:
  258.             (void) strcpy(tmp, cf->cf_hidedir);
  259.             (void) strcat(tmp, "/");
  260.             (void) strcat(tmp, game);
  261.             (void) signal(SIGINT, SIG_DFL);
  262.             (void) signal(SIGQUIT, SIG_DFL);
  263.             (void) signal(SIGTSTP, SIG_DFL);
  264. #ifdef DEBUG
  265.             dprintf("before: getuid = %d\n", getuid());
  266.             dprintf("before: geteuid = %d\n", geteuid());
  267. #endif DEBUG
  268.             (void) setuid(getuid());
  269. #ifdef DEBUG
  270.             dprintf("after: getuid = %d\n", getuid());
  271.             dprintf("after: geteuid = %d\n", geteuid());
  272. #endif DEBUG
  273.             if(setpriority(PRIO_PROCESS, 0, cf->cf_priority) < 0) {
  274.                 fatal("setpriority", TRUE);
  275.                 /*NOTREACHED*/
  276.             }
  277.             execv(tmp, args);
  278.             fatal(tmp, TRUE);
  279.             /*NOTREACHED*/
  280.     }
  281.     for (;;) {
  282.         sleep(sleeptime);
  283.         if (load() || checkfor(cf->cf_nogames) || tod() || freettys() || 
  284.           users()) {
  285.             warn(0);
  286.             sleep(sleeptime);
  287.             if (reprieve())
  288.                 continue;
  289.             sleep(sleeptime);
  290.             if (reprieve())
  291.                 continue;
  292.             warn(1);
  293.             sleep(sleeptime);
  294.             if (reprieve())
  295.                 continue;
  296.             warn(2);
  297.             sleep(sleeptime);
  298.             if (reprieve())
  299.                 continue;
  300.             blast(pid);
  301.         }
  302.     }
  303. }
  304.  
  305. reprieve()
  306. {
  307.     static char mess[] = "\r\nYou have a reprieve.  Continue playing.\r\n";
  308.  
  309.     if (checkfor(cf->cf_nogames) || load() || tod() || freettys() || users())
  310.         return (0);
  311.     (void) write(2, mess, sizeof(mess));
  312.     return (1);
  313. }
  314.  
  315. /*
  316.  * warn - Warn the user how close his game is to ending.
  317.  */
  318. warn(which)
  319. int which;
  320. {
  321.     char buf1[BUFSIZ];
  322.     char buf2[BUFSIZ];
  323.     char *space = "                                                        ";
  324.     extern errno;
  325.  
  326. #ifdef DEBUG
  327.     dprintf("warn(): which = %d\n", which);
  328. #endif DEBUG
  329.  
  330.     if (was_nogames)
  331.         (void) sprintf(buf2, getaline(cf->cf_nogames));
  332.     if (was_load)
  333.         (void) sprintf(buf2, 
  334.             "The system load is greater than %.2lf.",
  335.             cf->cf_load);
  336.     if (was_users)
  337.         (void) sprintf(buf2, 
  338.             "There are more than %d users logged in.",
  339.                 cf->cf_users);
  340.     if (was_freettys)
  341.         (void) sprintf(buf2, "There %s not %d %s tty%s available.",
  342.             (cf->cf_nofreettys > 1) ? "are" : "is", cf->cf_nofreettys,
  343.             cf->cf_spname, (cf->cf_nofreettys > 1) ? "s" : "");
  344.     if (was_tod)
  345.         (void) sprintf(buf2, "Game time is over.");
  346.  
  347.     (void) sprintf(buf1, 
  348.             "\r\n\007\007\007%s\r\n%s\r\nYou have %s%s%s\r\n%s\r\n",
  349.             space, buf2, warntime[which], warnmesg1, warnmesg2, space);
  350.     (void) write(2, buf1, strlen(buf1));
  351. }
  352.  
  353. /*
  354.  * blast - Kill the game.
  355.  */
  356. blast(pid)
  357. int pid;
  358. {
  359.     static char mess[] = "\rYour game is forfeit.\r\n";
  360.  
  361. #ifdef DEBUG
  362.     dprintf("blast(): pid = %d myuid = %d(%d)\n", pid, getuid(), geteuid());
  363. #endif DEBUG
  364.  
  365.     if(!hastried)
  366.         (void) write(2, mess, sizeof(mess));
  367.  
  368.     if (cf->cf_logfile[0]) {
  369.         (void) sprintf(mbuf, "blast(%d) %s", pid, game);
  370.         (void) logfile(mbuf, cf->cf_logfile);
  371.     }
  372.  
  373.     if(kill(pid, SIGHUP) < 0) {
  374.         (void) sprintf(mbuf, "kill(%d, SIGHUP) failed: %d", pid, errno);
  375.         (void) logfile(mbuf, cf->cf_logfile);
  376. #ifdef DEBUG
  377.         dprintf("%s: ", mbuf);
  378.         if(debug)perror();
  379. #endif DEBUG
  380.     }
  381.     sleep(30);
  382.     if(kill(pid, SIGKILL) < 0) {
  383.         (void) sprintf(mbuf, "kill(%d, SIGKILL) failed: %d", pid, errno);
  384.         (void) logfile(mbuf, cf->cf_logfile);
  385. #ifdef DEBUG
  386.         dprintf("%s: ", mbuf);
  387.         if(debug)perror();
  388. #endif DEBUG
  389.     }
  390.     if(!hastried) {
  391. #ifdef DEBUG
  392.         dprintf("_before: getuid = %d\n", getuid());
  393.         dprintf("_before: geteuid = %d\n", geteuid());
  394. #endif DEBUG
  395.         (void) setuid(getuid());
  396. #ifdef DEBUG
  397.         dprintf("_after: getuid = %d\n", getuid());
  398.         dprintf("_after: geteuid = %d\n", geteuid());
  399. #endif DEBUG
  400.         hastried = 1;
  401.         blast(pid);
  402.         return;
  403.     } else
  404.         hastried = 0;
  405. }
  406.  
  407. /*
  408.  * death - More on killing.
  409.  */
  410. death()
  411. {
  412.     union wait status;
  413.  
  414.     if (wait3(&status, WNOHANG | WUNTRACED, (char *)0) == 0) {
  415.         return;
  416.     }
  417.     if (status.w_stopval == WSTOPPED) {
  418.         (void) signal(SIGTSTP, SIG_DFL);
  419.         (void) kill(getpid(), SIGTSTP);
  420.         (void) signal(SIGTSTP, SIG_IGN);
  421.         return;
  422.     } else {
  423. #ifdef DEBUG
  424.         dprintf("\nClosing with exit(0)...\n");
  425. #endif DEBUG
  426.         if(cf->cf_logfile[0]) {
  427.             (void) sprintf(mbuf, "end of %s (%d)", game, getpid());
  428.             (void) logfile(mbuf, cf->cf_logfile);
  429.         }
  430.         (void) close(Fkmem);
  431.         (void) close(Fpmem);
  432.         (void) close(Fswap);
  433.         (void) close(Futmp);
  434.         exit(0);
  435.     }
  436. }
  437.  
  438. /*
  439.  * setup - Setup constants.
  440.  */
  441. setup(game)
  442. char *game;
  443. {
  444.     FILE *list;
  445.     char *getlogin();
  446.     struct passwd *pw, *getpwuid();
  447.  
  448.     Fswap = Fpmem = Fkmem = Futmp = 0;
  449.  
  450.     if ((Futmp = open("/etc/utmp", 0)) < 0) {
  451.         fatal("/etc/utmp", TRUE);
  452.         /*NOTREACHED*/
  453.     }
  454.     if ((Fkmem = open("/dev/kmem", 0)) < 0) {
  455.         fatal("/dev/kmem", TRUE);
  456.         /*NOTREACHED*/
  457.     }
  458.     if ((Fpmem = open("/dev/mem", 0)) < 0) {
  459.         fatal("/dev/mem", TRUE);
  460.         /*NOTREACHED*/
  461.     }
  462.     if ((Fswap = open("/dev/drum", 0)) < 0) {
  463.         fatal("/dev/drum", TRUE);
  464.         /*NOTREACHED*/
  465.     }
  466.  
  467.     nlist("/vmunix", nl);
  468.     if (nl[0].n_type == 0) {
  469.         fatal("/vmunix", TRUE);
  470.         /*NOTREACHED*/
  471.     }
  472.  
  473. #ifdef FINDTTY
  474.     usrptmap = (struct pte *) nl[N_USRPTMAP].n_value;
  475.     usrpt = (struct pte *) nl[N_USRPT].n_value;
  476.  
  477. #ifdef DEBUG
  478.     dprintf("seeking _nproc...\n");
  479. #endif DEBUG
  480.     memseek(Fkmem, (long) nl[N_NPROC].n_value);
  481.     if (read(Fkmem, (char *) &i_nproc, sizeof i_nproc) != sizeof i_nproc) {
  482.         fatal("Could not get value of nproc.", FALSE);
  483.         /*NOTREACHED*/
  484.     }
  485. #ifdef DEBUG
  486.     dprintf("seeking _proc...\n");
  487. #endif DEBUG
  488.     memseek(Fkmem, (long) nl[N_PROC].n_value);
  489.     if (read(Fkmem, (char *) &i_proc, sizeof i_proc) != sizeof i_proc) {
  490.         fatal("Could not get value of proc.", FALSE);
  491.         /*NOTREACHED*/
  492.     }
  493. #endif
  494.     mytty = gettyname();
  495. #ifdef DEBUG
  496.     dprintf("mytty = '%s'\n", mytty);
  497. #endif DEBUG
  498.     
  499.     if ((list = fopen(CONTROL, "r")) == NULL) {
  500.         fatal(CONTROL, TRUE);
  501.         /*NOTREACHED*/
  502.     }
  503.  
  504.     if ((user = getlogin()) == NULL) {
  505.         if ((pw = getpwuid(getuid())) != NULL)
  506.             user = pw->pw_name;
  507.         else
  508.             user = "(unknown)";
  509. #ifdef DEBUG
  510.         dprintf("getlogin() failed. user = '%s'\n", user);
  511. #endif DEBUG
  512.     }
  513. #ifdef DEBUG
  514.         else dprintf("getlogin() succeeded. user = '%s'\n", user);
  515. #endif DEBUG
  516.  
  517.     cf = parse(list, game);
  518.  
  519. #ifdef DEBUG
  520.     dprintf("game = '%s'\tmax load = '%.2f'\tmax users = '%d'\tpriority = %d\n",
  521.             cf->cf_game, cf->cf_load, cf->cf_users, cf->cf_priority);
  522.     dprintf("badttys = '%s'\tfreettys = '%s'\nnofree = %d\tsp_name = '%s'\n", 
  523.         cf->cf_badttys, cf->cf_freettys, cf->cf_nofreettys, cf->cf_spname);
  524.     dprintf("tod morn = %d \t even = %d\n", cf->cf_todmorn, cf->cf_todeven);
  525. #endif DEBUG
  526.         
  527.     (void) fclose(list);
  528.     (void) signal(SIGCHLD, death);
  529.     (void) signal(SIGINT, SIG_IGN);
  530.     (void) signal(SIGQUIT, SIG_IGN);
  531.     (void) signal(SIGTSTP, SIG_IGN);
  532. }
  533.  
  534. /*
  535.  * load - Return the 5 minute load average
  536.  */
  537. load()
  538. {
  539.     (void) lseek(Fkmem, (long)nl[N_AVENRUN].n_value, 0);
  540.     (void) read(Fkmem, avenrun, sizeof(avenrun));
  541.     return (was_load = (avenrun[1] >= cf->cf_load));
  542. }
  543.  
  544. /*
  545.  * users - Count the number of users logged in.
  546.  */
  547. users()
  548. {
  549.     int count = 0;
  550.  
  551.     (void) lseek(Futmp, (long)0, 0);
  552.     while (read(Futmp, &buf, sizeof(buf)) > 0) {
  553.         if (buf.ut_name[0] != '\0') {
  554.             count++;
  555.         }
  556.     }
  557.     return (was_users = (count > cf->cf_users));
  558. }
  559.  
  560. /*
  561.  * tod - Find out if it is okay to play right now.
  562.  */
  563. tod()
  564. {
  565.     long now;
  566.     struct tm *localtime();
  567.     struct tm *ntime;
  568.  
  569.     if (cf->cf_todmorn == 0 && cf->cf_todeven == 0) {
  570. #ifdef DEBUG
  571.         dprintf("tod(): tod not set.\n");
  572. #endif DEBUG
  573.         return(was_tod = FALSE);
  574.     }
  575.  
  576.     time(&now);
  577.     ntime = localtime(&now);
  578.     if(ntime->tm_wday == 0 || ntime->tm_wday == 6)
  579.         return(was_tod = FALSE);/* OK on Sat & Sun */
  580.     if(ntime->tm_hour < cf->cf_todmorn || ntime->tm_hour >= cf->cf_todeven)
  581.         return(was_tod = FALSE);/* OK during non working hours */
  582.     
  583.     return(was_tod = TRUE);
  584. }
  585.  
  586. checkfor(file)
  587. char *file;
  588. {
  589. #ifdef DEBUG
  590.     dprintf("checkfor(%s) called\n", file);
  591. #endif DEBUG
  592.  
  593.     was_nogames = access(file, R_OK) == 0;
  594. #ifdef DEBUG
  595.     dprintf("checkfor(): access = %d\n", was_nogames);
  596. #endif DEBUG
  597.     return(was_nogames);
  598. }
  599.  
  600. /*
  601.  * getaline - Returns the first line from file.
  602.  */
  603. char *
  604. getaline(file)
  605. char *file;
  606. {
  607.     char buf[BUFSIZ];
  608.     FILE *fd, *fopen();
  609.  
  610.     if((fd = fopen(file, "r")) != NULL) {
  611.         fgets(buf, sizeof(buf), fd);
  612.         (void) fclose(fd);
  613.         return(buf);
  614.     }
  615.     return(NULL);
  616. }
  617.  
  618. /*
  619.  * freettys - Find out if there are enough free ttys.
  620.  *        The user invoking a game (under GR) must be on
  621.  *        one of the ttys listed in cf->cf_freettys for this check.
  622.  */
  623. freettys()
  624. {
  625.     int left = 0;
  626.     char *remttys;
  627.  
  628.     remttys = cf->cf_freettys;
  629.     if(strlen(remttys) < 2)
  630.         return;
  631.  
  632. #ifdef DEBUG
  633.     dprintf("freeyttys started. ttys = '%s'\n", remttys);
  634. #endif DEBUG
  635.  
  636.     /*
  637.      * If you're not on a "special" tty, we don't
  638.      * worry about you.
  639.      */
  640.     if(!sgrep(mytty, remttys)) {
  641. #ifdef DEBUG
  642.         dprintf("You're NOT on a special tty.\n");
  643. #endif DEBUG
  644.         return(0);
  645.     }
  646.  
  647. #ifdef DEBUG
  648.     dprintf("You're on a special tty.\n");
  649. #endif DEBUG
  650.  
  651.     (void) lseek(Futmp, (long)0, 0);
  652.     while (read(Futmp, &buf, sizeof(buf)) > 0) {
  653.         if (buf.ut_name[0] != '\0') {
  654.             if(strncmp(buf.ut_line, "tty", 3) == 0)
  655.                 remttys = deltty(buf.ut_line+3, remttys);
  656.         }
  657.     }
  658.  
  659.     left = strlen(remttys) / 2;
  660. #ifdef DEBUG
  661.     dprintf("remaining ttys = '%s' # left = %d\n", remttys, left);
  662. #endif DEBUG
  663.     return(was_freettys = (left < cf->cf_nofreettys));
  664. }
  665.  
  666. /*
  667.  * deltty - delete a tty "name" from the remaining ttys
  668.  */
  669. char *
  670. deltty(name, list)
  671. char *name;
  672. char *list;
  673. {
  674.     char tmp[BUFSIZ];
  675.     register int i;
  676.  
  677.     i = 0;
  678.     while(*list) {
  679.         if (*list == *name) {
  680.             if(*++list == *++name) {
  681.                 *++list;
  682.             } else {
  683.                 *--list;
  684.             }
  685.             *--name;
  686.         } 
  687.         tmp[i++] = *list++;
  688.     }
  689.     tmp[i] = NULL;
  690.     return(tmp);
  691. }
  692.  
  693. /*
  694.  * sgrep(x, str) -- check for x in str.  Return 1 (TRUE) if exists.
  695.  *            Otherwise 0 (FALSE).
  696.  */
  697.  
  698. sgrep(x, str)
  699. char     *x;
  700. char     *str;
  701. {
  702.     if (!str)
  703.         return(FALSE);
  704.     while(*str) {
  705.         if(*str == *x){
  706.             if(*++str == *++x) {
  707.                 return(TRUE);
  708.             } else {
  709.                 *--x;
  710.             }
  711.         }
  712.         *++str;
  713.     }
  714.     return(FALSE);
  715. }
  716.  
  717. /*
  718.  * badttys - Are we allowed to play games on this tty?
  719.  */
  720. badttys()
  721. {
  722.     if(sgrep(mytty, cf->cf_badttys)) {
  723.         badtty = mytty;
  724.         return(was_badttys = TRUE);
  725.     }
  726.     return(was_badttys = FALSE);
  727. }
  728.  
  729. /*
  730.  * gettyname - Determine which tty we're on.
  731.  *             Returns 2 char string.
  732.  */
  733. char *
  734. gettyname()
  735. {
  736.     char *ttyname();
  737. #ifdef FINDTTY
  738.     char *findtty();
  739.     char *t, *t2;
  740.  
  741. #ifdef DEBUG
  742.     dprintf("gettyname(): calling findtty()...\n");
  743. #endif DEBUG
  744.     t = findtty(getpid());
  745.     if (strcmp(t, "co") == 0) {    /* We're probably  using rlogin or telnet */
  746.         t2 = ttyname(2)+8;
  747. #ifdef DEBUG
  748.         dprintf("t2 = '%s'\n", t2);
  749. #endif DEBUG
  750.         if (strcmp(t, t2)) {     /* there's a difference: so believe ttyname() */
  751. #ifdef DEBUG
  752.             dprintf("gettyname: difference.  using t2\n");
  753. #endif DEBUG
  754.             t = t2;
  755.         }
  756.     }
  757.     return(t);
  758. #else
  759. #ifdef DEBUG
  760.     dprintf("gettyname(): using ttyname()...\n");
  761. #endif DEBUG
  762.     return(ttyname(2)+8);
  763. #endif
  764. }
  765.  
  766. fatal(msg, pflag)
  767. char *msg;
  768. int pflag;
  769. {
  770.     fprintf(stderr, "%s: ", prog);
  771.     if (pflag)
  772.         perror(msg);
  773.     else
  774.         fprintf(stderr, "Fatal Error: %s\n", msg);
  775.     exit(1);
  776. }
  777.