/* Release 3.00 */

/*-------------------------------------------------------------------------*
*                                                                          *
*  csys.c - common system functions.					   *
*                                                                          *
*  COPYRIGHT (C) 1989 Jensen and Partners. All Rights Reserved             *
*  Written by Simon Knight.                                                *
*                                                                          *
*  COPYRIGHT (C) 1991 Psion PLC. All Rights Reserved                       *
*  Modified by NSM.                                                        *
*                                                                          *
*--------------------------------------------------------------------------*/

#define _USE_CONIO
#define _USE_TIME
#include <clib.h>

/*-------------------------------------------------------------------------*
*	 exit functions - terminate process after closing open files.      *
*--------------------------------------------------------------------------*/

void _exit1(void)
{
    int n;

    _flushall();
    n=0;
    while(n < _open_max)
    {
        if(_openfd[n])
            close(n);
        n++;
    }
    return;
}

void _exit2(void)
{
   int n;
   char *tmp;

   n=0;
   while (n < _open_max)
   {
	if ((tmp=_tmpfiles[n])!=NULL)
	{
            if(_openfd[n])
        	close(n);
	    unlink(tmp);
	}
	n++;
    }
    return;
}

/*-------------------------------------------------------------------------*
*	 abort - print message and raise ABORT signal.			   *
*--------------------------------------------------------------------------*/

void abort(void)
{
    fputs("Abnormal Program Termination\n", stderr);
    raise(SIGABRT);
    return;
}

/*-------------------------------------------------------------------------*
*	 atexit - put function pointer on stack to be called by exit.	   *
*--------------------------------------------------------------------------*/

int atexit(void (* func)(void))
{
    int ret;

    if(_exit_ptr != _exit_stk)	      /* return if stack full */
    {
        *(--_exit_ptr)=func;	      /* push func */
        ret=0;
    }
    else
	ret=-1;
    return(ret);
}

/*-------------------------------------------------------------------------*
*     onexit - put function pointer on stack to be called by exit.	   *
*--------------------------------------------------------------------------*/

void (* onexit(void (* func)(void)))()
{
    void (* ret)(void);

    if(_exit_ptr != _exit_stk)	      /* return if stack full */
    {
        *(--_exit_ptr)=func;	      /* push func */
        ret=func;
    }
    else
	ret=NULL;
    return(ret);
}

/*-------------------------------------------------------------------------*
*	 system - execute command.com.					   *
*--------------------------------------------------------------------------*/

int system(const char *command)
{
    char *compath;

    compath=getenv("COMSPEC");	     /* use COMSPEC to find command.com */
    if(compath == NULL)
        compath="ROM::SYS$SHLL";
    if(command == NULL)
    {
        if(!_exists(compath))    /* does file exist ? */
        {
            errno=ENOENT;
            return(0);
        }
        return(1);
    }
    flushall(); 		     /* flush open streams */
    return(spawnl(P_WAIT,compath,"",command,NULL));
}

/*-------------------------------------------------------------------------*
*	 exec?? - execute child process.				   *
*--------------------------------------------------------------------------*/

#pragma warn(wpnu => off)

int execl(const char *path, char *arg0, ...)
{
    va_list argptr;

    va_start(argptr, path);
    return(_execc(path, (char **) argptr, _E_EXEC));
}

int execlp(const char *path, char *arg0, ...)
{
    va_list argptr;

    va_start(argptr, path);
    return(_execc(path, (char **) argptr, _E_EXEC|_E_SEARCH));
}

int execv(const char *path, char *argv[])
{
    return(_execc(path, argv, _E_EXEC));
}

int execvp(const char *path, char *argv[])
{
    return(_execc(path, argv, _E_EXEC|_E_SEARCH));
}

/*-------------------------------------------------------------------------*
*	 spawn?? - spawn  child process.				   *
*--------------------------------------------------------------------------*/

int spawnl(int mode, const char *path, char *arg0, ...)
{
    va_list argptr;

    va_start(argptr, path);
    return(_execc(path, (char **) argptr, mode));
}

int spawnlp(int mode, const char *path, char *arg0, ...)
{
    va_list argptr;

    va_start(argptr, path);
    return(_execc(path, (char **) argptr, mode|_E_SEARCH));
}

int spawnv(int mode, const char *path, char *argv[])

{
    return(_execc(path, argv, mode));
}

#pragma warn(wpnu => on)

int spawnvp(int mode, const char *path, char *argv[])
{
    return(_execc(path, argv, mode|_E_SEARCH));
}

/*-------------------------------------------------------------------------*
*	 searchenv - find file using environment string 		   *
*--------------------------------------------------------------------------*/

void _searchenv(const char *name, const char *env, char *path)
{
    char *envpath;
    int n, p, c;
    int length;

    if((envpath=getenv(env)) == NULL)
    {
	path[0]=0;
	return;
    }
    length=strlen(name)+1;
    getcwd(path, 0x80);	      /* try current directory */
    n=strlen(path);
    path[n++]='\\';
    memcpy(&path[n], name, length);
    if(_exists(path))
    {
	return; 		      /* found it already */
    }	
    n=0;
    p=0;
    do				      /* search each path */
    {
	while((c=envpath[n++]) && (c != ';'))
	{
	    path[p++]= (char) c;
	}
	if(path[p-1] != '\\')
	    path[p++]='\\';
	memcpy(&path[p], name, length);
	if(_exists(path))
        {
	    return;		      /* found it  */
	}
	p=0;
    } while (envpath[n-1]);
    path[0]=0;			      /* couldn't find file */
    return;
}

