/* _msdos.c  93.12.21
 * Copyright 1983-1992   Albert Davis
 * Non-portable functions for MSDOS
 */
#include "error.h"
#include <dos.h>
#include <process.h>
#include <signal.h>
#include <time.h>
/*--------------------------------------------------------------------------*/
	void    initialize_io(void);
	void    setup_traps(void);
static	void	sig_int(int);
static	void	sig_fpe(int);
	void	getrusage(int,struct rusage*);
	void	shell(void);
	int	system(const char*);
#ifdef MSC
static	char	getswitchar(void);
	double	Exp(double);
#endif
/*--------------------------------------------------------------------------*/
/*extern int _fmode;*/	    /* defined in stdlib.h */
/*extern char **environ;*/  /* defined in stdlib.h */
extern struct ioctrl io;
extern char e_int[], e_om[];
extern FILE *stream[];	    /* reverse of fileno() */
#ifdef __BORLANDC__
extern unsigned _stklen = 10000U;
#endif
/*--------------------------------------------------------------------------*/
void initialize_io(void)
{
 stream[fileno(stdin )] = stdin;
 stream[fileno(stdout)] = stdout;
 stream[fileno(stderr)] = stderr;
 stream[fileno(stdaux)] = stdaux;
 stream[fileno(stdprn)] = stdprn;
 io.mstdout = io.mstderr = 1<<fileno(stdout);
 io.mprint = 1<<fileno(stdprn);
 setbuf(stdprn, NULL);
 /*setmode(fileno(stdin), (int)O_BINARY);*/
}
/*--------------------------------------------------------------------------*/
void setup_traps(void)
{
 _fpreset();
 (void)signal(SIGFPE,sig_fpe);
 (void)signal(SIGINT,sig_int);
}
/*--------------------------------------------------------------------------*/
/* sig_int: what to do on receipt of interrupt signal (SIGINT)
 * cancel batch files, then back to command mode.
 * (actually, control-c trap)
 */
/*ARGSUSED*/
static void sig_int(int sig)
{
 (void)signal(SIGINT,sig_int);
 error(bERROR, "\n");
}
/*--------------------------------------------------------------------------*/
/*ARGSUSED*/
static void sig_fpe(int sig)
{
 error(bERROR, "floating point error\n");
 _fpreset();
}
/*--------------------------------------------------------------------------*/
void getrusage(int who, struct rusage *rusage)
{
 double ticks = (double)clock();
 rusage->ru_stime.tv_sec = rusage->ru_stime.tv_usec = 0;
 rusage->ru_utime.tv_usec =
 	(long)fmod(ticks, (double)CLK_TCK) * (1000000./(double)CLK_TCK);
 rusage->ru_utime.tv_sec = (long)(ticks/(double)CLK_TCK);
}
/*--------------------------------------------------------------------------*/
void shell(void)
{
 char *shell;
 int errcod;

 if (!(shell=getenv("COMSPEC")))
    error(bERROR, e_int, "comspec");

 errcod = spawnle(P_WAIT, shell, shell, NULL, environ);
 _fpreset();
 if (errcod == EOF) {
    switch (errno) {
       case E2BIG:
          error(bERROR, e_int, "arg list");
       case EINVAL:
          error(bERROR, e_int, "mode flag");
       case ENOENT:
          error(bERROR, "no shell");
       case ENOEXEC:
          error(bERROR, "bad shell");
       case ENOMEM:
          error(bERROR, e_om,"");
       default:
          error(bERROR, e_int, "system");
    }
 }
}
/*--------------------------------------------------------------------------*/
int system(const char *string)
{
 char *shell;
 char args[200];
 int errcod;

 if (!(shell=getenv("COMSPEC")))
    error(bERROR, e_int, "comspec");

 sprintf(args,"%cc %s",getswitchar(),string);

 errcod = spawnle(P_WAIT, shell, shell, args, NULL, environ);
 _fpreset();
 if (errcod == EOF) {
    switch (errno) {
       case E2BIG:
          error(bERROR, e_int, "arg list");
       case EINVAL:
          error(bERROR, e_int, "mode flag");
       case ENOENT:
          error(bERROR, "no shell");
       case ENOEXEC:
          error(bERROR, "bad shell");
       case ENOMEM:
          error(bERROR, e_om, "");
       default:
          error(bERROR, e_int, "system");
    }
 }
return 0;
}
/*--------------------------------------------------------------------------*/
#ifdef MSC
static char getswitchar(void)
{
 union REGS r;

 r.h.al = 0;
 r.h.ah = 0x37;
 intdos(&r, &r);
 return r.h.dl;
}
#endif
/*--------------------------------------------------------------------------*/
#ifdef MSC
double Exp(double x)	/* exp with trap.				    */
			/* function that comes with compiler gives strange  */
{			/* answers for large negative args,		    */
			/* after spawning a process			    */
#undef exp		/* temporary fix is to return 0 for more negative   */
			/* than -200.  (about -700 is the threshold)	    */
 return (x>-200.) ? exp(x) : 0.;
}
#endif
/*--------------------------------------------------------------------------*/
/*--------------------------------------------------------------------------*/
