|
|
1.1 ! root 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 are permitted ! 9: * provided that: (1) source distributions retain this entire copyright ! 10: * notice and comment, and (2) distributions including binaries display ! 11: * the following acknowledgement: ``This product includes software ! 12: * developed by the University of California, Berkeley and its contributors'' ! 13: * in the documentation or other materials provided with the distribution ! 14: * and in all advertising materials mentioning features or use of this ! 15: * software. Neither the name of the University nor the names of its ! 16: * contributors may be used to endorse or promote products derived ! 17: * from this software without specific prior written permission. ! 18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 21: */ ! 22: ! 23: #ifndef lint ! 24: static char sccsid[] = "@(#)machdep.c 5.5 (Berkeley) 6/1/90"; ! 25: #endif /* not lint */ ! 26: ! 27: /* ! 28: * machdep.c ! 29: * ! 30: * This source herein may be modified and/or distributed by anybody who ! 31: * so desires, with the following restrictions: ! 32: * 1.) No portion of this notice shall be removed. ! 33: * 2.) Credit shall not be taken for the creation of this source. ! 34: * 3.) This code is not to be traded, sold, or used for personal ! 35: * gain or profit. ! 36: * ! 37: */ ! 38: ! 39: /* Included in this file are all system dependent routines. Extensive use ! 40: * of #ifdef's will be used to compile the appropriate code on each system: ! 41: * ! 42: * UNIX: all UNIX systems. ! 43: * UNIX_BSD4_2: UNIX BSD 4.2 and later, UTEK, (4.1 BSD too?) ! 44: * UNIX_SYSV: UNIX system V ! 45: * UNIX_V7: UNIX version 7 ! 46: * ! 47: * All UNIX code should be included between the single "#ifdef UNIX" at the ! 48: * top of this file, and the "#endif" at the bottom. ! 49: * ! 50: * To change a routine to include a new UNIX system, simply #ifdef the ! 51: * existing routine, as in the following example: ! 52: * ! 53: * To make a routine compatible with UNIX system 5, change the first ! 54: * function to the second: ! 55: * ! 56: * md_function() ! 57: * { ! 58: * code; ! 59: * } ! 60: * ! 61: * md_function() ! 62: * { ! 63: * #ifdef UNIX_SYSV ! 64: * sys5code; ! 65: * #else ! 66: * code; ! 67: * #endif ! 68: * } ! 69: * ! 70: * Appropriate variations of this are of course acceptible. ! 71: * The use of "#elseif" is discouraged because of non-portability. ! 72: * If the correct #define doesn't exist, "UNIX_SYSV" in this case, make it up ! 73: * and insert it in the list at the top of the file. Alter the CFLAGS ! 74: * in you Makefile appropriately. ! 75: * ! 76: */ ! 77: ! 78: #ifdef UNIX ! 79: ! 80: #include <stdio.h> ! 81: #include <sys/types.h> ! 82: #include <sys/file.h> ! 83: #include <sys/stat.h> ! 84: #include <pwd.h> ! 85: ! 86: #ifdef UNIX_BSD4_2 ! 87: #include <sys/time.h> ! 88: #include <sgtty.h> ! 89: #endif ! 90: ! 91: #ifdef UNIX_SYSV ! 92: #include <time.h> ! 93: #include <termio.h> ! 94: #endif ! 95: ! 96: #include <signal.h> ! 97: #include "rogue.h" ! 98: #include "pathnames.h" ! 99: ! 100: /* md_slurp: ! 101: * ! 102: * This routine throws away all keyboard input that has not ! 103: * yet been read. It is used to get rid of input that the user may have ! 104: * typed-ahead. ! 105: * ! 106: * This function is not necessary, so it may be stubbed. The might cause ! 107: * message-line output to flash by because the game has continued to read ! 108: * input without waiting for the user to read the message. Not such a ! 109: * big deal. ! 110: */ ! 111: ! 112: md_slurp() ! 113: { ! 114: long ln = 0; ! 115: ! 116: #ifdef UNIX_BSD4_2 ! 117: ioctl(0, FIONREAD, &ln); ! 118: #endif ! 119: #ifdef UNIX_SYSV ! 120: ioctl(0, TCFLSH, &ln); ! 121: ln = 0; ! 122: #endif ! 123: ! 124: ln += stdin->_cnt; ! 125: ! 126: for (; ln > 0; ln--) { ! 127: (void) getchar(); ! 128: } ! 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, *getpwuid(); ! 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.