# 2.11BSD#431 - /usr/src/games/hack/hack.unix.c

##### Functions

    ckmailstatus      X
    getdate           X
    gethdate          X
    getlock           X
    getlt             X
    getmailstatus     X
    getyear           X
    mdrush            X
    midnight          X
    newmail           X
    night             X
    phase_of_the_moon X
    readmail          X
    regularize        X
    setrandom         X
    uptodate          X
    veryold           X

##### Variables

    buf               X
    hbuf              X

##### Macros

    MAXPATHLEN        X

       1: /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
       2: /* hack.unix.c - version 1.0.3 */
       3:
       4: /* This file collects some Unix dependencies; hack.pager.c contains some more */
       5:
       6: /*
       7:  * The time is used for:
       8:  *	- seed for rand()
       9:  *	- year on tombstone and yymmdd in record file
      10:  *	- phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
      11:  *	- night and midnight (the undead are dangerous at midnight)
      12:  *	- determination of what files are "very old"
      13:  */
      14:
      15: #include <stdio.h>
      16: #include <errno.h>
      17: #include "hack.h"   /* mainly for index() which depends on BSD */
      18:
      19: #include    <sys/types.h>       /* for time_t and stat */
      20: #include    <sys/stat.h>
      21: #ifdef BSD
      22: #include    <sys/time.h>
      23: #else
      24: #include    <time.h>
      25: #endif BSD
      26:
      27: extern char *getenv();
      28: extern time_t time();
      29:
      30: setrandom()
      31: {
      32:     (void) srand((int) time ((time_t *) 0));
      33: }
      34:
      35: struct tm *
      36: getlt()
      37: {
      38:     time_t date;
      39:     struct tm *localtime();
      40:
      41:     (void) time(&date);
      42:     return(localtime(&date));
      43: }
      44:
      45: getyear()
      46: {
      47:     return(1900 + getlt()->tm_year);
      48: }
      49:
      50: char *
      51: getdate()
      52: {
      53:     static char datestr[7];
      54:     register struct tm *lt = getlt();
      55:
      56:     (void) sprintf(datestr, "%2d%2d%2d",
      57:         lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
      58:     if(datestr[2] == ' ') datestr[2] = '0';
      59:     if(datestr[4] == ' ') datestr[4] = '0';
      60:     return(datestr);
      61: }
      62:
      63: phase_of_the_moon()         /* 0-7, with 0: new, 4: full */
      64: {                   /* moon period: 29.5306 days */
      65:                     /* year: 365.2422 days */
      66:     register struct tm *lt = getlt();
      67:     register int epact, diy, golden;
      68:
      69:     diy = lt->tm_yday;
      70:     golden = (lt->tm_year % 19) + 1;
      71:     epact = (11 * golden + 18) % 30;
      72:     if ((epact == 25 && golden > 11) || epact == 24)
      73:         epact++;
      74:
      75:     return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
      76: }
      77:
      78: night()
      79: {
      80:     register int hour = getlt()->tm_hour;
      81:
      82:     return(hour < 6 || hour > 21);
      83: }
      84:
      85: midnight()
      86: {
      87:     return(getlt()->tm_hour == 0);
      88: }
      89:
      90: struct stat buf, hbuf;
      91:
      92: gethdate(name) char *name; {
      93: /* old version - for people short of space */
      94: /*
      95: /* register char *np;
      96: /*	if(stat(name, &hbuf))
      97: /*		error("Cannot get status of %s.",
      98: /*			(np = rindex(name, '/')) ? np+1 : name);
      99: /*
     100: /* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
     101:
     102:
     103: /*
     104:  * The problem with   #include	<sys/param.h>   is that this include file
     105:  * does not exist on all systems, and moreover, that it sometimes includes
     106:  * <sys/types.h> again, so that the compiler sees these typedefs twice.
     107:  */
     108: #define     MAXPATHLEN  128
     109:
     110: register char *np, *path;
     111: char filename[MAXPATHLEN+1];
     112:     if (index(name, '/') != NULL || (path = getenv("PATH")) == NULL)
     113:         path = "";
     114:
     115:     for (;;) {
     116:         if ((np = index(path, ':')) == NULL)
     117:             np = path + strlen(path);   /* point to end str */
     118:         if (np - path <= 1)         /* %% */
     119:             (void) strcpy(filename, name);
     120:         else {
     121:             (void) strncpy(filename, path, np - path);
     122:             filename[np - path] = '/';
     123:             (void) strcpy(filename + (np - path) + 1, name);
     124:         }
     125:         if (stat(filename, &hbuf) == 0)
     126:             return;
     127:         if (*np == '\0')
     128:             break;
     129:         path = np + 1;
     130:     }
     131:     error("Cannot get status of %s.",
     132:         (np = rindex(name, '/')) ? np+1 : name);
     133: }
     134:
     135: uptodate(fd) {
     136:     if(fstat(fd, &buf)) {
     137:         pline("Cannot get status of saved level? ");
     138:         return(0);
     139:     }
     140:     if(buf.st_mtime < hbuf.st_mtime) {
     141:         pline("Saved level is out of date. ");
     142:         return(0);
     143:     }
     144:     return(1);
     145: }
     146:
     147: /* see whether we should throw away this xlock file */
     148: veryold(fd) {
     149:     register int i;
     150:     time_t date;
     151:
     152:     if(fstat(fd, &buf)) return(0);          /* cannot get status */
     153:     if(buf.st_size != sizeof(int)) return(0);   /* not an xlock file */
     154:     (void) time(&date);
     155:     if(date - buf.st_mtime < 3L*24L*60L*60L) {  /* recent */
     156:         extern int errno;
     157:         int lockedpid;  /* should be the same size as hackpid */
     158:
     159:         if(read(fd, (char *)&lockedpid, sizeof(lockedpid)) !=
     160:             sizeof(lockedpid))
     161:             /* strange ... */
     162:             return(0);
     163:
     164:         /* From: Rick Adams <seismo!rick>
     165: 		/* This will work on 4.1cbsd, 4.2bsd and system 3? & 5.
     166: 		/* It will do nothing on V7 or 4.1bsd. */
     167:         if(!(kill(lockedpid, 0) == -1 && errno == ESRCH))
     168:             return(0);
     169:     }
     170:     (void) close(fd);
     171:     for(i = 1; i <= MAXLEVEL; i++) {        /* try to remove all */
     172:         glo(i);
     173:         (void) unlink(lock);
     174:     }
     175:     glo(0);
     176:     if(unlink(lock)) return(0);         /* cannot remove it */
     177:     return(1);                  /* success! */
     178: }
     179:
     180: getlock()
     181: {
     182:     extern int errno, hackpid, locknum;
     183:     register int i = 0, fd;
     184:
     185:     (void) fflush(stdout);
     186:
     187:     /* we ignore QUIT and INT at this point */
     188:     if (link(HLOCK, LLOCK) == -1) {
     189:         register int errnosv = errno;
     190:
     191:         perror(HLOCK);
     192:         printf("Cannot link %s to %s\n", LLOCK, HLOCK);
     193:         switch(errnosv) {
     194:         case ENOENT:
     195:             printf("Perhaps there is no (empty) file %s ?\n", HLOCK);
     196:             break;
     197:         case EACCES:
     198:             printf("It seems you don't have write permission here.\n");
     199:             break;
     200:         case EEXIST:
     201:             printf("(Try again or rm %s.)\n", LLOCK);
     202:             break;
     203:         default:
     204:             printf("I don't know what is wrong.");
     205:         }
     206:         getret();
     207:         error("");
     208:         /*NOTREACHED*/
     209:     }
     210:
     211:     regularize(lock);
     212:     glo(0);
     213:     if(locknum > 25) locknum = 25;
     214:
     215:     do {
     216:         if(locknum) lock[0] = 'a' + i++;
     217:
     218:         if((fd = open(lock, 0)) == -1) {
     219:             if(errno == ENOENT) goto gotlock;    /* no such file */
     220:             perror(lock);
     221:             (void) unlink(LLOCK);
     222:             error("Cannot open %s", lock);
     223:         }
     224:
     225:         if(veryold(fd)) /* if true, this closes fd and unlinks lock */
     226:             goto gotlock;
     227:         (void) close(fd);
     228:     } while(i < locknum);
     229:
     230:     (void) unlink(LLOCK);
     231:     error(locknum ? "Too many hacks running now."
     232:               : "There is a game in progress under your name.");
     233: gotlock:
     234:     fd = creat(lock, FMASK);
     235:     if(unlink(LLOCK) == -1)
     236:         error("Cannot unlink %s.", LLOCK);
     237:     if(fd == -1) {
     238:         error("cannot creat lock file.");
     239:     } else {
     240:         if(write(fd, (char *) &hackpid, sizeof(hackpid))
     241:             != sizeof(hackpid)){
     242:             error("cannot write lock");
     243:         }
     244:         if(close(fd) == -1) {
     245:             error("cannot close lock");
     246:         }
     247:     }
     248: }
     249:
     250: #ifdef MAIL
     251:
     252: /*
     253:  * Notify user when new mail has arrived. [Idea from Merlyn Leroy, but
     254:  * I don't know the details of his implementation.]
     255:  * { Later note: he disliked my calling a general mailreader and felt that
     256:  *   hack should do the paging itself. But when I get mail, I want to put it
     257:  *   in some folder, reply, etc. - it would be unreasonable to put all these
     258:  *   functions in hack. }
     259:  * The mail daemon '2' is at present not a real monster, but only a visual
     260:  * effect. Thus, makemon() is superfluous. This might become otherwise,
     261:  * however. The motion of '2' is less restrained than usual: diagonal moves
     262:  * from a DOOR are possible. He might also use SDOOR's. Also, '2' is visible
     263:  * in a ROOM, even when you are Blind.
     264:  * Its path should be longer when you are Telepat-hic and Blind.
     265:  *
     266:  * Interesting side effects:
     267:  *	- You can get rich by sending yourself a lot of mail and selling
     268:  *	  it to the shopkeeper. Unfortunately mail isn't very valuable.
     269:  *	- You might die in case '2' comes along at a critical moment during
     270:  *	  a fight and delivers a scroll the weight of which causes you to
     271:  *	  collapse.
     272:  *
     273:  * Possible extensions:
     274:  *	- Open the file MAIL and do fstat instead of stat for efficiency.
     275:  *	  (But sh uses stat, so this cannot be too bad.)
     276:  *	- Examine the mail and produce a scroll of mail called "From somebody".
     277:  *	- Invoke MAILREADER in such a way that only this single letter is read.
     278:  *
     279:  *	- Make him lose his mail when a Nymph steals the letter.
     280:  *	- Do something to the text when the scroll is enchanted or cancelled.
     281:  */
     282: #include    "def.mkroom.h"
     283: static struct stat omstat,nmstat;
     284: static char *mailbox;
     285: static long laststattime;
     286:
     287: getmailstatus() {
     288:     if(!(mailbox = getenv("MAIL")))
     289:         return;
     290:     if(stat(mailbox, &omstat)){
     291: #ifdef PERMANENT_MAILBOX
     292:         pline("Cannot get status of MAIL=%s .", mailbox);
     293:         mailbox = 0;
     294: #else
     295:         omstat.st_mtime = 0;
     296: #endif PERMANENT_MAILBOX
     297:     }
     298: }
     299:
     300: ckmailstatus() {
     301:     if(!mailbox
     302: #ifdef MAILCKFREQ
     303:             || moves < laststattime + MAILCKFREQ
     304: #endif MAILCKFREQ
     305:                             )
     306:         return;
     307:     laststattime = moves;
     308:     if(stat(mailbox, &nmstat)){
     309: #ifdef PERMANENT_MAILBOX
     310:         pline("Cannot get status of MAIL=%s anymore.", mailbox);
     311:         mailbox = 0;
     312: #else
     313:         nmstat.st_mtime = 0;
     314: #endif PERMANENT_MAILBOX
     315:     } else if(nmstat.st_mtime > omstat.st_mtime) {
     316:         if(nmstat.st_size)
     317:             newmail();
     318:         getmailstatus();    /* might be too late ... */
     319:     }
     320: }
     321:
     322: newmail() {
     323:     /* produce a scroll of mail */
     324:     register struct obj *obj;
     325:     register struct monst *md;
     326:     extern char plname[];
     327:     extern struct obj *mksobj(), *addinv();
     328:     extern struct monst *makemon();
     329:     extern struct permonst pm_mail_daemon;
     330:
     331:     obj = mksobj(SCR_MAIL);
     332:     if(md = makemon(&pm_mail_daemon, u.ux, u.uy)) /* always succeeds */
     333:         mdrush(md,0);
     334:
     335:     pline("\"Hello, %s! I have some mail for you.\"", plname);
     336:     if(md) {
     337:         if(dist(md->mx,md->my) > 2)
     338:             pline("\"Catch!\"");
     339:         more();
     340:
     341:         /* let him disappear again */
     342:         mdrush(md,1);
     343:         mondead(md);
     344:     }
     345:
     346:     obj = addinv(obj);
     347:     (void) identify(obj);       /* set known and do prinv() */
     348: }
     349:
     350: /* make md run through the cave */
     351: mdrush(md,away)
     352: register struct monst *md;
     353: boolean away;
     354: {
     355:     register int uroom = inroom(u.ux, u.uy);
     356:     if(uroom >= 0) {
     357:         register int tmp = rooms[uroom].fdoor;
     358:         register int cnt = rooms[uroom].doorct;
     359:         register int fx = u.ux, fy = u.uy;
     360:         while(cnt--) {
     361:             if(dist(fx,fy) < dist(doors[tmp].x, doors[tmp].y)){
     362:                 fx = doors[tmp].x;
     363:                 fy = doors[tmp].y;
     364:             }
     365:             tmp++;
     366:         }
     367:         tmp_at(-1, md->data->mlet); /* open call */
     368:         if(away) {  /* interchange origin and destination */
     369:             unpmon(md);
     370:             tmp = fx; fx = md->mx; md->mx = tmp;
     371:             tmp = fy; fy = md->my; md->my = tmp;
     372:         }
     373:         while(fx != md->mx || fy != md->my) {
     374:             register int dx,dy,nfx = fx,nfy = fy,d1,d2;
     375:
     376:             tmp_at(fx,fy);
     377:             d1 = DIST(fx,fy,md->mx,md->my);
     378:             for(dx = -1; dx <= 1; dx++) for(dy = -1; dy <= 1; dy++)
     379:                 if(dx || dy) {
     380:                 d2 = DIST(fx+dx,fy+dy,md->mx,md->my);
     381:                 if(d2 < d1) {
     382:                     d1 = d2;
     383:                     nfx = fx+dx;
     384:                     nfy = fy+dy;
     385:                 }
     386:                 }
     387:             if(nfx != fx || nfy != fy) {
     388:                 fx = nfx;
     389:                 fy = nfy;
     390:             } else {
     391:                 if(!away) {
     392:                 md->mx = fx;
     393:                 md->my = fy;
     394:                 }
     395:                 break;
     396:             }
     397:         }
     398:         tmp_at(-1,-1);          /* close call */
     399:     }
     400:     if(!away)
     401:         pmon(md);
     402: }
     403:
     404: readmail() {
     405: #ifdef DEF_MAILREADER           /* This implies that UNIX is defined */
     406:     register char *mr = 0;
     407:     more();
     408:     if(!(mr = getenv("MAILREADER")))
     409:         mr = DEF_MAILREADER;
     410:     if(child(1)){
     411:         execl(mr, mr, (char *) 0);
     412:         exit(1);
     413:     }
     414: #else DEF_MAILREADER
     415:     (void) page_file(mailbox, FALSE);
     416: #endif DEF_MAILREADER
     417:     /* get new stat; not entirely correct: there is a small time
     418: 	   window where we do not see new mail */
     419:     getmailstatus();
     420: }
     421: #endif MAIL
     422:
     423: regularize(s)   /* normalize file name - we don't like ..'s or /'s */
     424: register char *s;
     425: {
     426:     register char *lp;
     427:
     428:     while((lp = index(s, '.')) || (lp = index(s, '/')))
     429:         *lp = '_';
     430: }

#### Defined functions

ckmailstatus defined in line 300; used 1 times

- in /usr/src/games/hack/hack.main.c line 395

getdate defined in line 50; used 2 times

- in /usr/src/games/hack/hack.end.c line 224, 258

gethdate defined in line 92; used 1 times

- in /usr/src/games/hack/hack.main.c line 125

getlock defined in line 180; used 1 times

- in /usr/src/games/hack/hack.main.c line 206

getlt defined in line 35; used 5 times

- in line 47, 54, 66, 80, 87

getmailstatus defined in line 287; used 3 times

- in line 318, 419
- in /usr/src/games/hack/hack.main.c line 184

getyear defined in line 45; used 1 times

- in /usr/src/games/hack/hack.rip.c line 56

mdrush defined in line 351; used 2 times

- in line 333, 342

midnight defined in line 85; used 2 times

- in /usr/src/games/hack/hack.mhitu.c line 65
- in /usr/src/games/hack/hack.shk.c line 165

newmail defined in line 322; used 1 times

- in line 317

night defined in line 78; used 1 times

- in /usr/src/games/hack/hack.dog.c line 386

phase_of_the_moon defined in line 63; used 1 times

- in /usr/src/games/hack/hack.main.c line 288

readmail defined in line 404; used 1 times

- in /usr/src/games/hack/hack.read.c line 31

regularize defined in line 423; used 2 times

- in line 211
- in /usr/src/games/hack/hack.main.c line 242

setrandom defined in line 30; used 1 times

- in /usr/src/games/hack/hack.main.c line 114

uptodate defined in line 135; used 2 times

- in /usr/src/games/hack/hack.bones.c line 81
- in /usr/src/games/hack/hack.main.c line 244

veryold defined in line 148; used 1 times

- in line 225

#### Defined variables

buf defined in line 90; used 5 times

- in line 136-140(2), 152-155(3)

hbuf defined in line 90; used 2 times

- in line 125, 140

laststattime defined in line 285; used 2 times

- in line 303-307(2)

mailbox defined in line 284; used 9 times

- in line 288-293(4), 301, 308-311(3), 415

nmstat defined in line 283; used 4 times

- in line 308-316(4)

omstat defined in line 283; used 3 times

- in line 290-295(2), 315

#### Defined macros

MAXPATHLEN defined in line 108; used 1 times

- in line 111

Last modified: 1988-08-24 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1245 |