/* Atari ST-specific functions, common to NET and BM */
/* written by Rob Janssen, PE1CHL */

#include <stdio.h>
#ifdef MWC
#include <osbind.h>			/* os interface defines */
#endif

#include "global.h"
#include "atari.h"

/* name of tempfiles in program-dependent to allow concurrent running */

static char tmpfilename[2];

/* current drive and dir at startup */

int  st_curdrive;
char st_curdir[66];

/* varnames for filename constants in files.c */

extern char startup[];
extern char on_exit[];
extern char userfile[];
extern char hosts[];
extern char fingerpath[];
extern char mailspool[];
extern char mailqdir[];
extern char routeqdir[];
extern char alias[];
extern char tmpdir[],TMPDIR[];
extern char bm_rc[];

void free();
char *getenv(),*getnenv();

/* Atari ST specific initialization code */

atari_init(tmpfname)
	char tmpfname;			/* 'b' or 'n' */

{
	char dirname[64];		/* temp dirname buffer */

	tmpfilename[0] = tmpfname;	/* set temp file name char */

	st_curdrive = Dgetdrv();	/* get current drive (0,1,...) */

	if (Dgetpath(dirname,0) == 0){	/* get current dir */
		sprintf(st_curdir,"%c:%s%s",(char) st_curdrive+'A',
			(*dirname? "" : "\\"),dirname);
	}

	/* fixup pathnames */

	startup[0] += st_curdrive;
	on_exit[0] += st_curdrive;
	userfile[0] += st_curdrive;
	hosts[0] += st_curdrive;
	fingerpath[0] += st_curdrive;
	mailspool[0] += st_curdrive;
	mailqdir[0] += st_curdrive;
	routeqdir[0] += st_curdrive;
	alias[0] += st_curdrive;
	tmpdir[0] += st_curdrive;
	bm_rc[0] += st_curdrive;

	printf("\033v\033e\033E\n");	/* autoWRAP ON, cursor ON, CLS, linefeed */
#if 0
	cleantemp();			/* clean the temp dir */
#endif
}

/* atari specific exit code */

atari_stop()
{
#if 0
	cleantemp();			/* remove any created temp files */
#endif
	Dsetdrv(st_curdrive);		/* reset current drive */
	Dsetpath(st_curdir);		/* reset directory */
}

#if 0
/* remove temp files (tempdir\[BN]*.TMP) */
cleantemp ()

{
	char filename[80];
	struct dta dta;

	Fsetdta(&dta);			/* set transfer area */

	strcpy(filename,getnenv(TMPDIR));
	strcat(filename,"\\");
	strcat(filename,tmpfilename);	/* "b" or "n" */
	strcat(filename,"*.TMP");

	if (Fsfirst(filename,~0x18) == 0)
		do
		{
			strcpy(filename,getnenv(TMPDIR));
			strcat(filename,"\\");
			strcat(filename,dta.fname);
			unlink(filename);
		} while (Fsnext() == 0);
}
#endif

/* build temp file name
 * this version is used instead of the lib routine to be able to set
 * tmp directory name, and to provide more unique names
 */

char *tmpnam (s)
	char *s;

{
	static char buf[64];
	static long sequence = 0;

	if (s == NULLCHAR)
	    s = buf;

	sprintf(s,"%s\\%s%07ld.TMP",getnenv(TMPDIR),tmpfilename,sequence++);

	return (s);
}

/* create and open temp file */
/* name is administered and it will be deleted by our replacement fclose() */

struct tempfiles {
	struct tempfiles *next;
	struct tempfiles *prev;
	FILE *fp;
	char name[1];
} *tempfiles = NULL;

FILE *tmpfile ()