void sleep(unsigned seconds)
{
    _sleepTenths(seconds*10l);
}

static void call_test1(void)
{
    calloc(0, 0);
    free(NULL);
    malloc(0);
    realloc(NULL, 0);
    _ncalloc(0, 0);
    _nfree(NULL);
    _nmalloc(0);
    _nrealloc(NULL, 0);

    _msize(NULL);
    _memmax();
    _memavl();
    _heapchk();
    _heapset(0);
    _heapwalk(NULL);
    coreleft();
    _freect(0);

    _nheapchk();
    _nheapset(0);
    _nheapwalk(NULL);
    _nmsize(NULL);
    nearcoreleft();
}

static void call_test3(void)
{
    cgets(NULL);
    cputs(NULL);
    getch();
    getche();
    kbhit();
    putch(0);
    ungetch(0);
}

static void call_test4(void)
{
    chdir(NULL);
    getcurdir(0, NULL);
    getcwd(NULL, 0);
    _getdrive();
    mkdir(NULL);
    rmdir(NULL);

    getdisk();
    searchpath(NULL);
    setdisk(0);
}

static void call_test6(void)
{
    access(NULL, 0);
    chmod(NULL, 0);
    chsize(0, 0L);
}

static void call_test7(void)
{
    abs(0);
    acos(0.0);
    asin(0.0);
    atan(0.0);
    atan2(0.0, 0.0);
    atof(NULL);
    ceil(0.0);
    cos(0.0);
    cosh(0.0);
    exp(0.0);
    fabs(0.0);
    floor(0.0);
    fmod(0.0, 0.0);
    frexp(0.0, NULL);
    labs(0L);
    ldexp(0.0, 0);
    log(0.0);
    log10(0.0);
    modf(0.0, NULL);
    poly(0.0, 0, NULL);
    pow(0.0, 0.0);
    sin(0.0);
    sinh(0.0);
    sqrt(0.0);
    strtod(NULL, NULL);
    tan(0.0);
    tanh(0.0);
    matherr(NULL);
    hypot(0.0, 0.0);
    pow10(0);
    _fpreset();
}

static void call_test8(void)
{
    void *ptr=NULL;

    memccpy(ptr, ptr, 0, 0);
    memchr(ptr, 0, 0);
    memcmp(ptr, ptr, 0);
    memcpy(ptr, ptr, 0);
    memicmp(ptr, ptr, 0);
    memmove(ptr, ptr, 0);
    memset(ptr, 0, 0);
    movmem(ptr, ptr, 0);
    setmem(ptr, 0, 0);

    memwmove(ptr, ptr, 0);
    memwset(ptr, 0, 0);
    memwcpy(ptr, ptr, 0);
}

static void call_test9(void)
{
    signal(0, NULL);
    raise(0);
}

static void call_test10(void)
{
    fgetc(NULL);
    fputc(0, NULL);
    rename(NULL, NULL);
    unlink(NULL);
}

static void call_test11(void)
{
    delay(0);
    getenv(NULL);
    mblen(NULL, 0);
    mbtowc(NULL, NULL, 0);
    wctomb(NULL, 0);
    mbstowcs(NULL, NULL, 0);
    wcstombs(NULL, NULL, 0);
    ecvt(0.0, 0, NULL, NULL);
    _exit(0);
    fcvt(0.0, 0, NULL, NULL);
    gcvt(0.0, 0, NULL);
    itoa(0, NULL, 0);
    _lrotl(0L, 0);
    _lrotr(0L, 0);
    ltoa(0L, NULL, 0);
    _searchenv(NULL, NULL, NULL);
    _rotl(0, 0);
    _rotr(0, 0);
    swab(NULL, NULL, 0);
    ultoa(0L, NULL, 0);
}

static void call_test12(void)
{
    void *ptr=NULL;

    strcat(ptr, ptr);
    strcmp(ptr, ptr);
    strcpy(ptr, ptr);
    strlen(ptr);
    strset(ptr, 0);
    stpcpy(ptr, ptr);
    strchr(ptr, 0);
    strcoll(ptr, ptr);
    strxfrm(ptr, ptr, 0);
    strcspn(ptr, ptr);
    strdup(ptr);
    strerror(0);
    stricmp(ptr, ptr);
    strlwr(ptr);
    strncat(ptr, ptr, 0);
    strncmp(ptr, ptr, 0);
    strncpy(ptr, ptr, 0);
    strnicmp(ptr, ptr, 0);
    strnset(ptr, 0, 0);
    strpbrk(ptr, ptr);
    strrchr(ptr, 0);
    strrev(ptr);
    strspn(ptr, ptr);
    strstr(ptr, ptr);
    strtok(ptr, ptr);
    strupr(ptr);
}

static void call_test13(void)
{
    settime(NULL);
    gettime(NULL);
    setdate(NULL);
    getdate(NULL);
    utime(NULL, NULL);
    get_utime(0);
    _filetime(0, NULL);
}

