ftp.nice.ch/pub/next/unix/games/nethack.3.0.N.bs.tar.gz#/PubDomain/Games/HACK/vms/vmsunix.c

This is vmsunix.c in view mode; [Download] [Up]

/*	SCCS Id: @(#)vmsunix.c	3.0	88/04/13
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

/* This file collects some Unix dependencies; pager.c contains some more */

/*
 * The time is used for:
 *	- seed for rand()
 *	- year on tombstone and yymmdd in record file
 *	- phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
 *	- night and midnight (the undead are dangerous at midnight)
 *	- determination of what files are "very old"
 */

#include "hack.h"

#include <rms.h>
#include <jpidef.h>
#include <ssdef.h>
#include <errno.h>
#include <signal.h>
#undef off_t
#include <sys/stat.h>

int FDECL(link, (const char *, const char *));

void
setrandom()
{
	(void) Srand((long) time ((time_t *) 0));
}

static struct tm *
getlt()
{
	time_t date;

	(void) time(&date);
	return(localtime(&date));
}

int
getyear()
{
	return(1900 + getlt()->tm_year);
}

char *
getdate()
{
	static char datestr[7];
	register struct tm *lt = getlt();

	Sprintf(datestr, "%2d%2d%2d",
		lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
	if(datestr[2] == ' ') datestr[2] = '0';
	if(datestr[4] == ' ') datestr[4] = '0';
	return(datestr);
}

int
phase_of_the_moon()			/* 0-7, with 0: new, 4: full */
{					/* moon period: 29.5306 days */
					/* year: 365.2422 days */
	register struct tm *lt = getlt();
	register int epact, diy, goldn;

	diy = lt->tm_yday;
	goldn = (lt->tm_year % 19) + 1;
	epact = (11 * goldn + 18) % 30;
	if ((epact == 25 && goldn > 11) || epact == 24)
		epact++;

	return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
}

int
night()
{
	register int hour = getlt()->tm_hour;

	return(hour < 6 || hour > 21);
}

int
midnight()
{
	return(getlt()->tm_hour == 0);
}

static struct stat buf, hbuf;

void
gethdate(name) char *name; {
	register char *np;

	if(stat(name, &hbuf))
		error("Cannot get status of %s.",
			(np = rindex(name, ']')) ? np+1 : name);
}

int
uptodate(fd)
int fd;
{
	if(fstat(fd, &buf)) {
		pline("Cannot get status of saved level? ");
		return(0);
	}
	if(buf.st_mtime < hbuf.st_mtime) {
		pline("Saved level is out of date. ");
		return(0);
	}
	return(1);
}

static int
veryold(fd)
int fd;
{
	register int i;
	time_t date;

	if(fstat(fd, &buf)) return(0);			/* cannot get status */
	if(buf.st_size != sizeof(int)) return(0);	/* not an xlock file */
	(void) time(&date);
	if(date - buf.st_mtime < 3L*24L*60L*60L) {	/* recent */
		int lockedpid;	/* should be the same size as hackpid */
		int status, dummy, code = JPI$_PID;

		if(read(fd, (char *)&lockedpid, sizeof(lockedpid)) !=
			sizeof(lockedpid))
			/* strange ... */
			return(0);
  		if(!(!((status = LIB$GETJPI(&code, &lockedpid, 0, &dummy)) & 1)
		     && status == SS$_NONEXPR))
			return(0);
	}
	(void) close(fd);
	for(i = 1; i <= MAXLEVEL+1; i++) {		/* try to remove all */
		glo(i);
		(void) delete(lock);
	}
	glo(0);
	if(delete(lock)) return(0);			/* cannot remove it */
	return(1);					/* success! */
}

void
getlock()
{
	register int i = 0, fd;

#ifdef HARD
	/* idea from rpick%ucqais@uccba.uc.edu
	 * prevent automated rerolling of characters
	 * test input (fd0) so that tee'ing output to get a screen dump still
	 * works
	 * also incidentally prevents development of any hack-o-matic programs
	 */
	if (!isatty(0))
		error("You must play from a terminal.");
#endif

	(void) fflush(stdout);

	/* we ignore QUIT and INT at this point */
	if (link(HLOCK, LLOCK) == -1) {
		register int errnosv = errno;

		perror(HLOCK);
		Printf("Cannot link %s to %s\n", LLOCK, HLOCK);
		switch(errnosv) {
		case ENOENT:
		    Printf("Perhaps there is no (empty) file %s ?\n", HLOCK);
		    break;
		case EACCES:
		    Printf("It seems you don't have write permission here.\n");
		    break;
		case EEXIST:
		    Printf("(Try again or rm %s.)\n", LLOCK);
		    break;
		default:
		    Printf("I don't know what is wrong.");
		}
		getret();
		error("");
		/*NOTREACHED*/
	}

	regularize(lock);
	glo(0);
	if(locknum > 25) locknum = 25;

	do {
		if(locknum) lock[0] = 'a' + i++;

		if((fd = open(lock, 0)) == -1) {
			if(errno == ENOENT) goto gotlock;    /* no such file */
			perror(lock);
			(void) unlink(LLOCK);
			error("Cannot open %s", lock);
		}

		if(veryold(fd))	/* if true, this closes fd and unlinks lock */
			goto gotlock;
		(void) close(fd);
	} while(i < locknum);

	(void) unlink(LLOCK);
	error(locknum ? "Too many hacks running now."
		      : "There is a game in progress under your name.");
gotlock:
	fd = creat(lock, FCMASK);
	if(unlink(LLOCK) == -1)
		error("Cannot unlink %s.", LLOCK);
	if(fd == -1) {
		error("cannot creat lock file.");
	} else {
		if(write(fd, (char *) &hackpid, sizeof(hackpid))
		    != sizeof(hackpid)){
			error("cannot write lock");
		}
		if(close(fd) == -1) {
			error("cannot close lock");
		}
	}
}	

void
regularize(s)	/* normalize file name */
register char *s;
{
	register char *lp;

	for (lp = s; *lp; lp++)
		if (!((*lp >= 'A' && *lp <= 'Z')
		      || (*lp >= 'a' && *lp <= 'z')
		      || (*lp >= '0' && *lp <= '9')
		      || *lp == '$' || *lp == '_'
		      || (lp > s && *lp == '-')))
			*lp = '_';
}

int link(file, new)
const char *file, *new;
{
    int status;
    struct FAB fab;
    struct NAM nam;
    unsigned short fid[3];
    char esa[NAM$C_MAXRSS];

    fab = cc$rms_fab;
    fab.fab$l_fop = FAB$M_OFP;
    fab.fab$l_fna = file;
    fab.fab$b_fns = strlen(file);
    fab.fab$l_nam = &nam;

    nam = cc$rms_nam;
    nam.nam$l_esa = esa;
    nam.nam$b_ess = NAM$C_MAXRSS;

    if (!((status = SYS$PARSE(&fab)) & 1)
	|| !((status = SYS$SEARCH(&fab)) & 1))
    {
	C$$TRANSLATE(status);
	return -1;
    }

    fid[0] = nam.nam$w_fid[0];
    fid[1] = nam.nam$w_fid[1];
    fid[2] = nam.nam$w_fid[2];

    fab.fab$l_fna = new;
    fab.fab$b_fns = strlen(new);

    if (!((status = SYS$PARSE(&fab)) & 1))
    {
	C$$TRANSLATE(status);
	return -1;
    }

    nam.nam$w_fid[0] = fid[0];
    nam.nam$w_fid[1] = fid[1];
    nam.nam$w_fid[2] = fid[2];

    nam.nam$l_esa = nam.nam$l_name;
    nam.nam$b_esl = nam.nam$b_name + nam.nam$b_type + nam.nam$b_ver;

    if (!((status = SYS$ENTER(&fab)) & 1))
    {
	C$$TRANSLATE(status);
	return -1;
    }

    return 0;
}

#undef unlink
int unlink(file)
const char *file;
{
    int status;
    struct FAB fab = cc$rms_fab;
    struct NAM nam = cc$rms_nam;
    char esa[NAM$C_MAXRSS];

    fab.fab$l_fop = FAB$M_DLT;
    fab.fab$l_fna = (char *) file;
    fab.fab$b_fns = strlen(file);
    fab.fab$l_nam = &nam;
    nam.nam$l_esa = esa;
    nam.nam$b_ess = NAM$C_MAXRSS;

    if (!((status = SYS$PARSE(&fab)) & 1)
	|| !((status = SYS$REMOVE(&fab)) & 1))
    {
	C$$TRANSLATE(status);
	return -1;
    }

    return 0;
}

#undef creat
int vms_creat(file, mode)
char *file;
unsigned int mode;
{
    if (index(file, ';'))
	(void) delete(file);
    return creat(file, mode);
}

#undef getuid
int
vms_getuid()
{
    return (getgid() << 16) | getuid();
}

#ifdef CHDIR
unsigned int oprv[2];

void
privoff()
{
    unsigned int prv[2] = { -1, -1 }, code = JPI$_PROCPRIV;

    (void) SYS$SETPRV(0, prv, 0, oprv);
    (void) LIB$GETJPI(&code, 0, 0, prv);
    (void) SYS$SETPRV(1, prv, 0, 0);
}

void
privon()
{
    (void) SYS$SETPRV(1, oprv, 0, 0);
}
#endif

#ifdef SHELL
unsigned int dosh_pid = 0;

int
dosh()
{
	int status;

	settty((char *) NULL);	/* also calls end_screen() */
	(void) signal(SIGINT,SIG_IGN);
	(void) signal(SIGQUIT,SIG_IGN);
	if (!dosh_pid || !((status = LIB$ATTACH(&dosh_pid)) & 1))
	{
#ifdef CHDIR
		(void) chdir(getenv("PATH"));
		privoff();
#endif
		dosh_pid = 0;
		status = LIB$SPAWN(0, 0, 0, 0, 0, &dosh_pid);
#ifdef CHDIR
		privon();
		chdirx((char *) 0, 0);
#endif
	}
	gettty();
	setftty();
	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
#ifdef WIZARD
	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
#endif
	docrt();
	if (!(status & 1))
	    pline("Spawn failed.  Try again.");
	return 0;
}
#endif

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.