{
	char *name;
	FILE *fp;
	register struct tempfiles *tf;

	name = tmpnam(NULLCHAR);

	if ((tf = (struct tempfiles *) calloc(1,sizeof(struct tempfiles) + strlen(name))) == NULL)
		return NULL;

	if ((fp = fopen(name,"w+")) == NULLFILE)
		free(tf);
	else {
		if ((tf->next = tempfiles) != NULL)
			tempfiles->prev = tf;

		tempfiles = tf;
		tf->fp = fp;
		strcpy(tf->name,name);
	}

	return (fp);
}

/* replacement for fclose().  checks if it is a tempfile and deletes it. */

#undef fclose
int notmpfclose (fp)
FILE *fp;

{
	int rv;
	register struct tempfiles *tf;

	rv = fclose(fp);		/* first close the file */

	for (tf = tempfiles; tf != NULL; tf = tf->next)
		if (tf->fp == fp) {	/* this one a tempfile? */
			unlink(tf->name); /* then remove it */

			if (tf->next != NULL)
				tf->next->prev = tf->prev;

			if (tf->prev != NULL)
				tf->prev->next = tf->next;
			else
				tempfiles = tf->next;

			free((char *) tf);
			break;
		}

	return rv;			/* return fclose() result */
}

#ifdef MWC
/* rename a file (MW C doesn't have it) */

int rename (s,d)
	char *s;			/* source name */
	char *d;			/* dest name */

{
	return (Frename(0,s,d) != 0L);	/* call gemdos function */
}
#endif

#ifdef __TURBOC__
/* create and remove directory (Turbo C doesn't have it) */

int mkdir (name)
	char *name;

{
	return (Dcreate(name) != 0L);	/* call gemdos function */
}

int rmdir (name)
	char *name;

{
	return (Ddelete(name) != 0L);	/* call gemdos function */
}

/* test accessability of a file (Turbo C doesn't have it) */

int access (name,mode)
	char *name;
	int mode;

{
	int rcode;
	struct dta dta,*orgdta;

	orgdta = Fgetdta();		/* save caller's DTA */
	Fsetdta(&dta);			/* set our's */
	rcode = Fsfirst(name,~0x08);	/* get all but volume lael */
	Fsetdta(orgdta);		/* restore DTA */

	if (rcode == 0){		/* found the file? */
		if (mode & 1)		/* exec */
			if (dta.attr & 0x18)
				return 1;

		if (mode & 2)		/* write */
			if (dta.attr & 0x19)
				return 1;

		if (mode & 4)		/* read */
			if (dta.attr & 0x08)
				return 1;

		return 0;
	}

	return 1;
}
#endif

#ifdef MWC
/* special version of calloc() that runs sligthly faster */
/* depends on Mark Williams routine lmalloc() */

char *calloc (count,size)
	unsigned count,size;

{
	register unsigned long n;
	register int16 *p;
	char *rv,*lmalloc();

	/* most calls specify a count of 1, save a long multiply.... */
	n = (count == 1)? size : (unsigned long) count * size;

	if ((rv = lmalloc(n)) != NULLCHAR)
	{
	    if (n = (n + 1) / 2){	/* compute number of words */
		p = (int16 *) rv;
		do
		{
		    *p++ = 0;
		} while (--n);
	    }
	}

	return rv;
}

/* a free() routine with some extra checks */
/* note that this will introduce a "free_ redefined" warning from */
/* the linker, but this can be ignored.	 define QFREE to skip this */
/* version, and use a macro (in global.h) instead. */

# ifndef QFREE
void
free (p)
register unsigned long *p;
{
	unsigned long s;
	extern unsigned long *_a_scanp;

	if ((s = p[-1]) == 0 || s > 1048576L || notmem(p)){
	    printf("WARNING!! freeing garbage (%ld @ 0x%lx)\n",s,p);
	    return;
	}

	if (s & 1){
	    printf("WARNING!! same area freed twice (%ld @ 0x%lx)\n",s & ~1L,p);
	    return;
	}

	*(_a_scanp = p - 1) |= 1;
}
# endif
#endif
