home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / games / rogue / machdep.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-08  |  19.2 KB  |  682 lines

  1. /*
  2.  * Copyright (c) 1988 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Timothy C. Stoehr.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)machdep.c    5.7 (Berkeley) 2/28/91";
  39. #endif /* not lint */
  40.  
  41. /*
  42.  * machdep.c
  43.  *
  44.  * This source herein may be modified and/or distributed by anybody who
  45.  * so desires, with the following restrictions:
  46.  *    1.)  No portion of this notice shall be removed.
  47.  *    2.)  Credit shall not be taken for the creation of this source.
  48.  *    3.)  This code is not to be traded, sold, or used for personal
  49.  *         gain or profit.
  50.  *
  51.  */
  52.  
  53. /* Included in this file are all system dependent routines.  Extensive use
  54.  * of #ifdef's will be used to compile the appropriate code on each system:
  55.  *
  56.  *    UNIX:        all UNIX systems.
  57.  *    UNIX_BSD4_2: UNIX BSD 4.2 and later, UTEK, (4.1 BSD too?)
  58.  *    UNIX_SYSV:   UNIX system V
  59.  *    UNIX_V7:     UNIX version 7
  60.  *
  61.  * All UNIX code should be included between the single "#ifdef UNIX" at the
  62.  * top of this file, and the "#endif" at the bottom.
  63.  * 
  64.  * To change a routine to include a new UNIX system, simply #ifdef the
  65.  * existing routine, as in the following example:
  66.  *
  67.  *   To make a routine compatible with UNIX system 5, change the first
  68.  *   function to the second:
  69.  *
  70.  *      md_function()
  71.  *      {
  72.  *         code;
  73.  *      }
  74.  *
  75.  *      md_function()
  76.  *      {
  77.  *      #ifdef UNIX_SYSV
  78.  *         sys5code;
  79.  *      #else
  80.  *         code;
  81.  *      #endif
  82.  *      }
  83.  *
  84.  * Appropriate variations of this are of course acceptible.
  85.  * The use of "#elseif" is discouraged because of non-portability.
  86.  * If the correct #define doesn't exist, "UNIX_SYSV" in this case, make it up
  87.  * and insert it in the list at the top of the file.  Alter the CFLAGS
  88.  * in you Makefile appropriately.
  89.  *
  90.  */
  91.  
  92. #ifdef UNIX
  93.  
  94. #include <stdio.h>
  95. #include <sys/types.h>
  96. #include <sys/file.h>
  97. #include <sys/stat.h>
  98. #include <pwd.h>
  99.  
  100. #ifdef UNIX_BSD4_2
  101. #include <sys/time.h>
  102. #include <sgtty.h>
  103. #endif
  104.  
  105. #ifdef UNIX_SYSV
  106. #include <time.h>
  107. #include <termio.h>
  108. #endif
  109.  
  110. #include <signal.h>
  111. #include "rogue.h"
  112. #include "pathnames.h"
  113.  
  114. /* md_slurp:
  115.  *
  116.  * This routine throws away all keyboard input that has not
  117.  * yet been read.  It is used to get rid of input that the user may have
  118.  * typed-ahead.
  119.  *
  120.  * This function is not necessary, so it may be stubbed.  The might cause
  121.  * message-line output to flash by because the game has continued to read
  122.  * input without waiting for the user to read the message.  Not such a
  123.  * big deal.
  124.  */
  125.  
  126. md_slurp()
  127. {
  128.     (void)fpurge(stdin);
  129. }
  130.  
  131. /* md_control_keyboard():
  132.  *
  133.  * This routine is much like md_cbreak_no_echo_nonl() below.  It sets up the
  134.  * keyboard for appropriate input.  Specifically, it prevents the tty driver
  135.  * from stealing characters.  For example, ^Y is needed as a command
  136.  * character, but the tty driver intercepts it for another purpose.  Any
  137.  * such behavior should be stopped.  This routine could be avoided if
  138.  * we used RAW mode instead of CBREAK.  But RAW mode does not allow the
  139.  * generation of keyboard signals, which the program uses.
  140.  *
  141.  * The parameter 'mode' when true, indicates that the keyboard should
  142.  * be set up to play rogue.  When false, it should be restored if
  143.  * necessary.
  144.  *
  145.  * This routine is not strictly necessary and may be stubbed.  This may
  146.  * cause certain command characters to be unavailable.
  147.  */
  148.  
  149. md_control_keybord(mode)
  150. boolean mode;
  151. {
  152.     static boolean called_before = 0;
  153. #ifdef UNIX_BSD4_2
  154.     static struct ltchars ltc_orig;
  155.     static struct tchars tc_orig;
  156.     struct ltchars ltc_temp;
  157.     struct tchars tc_temp;
  158. #endif
  159. #ifdef UNIX_SYSV
  160.     static struct termio _oldtty;
  161.     struct termio _tty;
  162. #endif
  163.  
  164.     if (!called_before) {
  165.         called_before = 1;
  166. #ifdef UNIX_BSD4_2
  167.         ioctl(0, TIOCGETC, &tc_orig);
  168.         ioctl(0, TIOCGLTC, <c_orig);
  169. #endif
  170. #ifdef UNIX_SYSV
  171.         ioctl(0, TCGETA, &_oldtty);
  172. #endif
  173.     }
  174. #ifdef UNIX_BSD4_2
  175.     ltc_temp = ltc_orig;
  176.     tc_temp = tc_orig;
  177. #endif
  178. #ifdef UNIX_SYSV
  179.     _tty = _oldtty;
  180. #endif
  181.  
  182.     if (!mode) {
  183. #ifdef UNIX_BSD4_2
  184.         ltc_temp.t_suspc = ltc_temp.t_dsuspc = -1;
  185.         ltc_temp.t_rprntc = ltc_temp.t_flushc = -1;
  186.         ltc_temp.t_werasc = ltc_temp.t_lnextc = -1;
  187.         tc_temp.t_startc = tc_temp.t_stopc = -1;
  188. #endif
  189. #ifdef UNIX_SYSV
  190.         _tty.c_cc[VSWTCH] = CNSWTCH;
  191. #endif
  192.     }
  193. #ifdef UNIX_BSD4_2
  194.     ioctl(0, TIOCSETC, &tc_temp);
  195.     ioctl(0, TIOCSLTC, <c_temp);
  196. #endif
  197. #ifdef UNIX_SYSV
  198.     ioctl(0, TCSETA, &_tty);
  199. #endif
  200. }
  201.  
  202. /* md_heed_signals():
  203.  *
  204.  * This routine tells the program to call particular routines when
  205.  * certain interrupts/events occur:
  206.  *
  207.  *      SIGINT: call onintr() to interrupt fight with monster or long rest.
  208.  *      SIGQUIT: call byebye() to check for game termination.
  209.  *      SIGHUP: call error_save() to save game when terminal hangs up.
  210.  *
  211.  *        On VMS, SIGINT and SIGQUIT correspond to ^C and ^Y.
  212.  *
  213.  * This routine is not strictly necessary and can be stubbed.  This will
  214.  * mean that the game cannot be interrupted properly with keyboard
  215.  * input, this is not usually critical.
  216.  */
  217.  
  218. md_heed_signals()
  219. {
  220.     signal(SIGINT, onintr);
  221.     signal(SIGQUIT, byebye);
  222.     signal(SIGHUP, error_save);
  223. }
  224.  
  225. /* md_ignore_signals():
  226.  *
  227.  * This routine tells the program to completely ignore the events mentioned
  228.  * in md_heed_signals() above.  The event handlers will later be turned on
  229.  * by a future call to md_heed_signals(), so md_heed_signals() and
  230.  * md_ignore_signals() need to work together.
  231.  *
  232.  * This function should be implemented or the user risks interrupting
  233.  * critical sections of code, which could cause score file, or saved-game
  234.  * file, corruption.
  235.  */
  236.  
  237. md_ignore_signals()
  238. {
  239.     signal(SIGQUIT, SIG_IGN);
  240.     signal(SIGINT, SIG_IGN);
  241.     signal(SIGHUP, SIG_IGN);
  242. }
  243.  
  244. /* md_get_file_id():
  245.  *
  246.  * This function returns an integer that uniquely identifies the specified
  247.  * file.  It need not check for the file's existence.  In UNIX, the inode
  248.  * number is used.
  249.  *
  250.  * This function is used to identify saved-game files.
  251.  */
  252.  
  253. int
  254. md_get_file_id(fname)
  255. char *fname;
  256. {
  257.     struct stat sbuf;
  258.  
  259.     if (stat(fname, &sbuf)) {
  260.         return(-1);
  261.     }
  262.     return((int) sbuf.st_ino);
  263. }
  264.  
  265. /* md_link_count():
  266.  *
  267.  * This routine returns the number of hard links to the specified file.
  268.  *
  269.  * This function is not strictly necessary.  On systems without hard links
  270.  * this routine can be stubbed by just returning 1.
  271.  */
  272.  
  273. int
  274. md_link_count(fname)
  275. char *fname;
  276. {
  277.     struct stat sbuf;
  278.  
  279.     stat(fname, &sbuf);
  280.     return((int) sbuf.st_nlink);
  281. }
  282.  
  283. /* md_gct(): (Get Current Time)
  284.  *
  285.  * This function returns the current year, month(1-12), day(1-31), hour(0-23),
  286.  * minute(0-59), and second(0-59).  This is used for identifying the time
  287.  * at which a game is saved.
  288.  *
  289.  * This function is not strictly necessary.  It can be stubbed by returning
  290.  * zeros instead of the correct year, month, etc.  If your operating
  291.  * system doesn't provide all of the time units requested here, then you
  292.  * can provide only those that it does, and return zeros for the others.
  293.  * If you cannot provide good time values, then users may be able to copy
  294.  * saved-game files and play them.  
  295.  */
  296.  
  297. md_gct(rt_buf)
  298. struct rogue_time *rt_buf;
  299. {
  300.     struct tm *t, *localtime();
  301.     long seconds;
  302.  
  303.     time(&seconds);
  304.     t = localtime(&seconds);
  305.  
  306.     rt_buf->year = t->tm_year;
  307.     rt_buf->month = t->tm_mon + 1;
  308.     rt_buf->day = t->tm_mday;
  309.     rt_buf->hour = t->tm_hour;
  310.     rt_buf->minute = t->tm_min;
  311.     rt_buf->second = t->tm_sec;
  312. }
  313.  
  314. /* md_gfmt: (Get File Modification Time)
  315.  *
  316.  * This routine returns a file's date of last modification in the same format
  317.  * as md_gct() above.
  318.  *
  319.  * This function is not strictly necessary.  It is used to see if saved-game
  320.  * files have been modified since they were saved.  If you have stubbed the
  321.  * routine md_gct() above by returning constant values, then you may do
  322.  * exactly the same here.
  323.  * Or if md_gct() is implemented correctly, but your system does not provide
  324.  * file modification dates, you may return some date far in the past so
  325.  * that the program will never know that a saved-game file being modified.  
  326.  * You may also do this if you wish to be able to restore games from
  327.  * saved-games that have been modified.
  328.  */
  329.  
  330. md_gfmt(fname, rt_buf)
  331. char *fname;
  332. struct rogue_time *rt_buf;
  333. {
  334.     struct stat sbuf;
  335.     long seconds;
  336.     struct tm *t;
  337.  
  338.     stat(fname, &sbuf);
  339.     seconds = (long) sbuf.st_mtime;
  340.     t = localtime(&seconds);
  341.  
  342.     rt_buf->year = t->tm_year;
  343.     rt_buf->month = t->tm_mon + 1;
  344.     rt_buf->day = t->tm_mday;
  345.     rt_buf->hour = t->tm_hour;
  346.     rt_buf->minute = t->tm_min;
  347.     rt_buf->second = t->tm_sec;
  348. }
  349.  
  350. /* md_df: (Delete File)
  351.  *
  352.  * This function deletes the specified file, and returns true (1) if the
  353.  * operation was successful.  This is used to delete saved-game files
  354.  * after restoring games from them.
  355.  *
  356.  * Again, this function is not strictly necessary, and can be stubbed
  357.  * by simply returning 1.  In this case, saved-game files will not be
  358.  * deleted and can be replayed.
  359.  */
  360.  
  361. boolean
  362. md_df(fname)
  363. char *fname;
  364. {
  365.     if (unlink(fname)) {
  366.         return(0);
  367.     }
  368.     return(1);
  369. }
  370.  
  371. /* md_gln: (Get login name)
  372.  *
  373.  * This routine returns the login name of the user.  This string is
  374.  * used mainly for identifying users in score files.
  375.  *
  376.  * A dummy string may be returned if you are unable to implement this
  377.  * function, but then the score file would only have one name in it.
  378.  */
  379.  
  380. char *
  381. md_gln()
  382. {
  383.     struct passwd *p;
  384.  
  385.     if (!(p = getpwuid(getuid())))
  386.         return((char *)NULL);
  387.     return(p->pw_name);
  388. }
  389.  
  390. /* md_sleep:
  391.  *
  392.  * This routine causes the game to pause for the specified number of
  393.  * seconds.
  394.  *
  395.  * This routine is not particularly necessary at all.  It is used for
  396.  * delaying execution, which is useful to this program at some times.
  397.  */
  398.  
  399. md_sleep(nsecs)
  400. int nsecs;
  401. {
  402.     (void) sleep(nsecs);
  403. }
  404.  
  405. /* md_getenv()
  406.  *
  407.  * This routine gets certain values from the user's environment.  These
  408.  * values are strings, and each string is identified by a name.  The names
  409.  * of the values needed, and their use, is as follows:
  410.  *
  411.  *   TERMCAP
  412.  *     The name of the users's termcap file, NOT the termcap entries
  413.  *     themselves.  This is used ONLY if the program is compiled with
  414.  *     CURSES defined (-DCURSES).  Even in this case, the program need
  415.  *     not find a string for TERMCAP.  If it does not, it will use the
  416.  *     default termcap file as returned by md_gdtcf();
  417.  *   TERM
  418.  *     The name of the users's terminal.  This is used ONLY if the program
  419.  *     is compiled with CURSES defined (-DCURSES).  In this case, the string
  420.  *     value for TERM must be found, or the routines in curses.c cannot
  421.  *     function, and the program will quit.
  422.  *   ROGUEOPTS
  423.  *     A string containing the various game options.  This need not be
  424.  *     defined.
  425.  *   HOME
  426.  *     The user's home directory.  This is only used when the user specifies
  427.  *     '~' as the first character of a saved-game file.  This string need
  428.  *     not be defined.
  429.  *   SHELL
  430.  *     The user's favorite shell.  If not found, "/bin/sh" is assumed.
  431.  *
  432.  * If your system does not provide a means of searching for these values,
  433.  * you will have to do it yourself.  None of the values above really need
  434.  * to be defined except TERM when the program is compiled with CURSES
  435.  * defined.  In this case, as a bare minimum, you can check the 'name'
  436.  * parameter, and if it is "TERM" find the terminal name and return that,
  437.  * else return zero.  If the program is not compiled with CURSES, you can
  438.  * get by with simply always returning zero.  Returning zero indicates
  439.  * that their is no defined value for the given string.
  440.  */
  441.  
  442. char *
  443. md_getenv(name)
  444. char *name;
  445. {
  446.     char *value;
  447.     char *getenv();
  448.  
  449.     value = getenv(name);
  450.  
  451.     return(value);
  452. }
  453.  
  454. /* md_malloc()
  455.  *
  456.  * This routine allocates, and returns a pointer to, the specified number
  457.  * of bytes.  This routines absolutely MUST be implemented for your
  458.  * particular system or the program will not run at all.  Return zero
  459.  * when no more memory can be allocated.
  460.  */
  461.  
  462. char *
  463. md_malloc(n)
  464. int n;
  465. {
  466.     char *malloc();
  467.     char *t;
  468.  
  469.     t = malloc(n);
  470.     return(t);
  471. }
  472.  
  473. /* md_gseed() (Get Seed)
  474.  *
  475.  * This function returns a seed for the random number generator (RNG).  This
  476.  * seed causes the RNG to begin generating numbers at some point in it's
  477.  * sequence.  Without a random seed, the RNG will generate the same set
  478.  * of numbers, and every game will start out exactly the same way.  A good
  479.  * number to use is the process id, given by getpid() on most UNIX systems.
  480.  *
  481.  * You need to find some single random integer, such as:
  482.  *   process id.
  483.  *   current time (minutes + seconds) returned from md_gct(), if implemented.
  484.  *   
  485.  * It will not help to return "get_rand()" or "rand()" or the return value of
  486.  * any pseudo-RNG.  If you don't have a random number, you can just return 1,
  487.  * but this means your games will ALWAYS start the same way, and will play
  488.  * exactly the same way given the same input.
  489.  */
  490.  
  491. md_gseed()
  492. {
  493.     return(getpid());
  494. }
  495.  
  496. /* md_exit():
  497.  *
  498.  * This function causes the program to discontinue execution and exit.
  499.  * This function must be implemented or the program will continue to
  500.  * hang when it should quit.
  501.  */
  502.  
  503. md_exit(status)
  504. int status;
  505. {
  506.     exit(status);
  507. }
  508.  
  509. /* md_lock():
  510.  *
  511.  * This function is intended to give the user exclusive access to the score
  512.  * file.  It does so by "creat"ing a lock file, which can only be created
  513.  * if it does not already exist.  The file is deleted when score file
  514.  * processing is finished.  The lock file should be located in the same
  515.  * directory as the score file.  These full path names should be defined for
  516.  * any particular site in rogue.h.  The constants _PATH_SCOREFILE and
  517.  * _PATH_LOCKFILE define these file names.
  518.  *
  519.  * When the parameter 'l' is non-zero (true), a lock is requested.  Otherwise
  520.  * the lock is released by removing the lock file.
  521.  */
  522.  
  523. md_lock(l)
  524. boolean l;
  525. {
  526.     short tries;
  527.     char *lock_file = _PATH_LOCKFILE;
  528.  
  529.     if (l) {
  530.         for (tries = 0; tries < 5; tries++) {
  531.             if (md_get_file_id(lock_file) == -1) {
  532.                 if (creat(lock_file, 0444) != -1) {
  533.                     break;
  534.                 } else {
  535.                     message("cannot lock score file", 0);
  536.                 }
  537.             } else {
  538.                 message("waiting to lock score file", 0);
  539.             }
  540.             sleep(2);
  541.         }
  542.     } else {
  543.         (void) unlink(lock_file);
  544.     }
  545. }
  546.  
  547. /* md_shell():
  548.  *
  549.  * This function spawns a shell for the user to use.  When this shell is
  550.  * terminated, the game continues.  Since this program may often be run
  551.  * setuid to gain access to privileged files, care is taken that the shell
  552.  * is run with the user's REAL user id, and not the effective user id.
  553.  * The effective user id is restored after the shell completes.
  554.  */
  555.  
  556. md_shell(shell)
  557. char *shell;
  558. {
  559.     long w[2];
  560.  
  561.     if (!fork()) {
  562.         int uid;
  563.  
  564.         uid = getuid();
  565.         setuid(uid);
  566.         execl(shell, shell, 0);
  567.     }
  568.     wait(w);
  569. }
  570.  
  571. /* If you have a viable curses/termlib library, then use it and don't bother
  572.  * implementing the routines below.  And don't compile with -DCURSES.
  573.  */
  574.  
  575. #ifdef CURSES
  576.  
  577. /* md_cbreak_no_echo_nonl:
  578.  *
  579.  * This routine sets up some terminal characteristics.  The tty-driver
  580.  * must be told to:
  581.  *   1.)  Not echo input.
  582.  *   2.)  Transmit input characters immediately upon typing. (cbreak mode)
  583.  *   3.)  Move the cursor down one line, without changing column, and
  584.  *        without generating a carriage-return, when it
  585.  *        sees a line-feed.  This is only necessary if line-feed is ever
  586.  *        used in the termcap 'do' (cursor down) entry, in which case,
  587.  *        your system should must have a way of accomplishing this.
  588.  *
  589.  * When the parameter 'on' is true, the terminal is set up as specified
  590.  * above.  When this parameter is false, the terminal is restored to the
  591.  * original state.
  592.  *
  593.  * Raw mode should not to be used.  Keyboard signals/events/interrupts should
  594.  * be sent, although they are not strictly necessary.  See notes in
  595.  * md_heed_signals().
  596.  *
  597.  * This function must be implemented for rogue to run properly if the
  598.  * program is compiled with CURSES defined to use the enclosed curses
  599.  * emulation package.  If you are not using this, then this routine is
  600.  * totally unnecessary.
  601.  * 
  602.  * Notice that information is saved between calls.  This is used to
  603.  * restore the terminal to an initial saved state.
  604.  *
  605.  */
  606.  
  607. md_cbreak_no_echo_nonl(on)
  608. boolean on;
  609. {
  610. #ifdef UNIX_BSD4_2
  611.     static struct sgttyb tty_buf;
  612.     static int tsave_flags;
  613.  
  614.     if (on) {
  615.         ioctl(0, TIOCGETP, &tty_buf);
  616.         tsave_flags = tty_buf.sg_flags;
  617.         tty_buf.sg_flags |= CBREAK;
  618.         tty_buf.sg_flags &= ~(ECHO | CRMOD);    /* CRMOD: see note 3 above */
  619.         ioctl(0, TIOCSETP, &tty_buf);
  620.     } else {
  621.         tty_buf.sg_flags = tsave_flags;
  622.         ioctl(0, TIOCSETP, &tty_buf);
  623.     }
  624. #endif
  625. #ifdef UNIX_SYSV
  626.     struct termio tty_buf;
  627.     static struct termio tty_save;
  628.  
  629.     if (on) {
  630.         ioctl(0, TCGETA, &tty_buf);
  631.         tty_save = tty_buf;
  632.         tty_buf.c_lflag &= ~(ICANON | ECHO);
  633.         tty_buf.c_oflag &= ~ONLCR;
  634.         tty_buf.c_cc[4] = 1;  /* MIN */
  635.         tty_buf.c_cc[5] = 2;  /* TIME */
  636.         ioctl(0, TCSETAF, &tty_buf);
  637.     } else {
  638.         ioctl(0, TCSETAF, &tty_save);
  639.     }
  640. #endif
  641. }
  642.  
  643. /* md_gdtcf(): (Get Default Termcap File)
  644.  *
  645.  * This function is called ONLY when the program is compiled with CURSES
  646.  * defined.  If you use your system's curses/termlib library, this function
  647.  * won't be called.  On most UNIX systems, "/etc/termcap" suffices.
  648.  *
  649.  * If their is no such termcap file, then return 0, but in that case, you
  650.  * must have a TERMCAP file returned from md_getenv("TERMCAP").  The latter
  651.  * will override the value returned from md_gdtcf().  If the program is
  652.  * compiled with CURSES defined, and md_gdtcf() returns 0, and
  653.  * md_getenv("TERMCAP") returns 0, the program will have no terminal
  654.  * capability information and will quit.
  655.  */
  656.  
  657. char *
  658. md_gdtcf()
  659. {
  660.     return("/etc/termcap");
  661. }
  662.  
  663. /* md_tstp():
  664.  *
  665.  * This function puts the game to sleep and returns to the shell.  This
  666.  * only applies to UNIX 4.2 and 4.3.  For other systems, the routine should
  667.  * be provided as a do-nothing routine.  md_tstp() will only be referenced
  668.  * in the code when compiled with CURSES defined.
  669.  *
  670.  */
  671.  
  672. md_tstp()
  673. {
  674. #ifdef UNIX_BSD4_2
  675.     kill(0, SIGTSTP);
  676. #endif
  677. }
  678.  
  679. #endif
  680.  
  681. #endif
  682.