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