home *** CD-ROM | disk | FTP | other *** search
- /*
- * XSPAWN
- * Version 1.33
- * (C) Copyright 1990 Whitney Software, Inc.
- * All Rights Reserved
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <string.h>
- #ifdef LATTICE
- #include <dos.h>
- #else
- #include <io.h>
- #endif
- #include "xspawnp.h"
-
- typedef struct _vector
- {
- char number; /* vector number */
- char flag; /* 0-CURRENT, 1-IRET, 2-free, 3-end */
- unsigned int vseg; /* vector segment */
- unsigned int voff; /* vector offset */
- }
- VECTOR;
-
- static void savevect( void );
- static int testfile( char *, char *, int * );
- static int tempfile( char *, int * );
- static int cmdenv( char **, char **, char *, char **, char ** );
- static int doxspawn( char *, char **, char ** );
- #ifdef LATTICE
- extern int __xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
- extern int __xsize( unsigned int, long *, long * );
- extern int __chkems( char *, int * );
- extern int __savemap( char * );
- extern int __restmap( char * );
- extern int __getems( int, int * );
- extern int __dskspace( int, unsigned int *, unsigned int * );
- extern int __getrc( void );
- extern int __create( char *, int * );
- extern int __getcd( int, char * );
- extern int __getdrv( void );
- extern void __getvect( int, unsigned int *, unsigned int * );
- extern void __setvect( VECTOR * );
- #else
- extern int _xspawn( char *, char *, char *, VECTOR *, int, int, char *, int );
- extern int _xsize( unsigned int, long *, long * );
- extern int _chkems( char *, int * );
- extern int _savemap( char * );
- extern int _restmap( char * );
- extern int _getems( int, int * );
- extern int _dskspace( int, unsigned int *, unsigned int * );
- extern int _getrc( void );
- extern int _create( char *, int * );
- extern int _getcd( int, char * );
- extern int _getdrv( void );
- extern void _getvect( int, unsigned int *, unsigned int * );
- extern void _setvect( VECTOR * );
- #endif
-
- #ifdef LATTICE
- extern char **environ;
- #endif
-
- int _swap = 0; /* if 0, do swap */
- char *_swappath = NULL; /* swap path */
- int _useems = 0; /* if 0, use EMS */
- int _required = 0; /* child memory requirement in K */
- static long swapsize; /* swap size requirement in bytes */
- static int ems = 2; /* if 0, EMS is available */
- static int mapsize; /* size of page map information */
- static unsigned int tempno = 1; /* tempfile number */
- static char errtab[] = /* error table */
- {
- 0,
- EINVAL,
- ENOENT,
- ENOENT,
- EMFILE,
- EACCES,
- EBADF,
- ENOMEM,
- ENOMEM,
- ENOMEM,
- E2BIG,
- ENOEXEC,
- EINVAL,
- EINVAL,
- -1,
- EXDEV,
- EACCES,
- EXDEV,
- ENOENT,
- -1
- };
- static VECTOR vectab1[] =
- {
- 0, 1, 0, 0,
- 1, 1, 0, 0,
- 2, 1, 0, 0,
- 3, 1, 0, 0,
- 0x1B, 1, 0, 0,
- 0x23, 1, 0, 0,
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 2, 0, 0, /* free record */
- 0, 3, 0, 0 /* end record */
- };
- static VECTOR vectab2[ sizeof vectab1 / sizeof vectab1[ 0 ]];
-
- int addvect( number, opcode )
- int number;
- int opcode;
- {
- register VECTOR *vect = vectab1;
-
- if ( number < 0 || number > 0xFF ||
- ( opcode != IRET && opcode != CURRENT ))
- {
- errno = EINVAL;
- return( -1 );
- }
-
- /* see if number is already in table */
- while ( vect->flag != 3 && ( vect->flag == 2 ||
- vect->number != ( char )number ))
- {
- vect++;
- }
-
- if ( vect->flag == 3 )
- {
- /* look for a free record */
- vect = vectab1;
- while ( vect->flag == CURRENT || vect->flag == IRET )
- vect++;
- }
-
- if ( vect->flag != 3 )
- {
- vect->number = ( char )number;
- vect->flag = ( char )opcode;
- if ( opcode == CURRENT )
- #ifdef LATTICE
- __getvect( number, &vect->vseg, &vect->voff );
- #else
- _getvect( number, &vect->vseg, &vect->voff );
- #endif
- return( 0 );
- }
-
- errno = ENOMEM;
- return( -1 );
- }
-
- static void savevect()
- {
- register VECTOR *vect1 = vectab1;
- register VECTOR *vect2 = vectab2;
-
- while ( vect1->flag != 3 )
- {
- if ( vect1->flag != 2 )
- {
- vect2->number = vect1->number;
- vect2->flag = CURRENT;
- #ifdef LATTICE
- __getvect( vect1->number, &vect2->vseg, &vect2->voff );
- #else
- _getvect( vect1->number, &vect2->vseg, &vect2->voff );
- #endif
- }
- else
- vect2->flag = 2; /* free */
- vect1++;
- vect2++;
- }
- vect2->flag = 3; /* end */
- }
-
- static int testfile( p, file, handle )
- register char *p;
- register char *file;
- int *handle;
- {
- unsigned int startno = tempno;
- int drive = ( *file | 32 ) - 96; /* a = 1, b = 2, etc. */
- int root;
- unsigned int bytes; /* bytes per cluster */
- unsigned int clusters; /* free clusters */
- int need; /* clusters needed for swap file */
- int rc; /* return code */
-
- if ( file + 2 == p )
- {
- *p++ = '\\';
- #ifdef LATTICE
- if ( __getcd( drive, p )) /* get current directory */
- #else
- if ( _getcd( drive, p )) /* get current directory */
- #endif
- return( 1 ); /* invalid drive */
- p = file + strlen( file );
- }
- else
- {
- *p = '\0';
- if ( access( file, 0 ))
- return( 1 ); /* path does not exist */
- }
- if ( *( p - 1 ) != '\\' && *( p - 1 ) != '/' )
- *p++ = '\\';
- if ( p - file == 3 )
- root = 1; /* is root directory */
- else
- root = 0; /* is not root directory */
- strcpy( p, "swp" );
- p += 3;
-
- #ifdef LATTICE
- if ( __dskspace( drive, &bytes, &clusters ) != 0 )
- #else
- if ( _dskspace( drive, &bytes, &clusters ) != 0 )
- #endif
- return( 1 ); /* invalid drive */
- need = ( int )( swapsize / bytes );
- if ( swapsize % bytes )
- need++;
- if ( root == 0 ) /* if subdirectory */
- need++; /* in case the directory needs space */
- if ( clusters < ( unsigned int )need )
- return( 1 ); /* insufficient free disk space */
-
- do
- {
- again: tempno = ( ++tempno ) ? tempno : 1;
- if ( tempno == startno )
- return( 1 ); /* extremely unlikely */
- #ifdef LATTICE
- stcu_d( p, tempno );
- #else
- ltoa(( long )tempno, p, 10 );
- #endif
- }
- while ( !access( file, 0 ));
-
- /*
- * The return code from _create will equal 80 if the user is running DOS 3.0
- * or above and the file was created by another program between the access
- * call and the _create call.
- */
-
- #ifdef LATTICE
- if (( rc = __create( file, handle )) == 80 )
- #else
- if (( rc = _create( file, handle )) == 80 )
- #endif
- goto again;
- return( rc );
- }
-
- static int tempfile( file, handle )
- char *file;
- int *handle;
- {
- register char *s = _swappath;
- register char *p = file;
-
- if ( s )
- {
- for ( ;; s++ )
- {
- while ( *s && *s != ';' )
- *p++ = *s++;
- if ( p > file )
- {
- if ( p == file + 1 || file[ 1 ] != ':' )
- {
- #ifdef MSC4
- memcpy( file + 2, file, ( int )( p - file ));
- #else
- memmove( file + 2, file, ( int )( p - file ));
- #endif
- #ifdef LATTICE
- *file = ( char )( __getdrv() + 'a' );
- #else
- *file = ( char )( _getdrv() + 'a' );
- #endif
- file[ 1 ] = ':';
- p += 2;
- }
- if ( testfile( p, file, handle ) == 0 )
- return( 0 );
- p = file;
- }
- if ( *s == '\0' )
- break;
- }
- }
- else /* try the current directory */
- {
- #ifdef LATTICE
- *p++ = ( char )( __getdrv() + 'a' );
- #else
- *p++ = ( char )( _getdrv() + 'a' );
- #endif
- *p++ = ':';
- if ( testfile( p, file, handle ) == 0 )
- return( 0 );
- }
-
- errno = EACCES;
- return( 1 );
- }
-
- static int cmdenv( argv, envp, command, env, memory )
- char **argv;
- char **envp;
- char *command;
- char **env;
- char **memory;
- {
- register char **vp;
- unsigned int elen = 0; /* environment length */
- char *p;
- int cnt;
- int len;
-
- /* construct environment */
-
- if ( envp == NULL )
- envp = environ;
-
- if ( envp )
- {
- for ( vp = envp; *vp; vp++ )
- {
- elen += strlen( *vp ) + 1;
- if ( elen > 32766 ) /* 32K - 2 */
- {
- errno = E2BIG;
- return( -1 );
- }
- }
- }
-
- if (( p = malloc( ++elen + 15 )) == NULL )
- {
- errno = ENOMEM;
- return( -1 );
- }
- *memory = p;
-
- *( unsigned int * )&p = *( unsigned int * )&p + 15 & ~15;
- *env = p;
-
- if ( envp )
- {
- for ( vp = envp; *vp; vp++ )
- p = strchr( strcpy( p, *vp ), '\0' ) + 1;
- }
-
- *p = '\0'; /* final element */
-
- /* construct command-line */
-
- vp = argv;
- p = command + 1;
- cnt = 0;
-
- if ( *vp )
- {
- while ( *++vp )
- {
- *p++ = ' ';
- cnt++;
- len = strlen( *vp );
- if ( cnt + len > 125 )
- {
- errno = E2BIG;
- free( *memory );
- return( -1 );
- }
- strcpy( p, *vp );
- p += len;
- cnt += len;
- }
- }
-
- *p = '\r';
- *command = ( char )cnt;
-
- return(( int )elen ); /* return environment length */
- }
-
- static int doxspawn( path, argv, envp )
- char *path; /* file to be executed */
- char *argv[]; /* array of pointers to arguments */
- char *envp[]; /* array of pointers to environment strings */
- {
- register int rc = 0; /* assume do xspawn */
- int doswap = 0; /* assume do swap */
- int elen; /* environment length */
- char *memory;
- char *env; /* environment */
- char command[ 128 ]; /* command-line */
- long totalsize; /* parent and free memory in bytes */
- int handle;
- int pages;
- char file[ 79 ];
- char *mapbuf = NULL; /* buffer for map information */
-
- /* construct the command-line and the environment */
- if (( elen = cmdenv( argv, envp, command, &env, &memory )) == -1 )
- return( -1 );
-
- if ( _swap == 0 )
- {
- if ( _useems == 0 )
- {
- if ( ems == 2 )
- #ifdef LATTICE
- ems = __chkems( "EMMXXXX0", &mapsize );
- #else
- ems = _chkems( "EMMXXXX0", &mapsize );
- #endif
- if ( ems == 0 && ( mapbuf = malloc( mapsize )) == NULL )
- {
- errno = ENOMEM;
- free( memory );
- return( -1 );
- }
- }
- #ifdef LATTICE
- if (( rc = __xsize(( unsigned int )(( unsigned long )_PSP >> 16 ),
- &swapsize, &totalsize )) == 0 )
- #else
- if (( rc = _xsize( _psp, &swapsize, &totalsize )) == 0 )
- #endif
- {
- if ( _required == 0 ||
- totalsize - swapsize - 272 < (( long )_required << 10 ))
- {
- if ( ems == 0 && _useems == 0 )
- {
- pages = ( int )( swapsize >> 14 );
- if ((( long )pages << 14 ) < swapsize )
- pages++;
- #ifdef LATTICE
- if ( __savemap( mapbuf ) == 0 &&
- __getems( pages, &handle ) == 0 )
- #else
- if ( _savemap( mapbuf ) == 0 &&
- _getems( pages, &handle ) == 0 )
- #endif
- *file = '\0'; /* use EMS */
- else if ( tempfile( file, &handle ) != 0 )
- rc = -1; /* don't do xspawn */
- }
- else if ( tempfile( file, &handle ) != 0 )
- rc = -1; /* don't do xspawn */
- }
- else
- doswap = 1; /* don't do swap */
- }
- else
- {
- errno = errtab[ rc ];
- rc = -1; /* don't do xspawn */
- }
- }
- else
- doswap = 1; /* don't do swap */
-
- if ( rc == 0 )
- {
- savevect(); /* save current vectors */
- #ifdef LATTICE
- rc = __xspawn( path, command, env, vectab1, doswap, elen, file,
- handle );
- #else
- rc = _xspawn( path, command, env, vectab1, doswap, elen, file,
- handle );
- #endif
- #ifdef LATTICE
- __setvect( vectab2 ); /* restore saved vectors */
- #else
- _setvect( vectab2 ); /* restore saved vectors */
- #endif
- if ( rc == 0 )
- #ifdef LATTICE
- rc = __getrc(); /* get child return code */
- #else
- rc = _getrc(); /* get child return code */
- #endif
- else
- {
- errno = errtab[ rc ];
- rc = -1;
- }
- /*
- * If EMS was used, restore the page-mapping state of the expanded
- * memory hardware.
- */
- #ifdef LATTICE
- if ( doswap == 0 && *file == '\0' && __restmap( mapbuf ) != 0 )
- #else
- if ( doswap == 0 && *file == '\0' && _restmap( mapbuf ) != 0 )
- #endif
- {
- errno = EACCES;
- rc = -1;
- }
- }
-
- if ( mapbuf )
- free( mapbuf );
- free( memory );
- return( rc );
- }
-
- int xspawnve( modeflag, path, argv, envp )
- int modeflag; /* execution mode for parent process */
- register char *path; /* file to be executed */
- char *argv[]; /* array of pointers to arguments */
- char *envp[]; /* array of pointers to environment strings */
- {
- register char *p;
- char *s;
- int rc = -1;
- char buf[ 80 ];
-
- if ( modeflag != P_WAIT )
- {
- errno = EINVAL;
- return( -1 );
- }
-
- p = strrchr( path, '\\' );
- s = strrchr( path, '/' );
- if ( p == NULL && s == NULL )
- p = path;
- else if ( p == NULL || s > p )
- p = s;
-
- if ( strchr( p, '.' ))
- {
- if ( !access( path, 0 ))
- rc = doxspawn( path, argv, envp );
- /* If file not found, access will have set errno to ENOENT. */
- }
- else
- {
- strcpy( buf, path );
- strcat( buf, ".com" );
- if ( !access( buf, 0 ))
- rc = doxspawn( buf, argv, envp );
- else
- {
- strcpy( strrchr( buf, '.' ), ".exe" );
- if ( !access( buf, 0 ))
- rc = doxspawn( buf, argv, envp );
- /* If file not found, access will have set errno to ENOENT. */
- }
- }
-
- return( rc );
- }