xref: /csrg-svn/games/rogue/machdep.c (revision 60842)
132689Sbostic /*
2*60842Sbostic  * Copyright (c) 1988, 1993
3*60842Sbostic  *	The Regents of the University of California.  All rights reserved.
436704Sbostic  *
536704Sbostic  * This code is derived from software contributed to Berkeley by
636704Sbostic  * Timothy C. Stoehr.
736704Sbostic  *
842595Sbostic  * %sccs.include.redist.c%
936704Sbostic  */
1036704Sbostic 
1136704Sbostic #ifndef lint
12*60842Sbostic static char sccsid[] = "@(#)machdep.c	8.1 (Berkeley) 05/31/93";
1336704Sbostic #endif /* not lint */
1436704Sbostic 
1536704Sbostic /*
1632689Sbostic  * machdep.c
1732689Sbostic  *
1832689Sbostic  * This source herein may be modified and/or distributed by anybody who
1932689Sbostic  * so desires, with the following restrictions:
2032689Sbostic  *    1.)  No portion of this notice shall be removed.
2132689Sbostic  *    2.)  Credit shall not be taken for the creation of this source.
2232689Sbostic  *    3.)  This code is not to be traded, sold, or used for personal
2332689Sbostic  *         gain or profit.
2432689Sbostic  *
2532689Sbostic  */
2632689Sbostic 
2732689Sbostic /* Included in this file are all system dependent routines.  Extensive use
2832689Sbostic  * of #ifdef's will be used to compile the appropriate code on each system:
2932689Sbostic  *
3032689Sbostic  *    UNIX:        all UNIX systems.
3132689Sbostic  *    UNIX_BSD4_2: UNIX BSD 4.2 and later, UTEK, (4.1 BSD too?)
3232689Sbostic  *    UNIX_SYSV:   UNIX system V
3332689Sbostic  *    UNIX_V7:     UNIX version 7
3432689Sbostic  *
3532689Sbostic  * All UNIX code should be included between the single "#ifdef UNIX" at the
3632689Sbostic  * top of this file, and the "#endif" at the bottom.
3732689Sbostic  *
3832689Sbostic  * To change a routine to include a new UNIX system, simply #ifdef the
3932689Sbostic  * existing routine, as in the following example:
4032689Sbostic  *
4132689Sbostic  *   To make a routine compatible with UNIX system 5, change the first
4232689Sbostic  *   function to the second:
4332689Sbostic  *
4432689Sbostic  *      md_function()
4532689Sbostic  *      {
4632689Sbostic  *         code;
4732689Sbostic  *      }
4832689Sbostic  *
4932689Sbostic  *      md_function()
5032689Sbostic  *      {
5132689Sbostic  *      #ifdef UNIX_SYSV
5232689Sbostic  *         sys5code;
5332689Sbostic  *      #else
5432689Sbostic  *         code;
5532689Sbostic  *      #endif
5632689Sbostic  *      }
5732689Sbostic  *
5832689Sbostic  * Appropriate variations of this are of course acceptible.
5932689Sbostic  * The use of "#elseif" is discouraged because of non-portability.
6032689Sbostic  * If the correct #define doesn't exist, "UNIX_SYSV" in this case, make it up
6132689Sbostic  * and insert it in the list at the top of the file.  Alter the CFLAGS
6232689Sbostic  * in you Makefile appropriately.
6332689Sbostic  *
6432689Sbostic  */
6532689Sbostic 
6632689Sbostic #ifdef UNIX
6732689Sbostic 
6832689Sbostic #include <stdio.h>
6932689Sbostic #include <sys/types.h>
7032689Sbostic #include <sys/file.h>
7132689Sbostic #include <sys/stat.h>
7232690Sbostic #include <pwd.h>
7332689Sbostic 
7432689Sbostic #ifdef UNIX_BSD4_2
7532689Sbostic #include <sys/time.h>
7632689Sbostic #include <sgtty.h>
7732689Sbostic #endif
7832689Sbostic 
7932689Sbostic #ifdef UNIX_SYSV
8032689Sbostic #include <time.h>
8132689Sbostic #include <termio.h>
8232689Sbostic #endif
8332689Sbostic 
8432689Sbostic #include <signal.h>
8532689Sbostic #include "rogue.h"
8641325Sbostic #include "pathnames.h"
8732689Sbostic 
8832689Sbostic /* md_slurp:
8932689Sbostic  *
9032689Sbostic  * This routine throws away all keyboard input that has not
9132689Sbostic  * yet been read.  It is used to get rid of input that the user may have
9232689Sbostic  * typed-ahead.
9332689Sbostic  *
9432689Sbostic  * This function is not necessary, so it may be stubbed.  The might cause
9532689Sbostic  * message-line output to flash by because the game has continued to read
9632689Sbostic  * input without waiting for the user to read the message.  Not such a
9732689Sbostic  * big deal.
9832689Sbostic  */
9932689Sbostic 
md_slurp()10032689Sbostic md_slurp()
10132689Sbostic {
10246279Sbostic 	(void)fpurge(stdin);
10332689Sbostic }
10432689Sbostic 
10532689Sbostic /* md_control_keyboard():
10632689Sbostic  *
10732689Sbostic  * This routine is much like md_cbreak_no_echo_nonl() below.  It sets up the
10832689Sbostic  * keyboard for appropriate input.  Specifically, it prevents the tty driver
10932689Sbostic  * from stealing characters.  For example, ^Y is needed as a command
11032689Sbostic  * character, but the tty driver intercepts it for another purpose.  Any
11132689Sbostic  * such behavior should be stopped.  This routine could be avoided if
11232689Sbostic  * we used RAW mode instead of CBREAK.  But RAW mode does not allow the
11332689Sbostic  * generation of keyboard signals, which the program uses.
11432689Sbostic  *
11532689Sbostic  * The parameter 'mode' when true, indicates that the keyboard should
11632689Sbostic  * be set up to play rogue.  When false, it should be restored if
11732689Sbostic  * necessary.
11832689Sbostic  *
11932689Sbostic  * This routine is not strictly necessary and may be stubbed.  This may
12032689Sbostic  * cause certain command characters to be unavailable.
12132689Sbostic  */
12232689Sbostic 
md_control_keybord(mode)12332689Sbostic md_control_keybord(mode)
12432689Sbostic boolean mode;
12532689Sbostic {
12632689Sbostic 	static boolean called_before = 0;
12732689Sbostic #ifdef UNIX_BSD4_2
12832689Sbostic 	static struct ltchars ltc_orig;
12932689Sbostic 	static struct tchars tc_orig;
13032689Sbostic 	struct ltchars ltc_temp;
13132689Sbostic 	struct tchars tc_temp;
13232689Sbostic #endif
13332689Sbostic #ifdef UNIX_SYSV
13432689Sbostic 	static struct termio _oldtty;
13532689Sbostic 	struct termio _tty;
13632689Sbostic #endif
13732689Sbostic 
13832689Sbostic 	if (!called_before) {
13932689Sbostic 		called_before = 1;
14032689Sbostic #ifdef UNIX_BSD4_2
14132689Sbostic 		ioctl(0, TIOCGETC, &tc_orig);
14232689Sbostic 		ioctl(0, TIOCGLTC, &ltc_orig);
14332689Sbostic #endif
14432689Sbostic #ifdef UNIX_SYSV
14532689Sbostic 		ioctl(0, TCGETA, &_oldtty);
14632689Sbostic #endif
14732689Sbostic 	}
14832689Sbostic #ifdef UNIX_BSD4_2
14932689Sbostic 	ltc_temp = ltc_orig;
15032689Sbostic 	tc_temp = tc_orig;
15132689Sbostic #endif
15232689Sbostic #ifdef UNIX_SYSV
15332689Sbostic 	_tty = _oldtty;
15432689Sbostic #endif
15532689Sbostic 
15632689Sbostic 	if (!mode) {
15732689Sbostic #ifdef UNIX_BSD4_2
15832689Sbostic 		ltc_temp.t_suspc = ltc_temp.t_dsuspc = -1;
15932689Sbostic 		ltc_temp.t_rprntc = ltc_temp.t_flushc = -1;
16032689Sbostic 		ltc_temp.t_werasc = ltc_temp.t_lnextc = -1;
16132689Sbostic 		tc_temp.t_startc = tc_temp.t_stopc = -1;
16232689Sbostic #endif
16332689Sbostic #ifdef UNIX_SYSV
16432689Sbostic 		_tty.c_cc[VSWTCH] = CNSWTCH;
16532689Sbostic #endif
16632689Sbostic 	}
16732689Sbostic #ifdef UNIX_BSD4_2
16832689Sbostic 	ioctl(0, TIOCSETC, &tc_temp);
16932689Sbostic 	ioctl(0, TIOCSLTC, &ltc_temp);
17032689Sbostic #endif
17132689Sbostic #ifdef UNIX_SYSV
17232689Sbostic 	ioctl(0, TCSETA, &_tty);
17332689Sbostic #endif
17432689Sbostic }
17532689Sbostic 
17632689Sbostic /* md_heed_signals():
17732689Sbostic  *
17832689Sbostic  * This routine tells the program to call particular routines when
17932689Sbostic  * certain interrupts/events occur:
18032689Sbostic  *
18132689Sbostic  *      SIGINT: call onintr() to interrupt fight with monster or long rest.
18232689Sbostic  *      SIGQUIT: call byebye() to check for game termination.
18332689Sbostic  *      SIGHUP: call error_save() to save game when terminal hangs up.
18432689Sbostic  *
18532689Sbostic  *		On VMS, SIGINT and SIGQUIT correspond to ^C and ^Y.
18632689Sbostic  *
18732689Sbostic  * This routine is not strictly necessary and can be stubbed.  This will
18832689Sbostic  * mean that the game cannot be interrupted properly with keyboard
18932689Sbostic  * input, this is not usually critical.
19032689Sbostic  */
19132689Sbostic 
md_heed_signals()19232689Sbostic md_heed_signals()
19332689Sbostic {
19432689Sbostic 	signal(SIGINT, onintr);
19532689Sbostic 	signal(SIGQUIT, byebye);
19632689Sbostic 	signal(SIGHUP, error_save);
19732689Sbostic }
19832689Sbostic 
19932689Sbostic /* md_ignore_signals():
20032689Sbostic  *
20132689Sbostic  * This routine tells the program to completely ignore the events mentioned
20232689Sbostic  * in md_heed_signals() above.  The event handlers will later be turned on
20332689Sbostic  * by a future call to md_heed_signals(), so md_heed_signals() and
20432689Sbostic  * md_ignore_signals() need to work together.
20532689Sbostic  *
20632689Sbostic  * This function should be implemented or the user risks interrupting
20732689Sbostic  * critical sections of code, which could cause score file, or saved-game
20832689Sbostic  * file, corruption.
20932689Sbostic  */
21032689Sbostic 
md_ignore_signals()21132689Sbostic md_ignore_signals()
21232689Sbostic {
21332689Sbostic 	signal(SIGQUIT, SIG_IGN);
21432689Sbostic 	signal(SIGINT, SIG_IGN);
21532689Sbostic 	signal(SIGHUP, SIG_IGN);
21632689Sbostic }
21732689Sbostic 
21832689Sbostic /* md_get_file_id():
21932689Sbostic  *
22032689Sbostic  * This function returns an integer that uniquely identifies the specified
22132689Sbostic  * file.  It need not check for the file's existence.  In UNIX, the inode
22232689Sbostic  * number is used.
22332689Sbostic  *
22432689Sbostic  * This function is used to identify saved-game files.
22532689Sbostic  */
22632689Sbostic 
22732689Sbostic int
md_get_file_id(fname)22832689Sbostic md_get_file_id(fname)
22932689Sbostic char *fname;
23032689Sbostic {
23132689Sbostic 	struct stat sbuf;
23232689Sbostic 
23332689Sbostic 	if (stat(fname, &sbuf)) {
23432689Sbostic 		return(-1);
23532689Sbostic 	}
23632689Sbostic 	return((int) sbuf.st_ino);
23732689Sbostic }
23832689Sbostic 
23932689Sbostic /* md_link_count():
24032689Sbostic  *
24132689Sbostic  * This routine returns the number of hard links to the specified file.
24232689Sbostic  *
24332689Sbostic  * This function is not strictly necessary.  On systems without hard links
24432689Sbostic  * this routine can be stubbed by just returning 1.
24532689Sbostic  */
24632689Sbostic 
24732689Sbostic int
md_link_count(fname)24832689Sbostic md_link_count(fname)
24932689Sbostic char *fname;
25032689Sbostic {
25132689Sbostic 	struct stat sbuf;
25232689Sbostic 
25332689Sbostic 	stat(fname, &sbuf);
25432689Sbostic 	return((int) sbuf.st_nlink);
25532689Sbostic }
25632689Sbostic 
25732689Sbostic /* md_gct(): (Get Current Time)
25832689Sbostic  *
25932689Sbostic  * This function returns the current year, month(1-12), day(1-31), hour(0-23),
26032689Sbostic  * minute(0-59), and second(0-59).  This is used for identifying the time
26132689Sbostic  * at which a game is saved.
26232689Sbostic  *
26332689Sbostic  * This function is not strictly necessary.  It can be stubbed by returning
26432689Sbostic  * zeros instead of the correct year, month, etc.  If your operating
26532689Sbostic  * system doesn't provide all of the time units requested here, then you
26632689Sbostic  * can provide only those that it does, and return zeros for the others.
26732689Sbostic  * If you cannot provide good time values, then users may be able to copy
26832689Sbostic  * saved-game files and play them.
26932689Sbostic  */
27032689Sbostic 
27132689Sbostic md_gct(rt_buf)
27232689Sbostic struct rogue_time *rt_buf;
27332689Sbostic {
27432689Sbostic 	struct tm *t, *localtime();
27532689Sbostic 	long seconds;
27632689Sbostic 
27732689Sbostic 	time(&seconds);
27832689Sbostic 	t = localtime(&seconds);
27932689Sbostic 
28032689Sbostic 	rt_buf->year = t->tm_year;
28132689Sbostic 	rt_buf->month = t->tm_mon + 1;
28232689Sbostic 	rt_buf->day = t->tm_mday;
28332689Sbostic 	rt_buf->hour = t->tm_hour;
28432689Sbostic 	rt_buf->minute = t->tm_min;
28532689Sbostic 	rt_buf->second = t->tm_sec;
28632689Sbostic }
28732689Sbostic 
28832689Sbostic /* md_gfmt: (Get File Modification Time)
28932689Sbostic  *
29032689Sbostic  * This routine returns a file's date of last modification in the same format
29132689Sbostic  * as md_gct() above.
29232689Sbostic  *
29332689Sbostic  * This function is not strictly necessary.  It is used to see if saved-game
29432689Sbostic  * files have been modified since they were saved.  If you have stubbed the
29532689Sbostic  * routine md_gct() above by returning constant values, then you may do
29632689Sbostic  * exactly the same here.
29732689Sbostic  * Or if md_gct() is implemented correctly, but your system does not provide
29832689Sbostic  * file modification dates, you may return some date far in the past so
29932689Sbostic  * that the program will never know that a saved-game file being modified.
30032689Sbostic  * You may also do this if you wish to be able to restore games from
30132689Sbostic  * saved-games that have been modified.
30232689Sbostic  */
30332689Sbostic 
md_gfmt(fname,rt_buf)30432689Sbostic md_gfmt(fname, rt_buf)
30532689Sbostic char *fname;
30632689Sbostic struct rogue_time *rt_buf;
30732689Sbostic {
30832689Sbostic 	struct stat sbuf;
30932689Sbostic 	long seconds;
31032689Sbostic 	struct tm *t;
31132689Sbostic 
31232689Sbostic 	stat(fname, &sbuf);
31332689Sbostic 	seconds = (long) sbuf.st_mtime;
31432689Sbostic 	t = localtime(&seconds);
31532689Sbostic 
31632689Sbostic 	rt_buf->year = t->tm_year;
31732689Sbostic 	rt_buf->month = t->tm_mon + 1;
31832689Sbostic 	rt_buf->day = t->tm_mday;
31932689Sbostic 	rt_buf->hour = t->tm_hour;
32032689Sbostic 	rt_buf->minute = t->tm_min;
32132689Sbostic 	rt_buf->second = t->tm_sec;
32232689Sbostic }
32332689Sbostic 
32432689Sbostic /* md_df: (Delete File)
32532689Sbostic  *
32632689Sbostic  * This function deletes the specified file, and returns true (1) if the
32732689Sbostic  * operation was successful.  This is used to delete saved-game files
32832689Sbostic  * after restoring games from them.
32932689Sbostic  *
33032689Sbostic  * Again, this function is not strictly necessary, and can be stubbed
33132689Sbostic  * by simply returning 1.  In this case, saved-game files will not be
33232689Sbostic  * deleted and can be replayed.
33332689Sbostic  */
33432689Sbostic 
33532689Sbostic boolean
md_df(fname)33632689Sbostic md_df(fname)
33732689Sbostic char *fname;
33832689Sbostic {
33932689Sbostic 	if (unlink(fname)) {
34032689Sbostic 		return(0);
34132689Sbostic 	}
34232689Sbostic 	return(1);
34332689Sbostic }
34432689Sbostic 
34532689Sbostic /* md_gln: (Get login name)
34632689Sbostic  *
34732689Sbostic  * This routine returns the login name of the user.  This string is
34832689Sbostic  * used mainly for identifying users in score files.
34932689Sbostic  *
35032689Sbostic  * A dummy string may be returned if you are unable to implement this
35132689Sbostic  * function, but then the score file would only have one name in it.
35232689Sbostic  */
35332689Sbostic 
35432689Sbostic char *
md_gln()35532689Sbostic md_gln()
35632689Sbostic {
35746758Sbostic 	struct passwd *p;
35832689Sbostic 
35932690Sbostic 	if (!(p = getpwuid(getuid())))
36032690Sbostic 		return((char *)NULL);
36132690Sbostic 	return(p->pw_name);
36232689Sbostic }
36332689Sbostic 
36432689Sbostic /* md_sleep:
36532689Sbostic  *
36632689Sbostic  * This routine causes the game to pause for the specified number of
36732689Sbostic  * seconds.
36832689Sbostic  *
36932689Sbostic  * This routine is not particularly necessary at all.  It is used for
37032689Sbostic  * delaying execution, which is useful to this program at some times.
37132689Sbostic  */
37232689Sbostic 
md_sleep(nsecs)37332689Sbostic md_sleep(nsecs)
37432689Sbostic int nsecs;
37532689Sbostic {
37632689Sbostic 	(void) sleep(nsecs);
37732689Sbostic }
37832689Sbostic 
37932689Sbostic /* md_getenv()
38032689Sbostic  *
38132689Sbostic  * This routine gets certain values from the user's environment.  These
38232689Sbostic  * values are strings, and each string is identified by a name.  The names
38332689Sbostic  * of the values needed, and their use, is as follows:
38432689Sbostic  *
38532689Sbostic  *   TERMCAP
38632689Sbostic  *     The name of the users's termcap file, NOT the termcap entries
38732689Sbostic  *     themselves.  This is used ONLY if the program is compiled with
38832689Sbostic  *     CURSES defined (-DCURSES).  Even in this case, the program need
38932689Sbostic  *     not find a string for TERMCAP.  If it does not, it will use the
39032689Sbostic  *     default termcap file as returned by md_gdtcf();
39132689Sbostic  *   TERM
39232689Sbostic  *     The name of the users's terminal.  This is used ONLY if the program
39332689Sbostic  *     is compiled with CURSES defined (-DCURSES).  In this case, the string
39432689Sbostic  *     value for TERM must be found, or the routines in curses.c cannot
39532689Sbostic  *     function, and the program will quit.
39632689Sbostic  *   ROGUEOPTS
39732689Sbostic  *     A string containing the various game options.  This need not be
39832689Sbostic  *     defined.
39932689Sbostic  *   HOME
40032689Sbostic  *     The user's home directory.  This is only used when the user specifies
40132689Sbostic  *     '~' as the first character of a saved-game file.  This string need
40232689Sbostic  *     not be defined.
40332689Sbostic  *   SHELL
40432689Sbostic  *     The user's favorite shell.  If not found, "/bin/sh" is assumed.
40532689Sbostic  *
40632689Sbostic  * If your system does not provide a means of searching for these values,
40732689Sbostic  * you will have to do it yourself.  None of the values above really need
40832689Sbostic  * to be defined except TERM when the program is compiled with CURSES
40932689Sbostic  * defined.  In this case, as a bare minimum, you can check the 'name'
41032689Sbostic  * parameter, and if it is "TERM" find the terminal name and return that,
41132689Sbostic  * else return zero.  If the program is not compiled with CURSES, you can
41232689Sbostic  * get by with simply always returning zero.  Returning zero indicates
41332689Sbostic  * that their is no defined value for the given string.
41432689Sbostic  */
41532689Sbostic 
41632689Sbostic char *
md_getenv(name)41732689Sbostic md_getenv(name)
41832689Sbostic char *name;
41932689Sbostic {
42032689Sbostic 	char *value;
42132689Sbostic 	char *getenv();
42232689Sbostic 
42332689Sbostic 	value = getenv(name);
42432689Sbostic 
42532689Sbostic 	return(value);
42632689Sbostic }
42732689Sbostic 
42832689Sbostic /* md_malloc()
42932689Sbostic  *
43032689Sbostic  * This routine allocates, and returns a pointer to, the specified number
43132689Sbostic  * of bytes.  This routines absolutely MUST be implemented for your
43232689Sbostic  * particular system or the program will not run at all.  Return zero
43332689Sbostic  * when no more memory can be allocated.
43432689Sbostic  */
43532689Sbostic 
43632689Sbostic char *
md_malloc(n)43732689Sbostic md_malloc(n)
43832689Sbostic int n;
43932689Sbostic {
44032689Sbostic 	char *malloc();
44132689Sbostic 	char *t;
44232689Sbostic 
44332689Sbostic 	t = malloc(n);
44432689Sbostic 	return(t);
44532689Sbostic }
44632689Sbostic 
44732689Sbostic /* md_gseed() (Get Seed)
44832689Sbostic  *
44932689Sbostic  * This function returns a seed for the random number generator (RNG).  This
45032689Sbostic  * seed causes the RNG to begin generating numbers at some point in it's
45132689Sbostic  * sequence.  Without a random seed, the RNG will generate the same set
45232689Sbostic  * of numbers, and every game will start out exactly the same way.  A good
45332689Sbostic  * number to use is the process id, given by getpid() on most UNIX systems.
45432689Sbostic  *
45532689Sbostic  * You need to find some single random integer, such as:
45632689Sbostic  *   process id.
45732689Sbostic  *   current time (minutes + seconds) returned from md_gct(), if implemented.
45832689Sbostic  *
45932689Sbostic  * It will not help to return "get_rand()" or "rand()" or the return value of
46032689Sbostic  * any pseudo-RNG.  If you don't have a random number, you can just return 1,
46132689Sbostic  * but this means your games will ALWAYS start the same way, and will play
46232689Sbostic  * exactly the same way given the same input.
46332689Sbostic  */
46432689Sbostic 
md_gseed()46532689Sbostic md_gseed()
46632689Sbostic {
46732689Sbostic 	return(getpid());
46832689Sbostic }
46932689Sbostic 
47032689Sbostic /* md_exit():
47132689Sbostic  *
47232689Sbostic  * This function causes the program to discontinue execution and exit.
47332689Sbostic  * This function must be implemented or the program will continue to
47432689Sbostic  * hang when it should quit.
47532689Sbostic  */
47632689Sbostic 
md_exit(status)47732689Sbostic md_exit(status)
47832689Sbostic int status;
47932689Sbostic {
48032689Sbostic 	exit(status);
48132689Sbostic }
48232689Sbostic 
48332689Sbostic /* md_lock():
48432689Sbostic  *
48541325Sbostic  * This function is intended to give the user exclusive access to the score
48655779Sbostic  * file.  It does so by flock'ing the score file.  The full path name of the
48755779Sbostic  * score file should be defined for any particular site in rogue.h.  The
48855779Sbostic  * constants _PATH_SCOREFILE defines this file name.
48932689Sbostic  *
49032689Sbostic  * When the parameter 'l' is non-zero (true), a lock is requested.  Otherwise
49155779Sbostic  * the lock is released.
49232689Sbostic  */
49332689Sbostic 
md_lock(l)49432689Sbostic md_lock(l)
49532689Sbostic boolean l;
49632689Sbostic {
49755779Sbostic 	static int fd;
49832689Sbostic 	short tries;
49932689Sbostic 
50032689Sbostic 	if (l) {
50155779Sbostic 		if ((fd = open(_PATH_SCOREFILE, O_RDONLY)) < 1) {
50255779Sbostic 			message("cannot lock score file", 0);
50355779Sbostic 			return;
50432689Sbostic 		}
50555779Sbostic 		for (tries = 0; tries < 5; tries++)
50655779Sbostic 			if (!flock(fd, LOCK_EX|LOCK_NB))
50755779Sbostic 				return;
50832689Sbostic 	} else {
50955779Sbostic 		(void)flock(fd, LOCK_NB);
51055779Sbostic 		(void)close(fd);
51132689Sbostic 	}
51232689Sbostic }
51332689Sbostic 
51432689Sbostic /* md_shell():
51532689Sbostic  *
51632689Sbostic  * This function spawns a shell for the user to use.  When this shell is
51732689Sbostic  * terminated, the game continues.  Since this program may often be run
51832689Sbostic  * setuid to gain access to privileged files, care is taken that the shell
51932689Sbostic  * is run with the user's REAL user id, and not the effective user id.
52032689Sbostic  * The effective user id is restored after the shell completes.
52132689Sbostic  */
52232689Sbostic 
md_shell(shell)52332689Sbostic md_shell(shell)
52432689Sbostic char *shell;
52532689Sbostic {
52632689Sbostic 	long w[2];
52732689Sbostic 
52832689Sbostic 	if (!fork()) {
52932689Sbostic 		int uid;
53032689Sbostic 
53132689Sbostic 		uid = getuid();
53232689Sbostic 		setuid(uid);
53332689Sbostic 		execl(shell, shell, 0);
53432689Sbostic 	}
53532689Sbostic 	wait(w);
53632689Sbostic }
53732689Sbostic 
53832689Sbostic /* If you have a viable curses/termlib library, then use it and don't bother
53932689Sbostic  * implementing the routines below.  And don't compile with -DCURSES.
54032689Sbostic  */
54132689Sbostic 
54232689Sbostic #ifdef CURSES
54332689Sbostic 
54432689Sbostic /* md_cbreak_no_echo_nonl:
54532689Sbostic  *
54632689Sbostic  * This routine sets up some terminal characteristics.  The tty-driver
54732689Sbostic  * must be told to:
54832689Sbostic  *   1.)  Not echo input.
54932689Sbostic  *   2.)  Transmit input characters immediately upon typing. (cbreak mode)
55032689Sbostic  *   3.)  Move the cursor down one line, without changing column, and
55132689Sbostic  *        without generating a carriage-return, when it
55232689Sbostic  *        sees a line-feed.  This is only necessary if line-feed is ever
55332689Sbostic  *        used in the termcap 'do' (cursor down) entry, in which case,
55432689Sbostic  *        your system should must have a way of accomplishing this.
55532689Sbostic  *
55632689Sbostic  * When the parameter 'on' is true, the terminal is set up as specified
55732689Sbostic  * above.  When this parameter is false, the terminal is restored to the
55832689Sbostic  * original state.
55932689Sbostic  *
56032689Sbostic  * Raw mode should not to be used.  Keyboard signals/events/interrupts should
56132689Sbostic  * be sent, although they are not strictly necessary.  See notes in
56232689Sbostic  * md_heed_signals().
56332689Sbostic  *
56432689Sbostic  * This function must be implemented for rogue to run properly if the
56532689Sbostic  * program is compiled with CURSES defined to use the enclosed curses
56632689Sbostic  * emulation package.  If you are not using this, then this routine is
56732689Sbostic  * totally unnecessary.
56832689Sbostic  *
56932689Sbostic  * Notice that information is saved between calls.  This is used to
57032689Sbostic  * restore the terminal to an initial saved state.
57132689Sbostic  *
57232689Sbostic  */
57332689Sbostic 
md_cbreak_no_echo_nonl(on)57432689Sbostic md_cbreak_no_echo_nonl(on)
57532689Sbostic boolean on;
57632689Sbostic {
57732689Sbostic #ifdef UNIX_BSD4_2
57832689Sbostic 	static struct sgttyb tty_buf;
57932689Sbostic 	static int tsave_flags;
58032689Sbostic 
58132689Sbostic 	if (on) {
58232689Sbostic 		ioctl(0, TIOCGETP, &tty_buf);
58332689Sbostic 		tsave_flags = tty_buf.sg_flags;
58432689Sbostic 		tty_buf.sg_flags |= CBREAK;
58532689Sbostic 		tty_buf.sg_flags &= ~(ECHO | CRMOD);	/* CRMOD: see note 3 above */
58632689Sbostic 		ioctl(0, TIOCSETP, &tty_buf);
58732689Sbostic 	} else {
58832689Sbostic 		tty_buf.sg_flags = tsave_flags;
58932689Sbostic 		ioctl(0, TIOCSETP, &tty_buf);
59032689Sbostic 	}
59132689Sbostic #endif
59232689Sbostic #ifdef UNIX_SYSV
59332689Sbostic 	struct termio tty_buf;
59432689Sbostic 	static struct termio tty_save;
59532689Sbostic 
59632689Sbostic 	if (on) {
59732689Sbostic 		ioctl(0, TCGETA, &tty_buf);
59832689Sbostic 		tty_save = tty_buf;
59932689Sbostic 		tty_buf.c_lflag &= ~(ICANON | ECHO);
60032689Sbostic 		tty_buf.c_oflag &= ~ONLCR;
60132689Sbostic 		tty_buf.c_cc[4] = 1;  /* MIN */
60232689Sbostic 		tty_buf.c_cc[5] = 2;  /* TIME */
60332689Sbostic 		ioctl(0, TCSETAF, &tty_buf);
60432689Sbostic 	} else {
60532689Sbostic 		ioctl(0, TCSETAF, &tty_save);
60632689Sbostic 	}
60732689Sbostic #endif
60832689Sbostic }
60932689Sbostic 
61032689Sbostic /* md_gdtcf(): (Get Default Termcap File)
61132689Sbostic  *
61232689Sbostic  * This function is called ONLY when the program is compiled with CURSES
61332689Sbostic  * defined.  If you use your system's curses/termlib library, this function
61432689Sbostic  * won't be called.  On most UNIX systems, "/etc/termcap" suffices.
61532689Sbostic  *
61632689Sbostic  * If their is no such termcap file, then return 0, but in that case, you
61732689Sbostic  * must have a TERMCAP file returned from md_getenv("TERMCAP").  The latter
61832689Sbostic  * will override the value returned from md_gdtcf().  If the program is
61932689Sbostic  * compiled with CURSES defined, and md_gdtcf() returns 0, and
62032689Sbostic  * md_getenv("TERMCAP") returns 0, the program will have no terminal
62132689Sbostic  * capability information and will quit.
62232689Sbostic  */
62332689Sbostic 
62432689Sbostic char *
md_gdtcf()62532689Sbostic md_gdtcf()
62632689Sbostic {
62732689Sbostic 	return("/etc/termcap");
62832689Sbostic }
62932689Sbostic 
63032689Sbostic /* md_tstp():
63132689Sbostic  *
63232689Sbostic  * This function puts the game to sleep and returns to the shell.  This
63332689Sbostic  * only applies to UNIX 4.2 and 4.3.  For other systems, the routine should
63432689Sbostic  * be provided as a do-nothing routine.  md_tstp() will only be referenced
63532689Sbostic  * in the code when compiled with CURSES defined.
63632689Sbostic  *
63732689Sbostic  */
63832689Sbostic 
md_tstp()63932689Sbostic md_tstp()
64032689Sbostic {
64132689Sbostic #ifdef UNIX_BSD4_2
64232689Sbostic 	kill(0, SIGTSTP);
64332689Sbostic #endif
64432689Sbostic }
64532689Sbostic 
64632689Sbostic #endif
64732689Sbostic 
64832689Sbostic #endif
649