/*	SCCS Id: @(#)unixunix.c	3.4	1994/11/07	*/
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed.  See license for details. */

/* This file collects some Unix dependencies */

#include "hack.h"	/* mainly for index() which depends on BSD */

#include <errno.h>
#include <sys/stat.h>
#include <signal.h>
#include <stdio.h>

#ifdef SUSPEND
#include "kernel.h"
#include "swis.h"
#endif

void
getlock() /* Stolen from mac version, then beaten into submission */
{
	FILE *f;
	const char *fq_lock;
	int pid = getpid(); /* Process ID */
	
	set_levelfile_name(lock,0);
	fq_lock = fqname(lock, LEVELPREFIX, 0); /* Add prefix */ 

	f = fopen(fq_lock,"w");
	if (f == NULL)
	{
		raw_printf("Could not lock the game %s.", lock);
		panic("Doh!");
	}
	fputc(pid & 255,f);
	fputc((pid >> 8) & 255,f); 
	fputc((pid >> 16) & 255,f);
	fputc((pid >> 24) & 255,f);
	fclose(f); 
}

void
regularize(s)	/* normalize file name - we don't like .'s, /'s, spaces */
register char *s;
{
	register char *lp;

	while((lp=index(s, '.')) || (lp=index(s, '/')) || (lp=index(s,' ')))
		*lp = '_';
#ifdef RUNTIME_SHORT_FILENAMES
	/* avoid problems with 10 character file name limit */
# ifdef COMPRESS
	/* leave room for .e from error and .Z from compress appended to
	 * save files */
	{
#  ifdef COMPRESS_EXTENSION
	    int i = 8 - strlen(COMPRESS_EXTENSION); /* Are these lengths right? I've just shortened them all by 4... (14->10) */
#  else
	    int i = 6;		/* should never happen... */
#  endif
	    if(strlen(s) > i)
		s[i] = '\0';
	}
# else
	if(strlen(s) > 7)
		/* leave room for .nn appended to level files */
		s[7] = '\0';
# endif
#endif
}

#ifdef SHELL
int
dosh()
{
	register char *str;
	if(child(0)) {
		if((str = getenv("SHELL")) != (char*)0)
			(void) execl(str, str, (char *)0);
		else
			(void) execl("/bin/sh", "sh", (char *)0);
		raw_print("sh: cannot execute.");
		exit(EXIT_FAILURE);
	}
	return 0;
}
#endif /* SHELL */

#if defined(SHELL) || defined(DEF_PAGER) || defined(DEF_MAILREADER)
int
child(wt)
int wt;
{
	register int f;
	suspend_nhwindows((char *)0);	/* also calls end_screen() */
	if((f = fork()) == 0){		/* child */
		(void) setgid(getgid());
		(void) setuid(getuid());
		return(1);
	}
	if(f == -1) {	/* cannot fork */
		pline("Fork failed.  Try again.");
		return(0);
	}
	/* fork succeeded; wait for child to exit */
	(void) signal(SIGINT,SIG_IGN);
	(void) signal(SIGQUIT,SIG_IGN);
	(void) wait( (int *) 0);
	(void) signal(SIGINT, (SIG_RET_TYPE) done1);
#ifdef WIZARD
	if(wizard) (void) signal(SIGQUIT,SIG_DFL);
#endif
	if(wt) {
		raw_print("");
		wait_synch();
	}
	resume_nhwindows();
	return(0);
}
#endif

#ifdef GETRES_SUPPORT

/* Hard-wire id's to 1 */

int
(getresuid)(ruid, euid, suid)
uid_t *ruid, *euid, *suid;
{
    return 1;
}

uid_t
(getuid)()
{
    return 1;
}

uid_t
(geteuid)()
{
    return 1;
}

int
(getresgid)(rgid, egid, sgid)
gid_t *rgid, *egid, *sgid;
{
    return 1;
}

gid_t
(getgid)()
{
    return 1;
}

gid_t
(getegid)()
{
    return 1;
}

#endif	/* GETRES_SUPPORT */

