home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / nethack-3.1 / sys / unix / unixunix.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-05  |  7.3 KB  |  324 lines

  1. /*    SCCS Id: @(#)unixunix.c    3.1    90/22/02
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* This file collects some Unix dependencies */
  6.  
  7. #include "hack.h"    /* mainly for index() which depends on BSD */
  8.  
  9. #include <errno.h>
  10. #include <sys/stat.h>
  11. #ifdef NO_FILE_LINKS
  12. #include <fcntl.h>
  13. #endif
  14. #include <signal.h>
  15. #if defined(BSD) || defined(ULTRIX)
  16. #include <sys/wait.h>
  17. #endif
  18.  
  19. static struct stat buf, hbuf;
  20.  
  21. void
  22. gethdate(name) const char *name; {
  23. /* old version - for people short of space */
  24. /*
  25. /* register char *np;
  26. /*    if(stat(name, &hbuf))
  27. /*        error("Cannot get status of %s.",
  28. /*            (np = rindex(name, '/')) ? np+1 : name);
  29. /*
  30. /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
  31.  
  32.  
  33. /*
  34.  * The problem with   #include    <sys/param.h>   is that this include file
  35.  * does not exist on all systems, and moreover, that it sometimes includes
  36.  * <sys/types.h> again, so that the compiler sees these typedefs twice.
  37.  */
  38. #define        MAXPATHLEN    1024
  39.  
  40. register const char *np, *path;
  41. char filename[MAXPATHLEN+1];
  42.     if (index(name, '/') != NULL || (path = getenv("PATH")) == NULL)
  43.         path = "";
  44.  
  45.     for (;;) {
  46.         if ((np = index(path, ':')) == NULL)
  47.             np = path + strlen(path);    /* point to end str */
  48.         if (np - path <= 1)            /* %% */
  49.             Strcpy(filename, name);
  50.         else {
  51.             (void) strncpy(filename, path, np - path);
  52.             filename[np - path] = '/';
  53.             Strcpy(filename + (np - path) + 1, name);
  54.         }
  55.         if (stat(filename, &hbuf) == 0)
  56.             return;
  57.         if (*np == '\0')
  58.             break;
  59.         path = np + 1;
  60.     }
  61. #if defined(BOS) && defined(NHSTDC)
  62. /*
  63.  *    This one is really **STUPID**.  I don't know why it's happening
  64.  *    as similar constructs work elsewhere, but...
  65.  */
  66.     if((np = rindex(name, '/')))
  67.          error("Cannot get status of %s.", np+1);
  68.     else error("Cannot get status of %s.", name);
  69. #else
  70.     error("Cannot get status of %s.",
  71.         (np = rindex(name, '/')) ? np+1 : name);
  72. #endif
  73. }
  74.  
  75. int
  76. uptodate(fd)
  77. int fd;
  78. {
  79.     if(fstat(fd, &buf)) {
  80.         pline("Cannot get status of saved level? ");
  81.         wait_synch();
  82.         return(0);
  83.     }
  84.     if(buf.st_mtime < hbuf.st_mtime) {
  85.         pline("Saved level is out of date. ");
  86.         wait_synch();
  87.         return(0);
  88.     }
  89.     return(1);
  90. }
  91.  
  92. /* see whether we should throw away this xlock file */
  93. static int
  94. veryold(fd)
  95. int fd;
  96. {
  97.     time_t date;
  98.  
  99.     if(fstat(fd, &buf)) return(0);            /* cannot get status */
  100. #ifndef INSURANCE
  101.     if(buf.st_size != sizeof(int)) return(0);    /* not an xlock file */
  102. #endif
  103. #ifdef BSD
  104.     (void) time((long *)(&date));
  105. #else
  106.     (void) time(&date);
  107. #endif
  108.     if(date - buf.st_mtime < 3L*24L*60L*60L) {    /* recent */
  109. #ifndef NETWORK
  110.         extern int errno;
  111. #endif
  112.         int lockedpid;    /* should be the same size as hackpid */
  113.  
  114.         if(read(fd, (genericptr_t)&lockedpid, sizeof(lockedpid)) !=
  115.             sizeof(lockedpid))
  116.             /* strange ... */
  117.             return(0);
  118.  
  119.         /* From: Rick Adams <seismo!rick>
  120.         /* This will work on 4.1cbsd, 4.2bsd and system 3? & 5.
  121.         /* It will do nothing on V7 or 4.1bsd. */
  122. #ifndef NETWORK
  123.         /* It will do a VERY BAD THING if the playground is shared
  124.            by more than one machine! -pem */
  125.           if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
  126. #endif
  127.             return(0);
  128.     }
  129.     (void) close(fd);
  130.     return(1);
  131. }
  132.  
  133. static int
  134. eraseoldlocks()
  135. {
  136.     register int i;
  137.  
  138.     /* cannot use maxledgerno() here, because we need to find a lock name
  139.      * before starting everything (including the dungeon initialization
  140.      * that sets astral_level, needed for maxledgerno()) up
  141.      */
  142.     for(i = 1; i <= MAXDUNGEON*MAXLEVEL + 1; i++) {
  143.         /* try to remove all */
  144.         set_levelfile_name(lock, i);
  145.         (void) unlink(lock);
  146.     }
  147.     set_levelfile_name(lock, 0);
  148.     if(unlink(lock)) return(0);            /* cannot remove it */
  149.     return(1);                    /* success! */
  150. }
  151.  
  152. void
  153. getlock()
  154. {
  155.     extern int errno;
  156.     register int i = 0, fd, c;
  157.  
  158.     /* idea from rpick%ucqais@uccba.uc.edu
  159.      * prevent automated rerolling of characters
  160.      * test input (fd0) so that tee'ing output to get a screen dump still
  161.      * works
  162.      * also incidentally prevents development of any hack-o-matic programs
  163.      */
  164.     if (!isatty(0))
  165.         error("You must play from a terminal.");
  166.  
  167.     /* we ignore QUIT and INT at this point */
  168.     if (!lock_file(HLOCK, 10)) {
  169.         wait_synch();
  170.         error("");
  171.     }
  172.  
  173.     regularize(lock);
  174.     set_levelfile_name(lock, 0);
  175.  
  176.     if(locknum) {
  177.         if(locknum > 25) locknum = 25;
  178.  
  179.         do {
  180.             lock[0] = 'a' + i++;
  181.  
  182.             if((fd = open(lock, 0)) == -1) {
  183.                 if(errno == ENOENT) goto gotlock; /* no such file */
  184.                 perror(lock);
  185.                 unlock_file(HLOCK);
  186.                 error("Cannot open %s", lock);
  187.             }
  188.  
  189.             if(veryold(fd) /* closes fd if true */
  190.                             && eraseoldlocks())
  191.                 goto gotlock;
  192.             (void) close(fd);
  193.         } while(i < locknum);
  194.  
  195.         unlock_file(HLOCK);
  196.         error("Too many hacks running now.");
  197.     } else {
  198.         if((fd = open(lock, 0)) == -1) {
  199.             if(errno == ENOENT) goto gotlock;    /* no such file */
  200.             perror(lock);
  201.             unlock_file(HLOCK);
  202.             error("Cannot open %s", lock);
  203.         }
  204.  
  205.         if(veryold(fd) /* closes fd if true */ && eraseoldlocks())
  206.             goto gotlock;
  207.         (void) close(fd);
  208.  
  209.         if(flags.window_inited) {
  210.             c = yn("There is already a game in progress under your name.  Destroy old game?");
  211.         } else {
  212.             (void) printf("\nThere is already a game in progress under your name.");
  213.             (void) printf("  Destroy old game? [yn] ");
  214.             (void) fflush(stdout);
  215.             c = getchar();
  216.             (void) putchar(c);
  217.             (void) fflush(stdout);
  218.             while (getchar() != '\n') ; /* eat rest of line and newline */
  219.         }
  220.         if(c == 'y' || c == 'Y')
  221.             if(eraseoldlocks())
  222.                 goto gotlock;
  223.             else {
  224.                 unlock_file(HLOCK);
  225.                 error("Couldn't destroy old game.");
  226.             }
  227.         else {
  228.             unlock_file(HLOCK);
  229.             error("");
  230.         }
  231.     }
  232.  
  233. gotlock:
  234.     fd = creat(lock, FCMASK);
  235.     unlock_file(HLOCK);
  236.     if(fd == -1) {
  237.         error("cannot creat lock file.");
  238.     } else {
  239.         if(write(fd, (genericptr_t) &hackpid, sizeof(hackpid))
  240.             != sizeof(hackpid)){
  241.             error("cannot write lock");
  242.         }
  243.         if(close(fd) == -1) {
  244.             error("cannot close lock");
  245.         }
  246.     }
  247. }    
  248.  
  249. void
  250. regularize(s)    /* normalize file name - we don't like .'s, /'s, spaces */
  251. register char *s;
  252. {
  253.     register char *lp;
  254.  
  255.     while((lp=index(s, '.')) || (lp=index(s, '/')) || (lp=index(s,' ')))
  256.         *lp = '_';
  257. #if defined(SYSV) && !defined(AIX_31)
  258.     /* avoid problems with 14 character file name limit */
  259. # ifdef COMPRESS
  260.     if(strlen(s) > 10)
  261.         /* leave room for .e from error and .Z from compress
  262.          * appended to save files */
  263.         s[10] = '\0';
  264. # else
  265.     if(strlen(s) > 11)
  266.         /* leave room for .nn appended to level files */
  267.         s[11] = '\0';
  268. # endif
  269. #endif
  270. }
  271.  
  272. #ifdef SHELL
  273. int
  274. dosh()
  275. {
  276.     register char *str;
  277.     if(child(0)) {
  278.         if(str = getenv("SHELL"))
  279.             (void) execl(str, str, NULL);
  280.         else
  281.             (void) execl("/bin/sh", "sh", NULL);
  282.         raw_print("sh: cannot execute.");
  283.         exit(1);
  284.     }
  285.     return 0;
  286. }
  287. #endif /* SHELL /**/
  288.  
  289. #if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
  290. int
  291. child(wt)
  292. int wt;
  293. {
  294.     register int f;
  295.     suspend_nhwindows(NULL);    /* also calls end_screen() */
  296.     if((f = fork()) == 0){        /* child */
  297.         (void) setgid(getgid());
  298.         (void) setuid(getuid());
  299. #ifdef CHDIR
  300.         (void) chdir(getenv("HOME"));
  301. #endif
  302.         return(1);
  303.     }
  304.     if(f == -1) {    /* cannot fork */
  305.         pline("Fork failed.  Try again.");
  306.         return(0);
  307.     }
  308.     /* fork succeeded; wait for child to exit */
  309.     (void) signal(SIGINT,SIG_IGN);
  310.     (void) signal(SIGQUIT,SIG_IGN);
  311.     (void) wait( (int *) 0);
  312.     (void) signal(SIGINT, (SIG_RET_TYPE) done1);
  313. #ifdef WIZARD
  314.     if(wizard) (void) signal(SIGQUIT,SIG_DFL);
  315. #endif
  316.     if(wt) {
  317.         raw_print("");
  318.         wait_synch();
  319.     }
  320.     resume_nhwindows();
  321.     return(0);
  322. }
  323. #endif
  324.