#ifdef SUSPEND
int dosuspend()
{
	int ic,mode,*mblk,handle;
	_kernel_swi_regs regs;
	_kernel_oserror *err;
	int blk[64];
	/* Provide our own version of dosuspend(), which drops back to the WIMP
	   just leaving an icon on the iconbar. Clicking that will then resume
	   the game. */
	/* First, check if we were run from the WIMP */
	/* Relying on Wimp$State isn't possible, since that will prevent us
	   running at all - the mode change (and probably the character
	   redefinitions) in the !Run file cause Wimp$State to change from
	   'desktop' to some other value */
	/* So just rely on TaskWindow_TaskInfo, and any error returned by
	   Wimp_Initialise */
	regs.r[0] = 0;
	_kernel_swi(TaskWindow_TaskInfo,&regs,&regs);
	if (regs.r[0])
	{
		pline("Unable to suspend - !NetHack doesn't appear to have been run from the WIMP");
		return 0;
	}
	/* Assume we can enter the WIMP, so suspend windows & get screen mode */
	suspend_nhwindows((char *)0);
	regs.r[0] = 1;
	_kernel_swi(OS_ScreenMode,&regs,&regs);
	if (regs.r[1] >= 256)
	{
		mode=5;
		while (((int *) regs.r[1])[mode] != -1)
			mode += 2;
		mode++;
		mblk = malloc(sizeof(int)*mode);
		while (mode >= 0)
		{
			mblk[mode] = ((int *) regs.r[1])[mode];
			mode--;
		}
		return 0;
	}
	else
	{
		mode = regs.r[1];
		mblk = 0;
	}
	/* Now try registering */
	regs.r[0] = 310;
	regs.r[1] = 0x4B534154; /* 'TASK' */
	regs.r[2] = (int) "NetHack";
	regs.r[3] = 0; /* Ignore all user messages except quit */
	err = _kernel_swi(Wimp_Initialise,&regs,&regs);
	if (err)
	{
		/* Copy error block, in case it gets overwritten */
		memcpy(blk,err,256);
		err = (_kernel_oserror *) blk;
		/* Now restore mode */
		regs.r[0] = 0;
		if (mblk)
			regs.r[1] = (int) mblk;
		else
			regs.r[1] = mode;
		regs.r[1] = 15;
		_kernel_swi(OS_ScreenMode,&regs,&regs);
		if (mblk)
			free(mblk);
		/* Resume windows */
		resume_nhwindows();
		/* Print error */
		pline("Unable to suspend - got error %d, '%s'",err->errnum,err->errmess);
		return 0;
	}
	handle = regs.r[1];
	/* Now create iconbar icon */
	regs.r[0] = 0;
	regs.r[1] = (int) blk;
	blk[0] = -1;
	blk[1] = 0;
	blk[2] = 0;
	blk[3] = 68;
	blk[4] = 70;
	blk[5] = 0x301A; /* Sprite, H&V centered, click without auto repeat */
	strcpy((char *) &blk[6],"!NetHack");
	_kernel_swi(Wimp_CreateIcon,&regs,&regs);
	ic = regs.r[0];
	/* Wait */
	do {
		regs.r[0] = 0x3933; /* Ignore all except mouse click & user message */
		regs.r[1] = (int) blk;
		_kernel_swi(Wimp_Poll,&regs,&regs);
	} while ((regs.r[0] != 6) &&
			!( ((regs.r[0] == 17) || (regs.r[0] == 18)) && (blk[4] == 0))); /* While not mouse click, and not quit */
	if (regs.r[0] == 6)
		blk[4] = 1; /* 'No quit' flag */
	/* So quit WIMP & resume nethack */
	regs.r[0] = handle;
	regs.r[1] = 0x4B534154; /* 'TASK' */
	_kernel_swi(Wimp_CloseDown,&regs,&regs);
	/* Get old screen mode back */
	regs.r[0] = 0;
	if (mblk)
		regs.r[1] = (int) mblk;
	else
		regs.r[1] = mode;
	regs.r[1] = 15;
	_kernel_swi(OS_ScreenMode,&regs,&regs);
	if (mblk)
		free(mblk);
	/* Resume */
	resume_nhwindows();
	/* Check if we should quit */
	if (blk[4] == 0)
		done2();
	return 0;
}

#endif /* SUSPEND */
