1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102 |
- /* OpenDoors Online Software Programming Toolkit
- * (C) Copyright 1991 - 1999 by Brian Pirie.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- *
- * File: ODSpawn.c
- *
- * Description: Implements the od_spawn...() functions for suspending this
- * program and executing a sub-program. Can be called by the
- * user explicitly, or invoked for sysop OS shell.
- *
- * Revisions: Date Ver Who Change
- * ---------------------------------------------------------------
- * Oct 13, 1994 6.00 BP New file header format.
- * Oct 21, 1994 6.00 BP Further isolated com routines.
- * Dec 09, 1994 6.00 BP Use new directory access functions.
- * Dec 13, 1994 6.00 BP Standardized coding style.
- * Dec 31, 1994 6.00 BP Remove #ifndef USEINLINE DOS code.
- * Jan 01, 1995 6.00 BP _waitdrain -> ODWaitDrain()
- * Aug 19, 1995 6.00 BP 32-bit portability.
- * Nov 11, 1995 6.00 BP Removed register keyword.
- * Nov 14, 1995 6.00 BP Added include of odscrn.h.
- * Nov 16, 1995 6.00 BP Removed oddoor.h, added odcore.h.
- * Nov 17, 1995 6.00 BP Use new input queue mechanism.
- * Nov 21, 1995 6.00 BP Ported to Win32.
- * Dec 30, 1995 6.00 BP Added ODCALL for calling convention.
- * Jan 23, 1996 6.00 BP Finished port to Win32.
- * Feb 19, 1996 6.00 BP Changed version number to 6.00.
- * Feb 23, 1996 6.00 BP Enable and test under Win32.
- * Feb 27, 1996 6.00 BP Store screen info in our own struct.
- * Mar 03, 1996 6.10 BP Begin version 6.10.
- * Mar 19, 1996 6.10 BP MSVC15 source-level compatibility.
- * Aug 10, 2003 6.23 SH *nix support - some functions not supported (Yet)
- */
- #define BUILDING_OPENDOORS
- #include <stdlib.h>
- #include <string.h>
- #include <stdio.h>
- #include <ctype.h>
- #include <time.h>
- #include <errno.h>
- #include "OpenDoor.h"
- #ifdef ODPLAT_NIX
- #include <signal.h>
- #include <sys/types.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #endif
- #include "ODCore.h"
- #include "ODGen.h"
- #include "ODCom.h"
- #include "ODPlat.h"
- #include "ODScrn.h"
- #include "ODInQue.h"
- #include "ODInEx.h"
- #include "ODUtil.h"
- #include "ODKrnl.h"
- #include "ODSwap.h"
- #ifdef ODPLAT_WIN32
- #include "ODFrame.h"
- #endif /* ODPLAT_WIN32 */
- #if defined(ODPLAT_WIN32) && defined(_MSC_VER)
- #undef P_WAIT
- #undef P_NOWAIT
- #include <process.h>
- #endif /* ODPLAT_WIN32 && _MSC_VER */
- #ifdef ODPLAT_DOS
- /* Local and global variables for memory swapping spawn routines. */
- 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])];
- /* Location function prototypes. */
- int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
- char *papszEnviron[]);
- int _spawnve(int nModeFlag, char *pszPath, char *papszArgs[],
- char * papszEnviron[]);
- static void savevect(void);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_NIX
- /* Location function prototypes. */
- int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
- char *papszEnviron[]);
- #endif /* ODPLAT_NIX */
- /* ----------------------------------------------------------------------------
- * od_spawn()
- *
- * Executes the specified command line, suspending OpenDoors operations while
- * the spawned-to program is running.
- *
- * Parameters: pszCommandLine - Command to execute along with any parameters.
- *
- * Return: TRUE on success, or FALSE on failure.
- */
- ODAPIDEF BOOL ODCALL od_spawn(const char *pszCommandLine)
- {
- #ifdef ODPLAT_DOS
- char *apszArgs[4];
- INT16 nReturnCode;
- /* Log function entry if running in trace mode. */
- TRACE(TRACE_API, "od_spawn()");
- *apszArgs=getenv("COMSPEC");
- apszArgs[1] = "/c";
- apszArgs[2] = pszCommandLine;
- apszArgs[3] = NULL;
-
- if(*apszArgs != NULL)
- {
- if((nReturnCode = od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL)) != -1
- || errno != ENOENT)
- {
- return(nReturnCode != -1);
- }
- }
- *apszArgs = "command.com";
- return(od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL) != -1);
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_WIN32
- char *pch;
- char *apszArgs[3];
- char szProgName[80];
- /* Build command and arguments list. */
- /* Build program name. */
- ODStringCopy(szProgName, pszCommandLine, sizeof(szProgName));
- pch = strchr(szProgName, ' ');
- if(pch != NULL) *pch = '\0';
- apszArgs[0] = szProgName;
- /* Build arguments. */
- pch = strchr(pszCommandLine, ' ');
- if(pch == NULL)
- {
- apszArgs[1] = NULL;
- }
- else
- {
- apszArgs[1] = pch + 1;
- apszArgs[2] = NULL;
- }
- /* Now, call od_spawnvpe(). */
- return(od_spawnvpe(P_WAIT, *apszArgs, apszArgs, NULL) != -1);
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_NIX
- sigset_t block;
- int retval;
- /* Suspend kernel */
- sigemptyset(&block);
- sigaddset(&block,SIGALRM);
- sigprocmask(SIG_BLOCK,&block,NULL);
- retval=system(pszCommandLine);
- /* Restore kernel */
- sigemptyset(&block);
- sigaddset(&block,SIGALRM);
- sigprocmask(SIG_UNBLOCK,&block,NULL);
- return(retval!=-1 && retval != 127);
- #endif
- }
- /* ----------------------------------------------------------------------------
- * od_spawnvpe()
- *
- * Executes the specified program, using the specified arguments and
- * environment variables, optionally suspending OpenDoors operations while
- * the spawned-to program is running.
- *
- * Parameters: nModeFlag - P_WAIT to for OpenDoors operations to be suspended
- * while the spawned-to program is running, or
- * P_NOWAIT if the calling program should continue to
- * run while the spawned-to program is running. In
- * non-multitasking environments, the only valid value
- * of this parameters is P_WAIT.
- *
- * pszPath - Complete path and filename of the program to
- * exectute.
- *
- * papszArg - Array of string pointers to command line arguments.
- *
- * papszEnv - Array of string pointers to environment variables.
- *
- * Return: -1 on failure or the spawned-to program's return value on
- * success.
- */
- ODAPIDEF INT16 ODCALL od_spawnvpe(INT16 nModeFlag, char *pszPath,
- char *papszArg[], char *papszEnv[])
- {
- INT16 nToReturn;
- time_t nStartUnixTime;
- DWORD dwQuotient;
- #ifdef ODPLAT_WIN32
- void *pWindow;
- #endif /* ODPLAT_WIN32 */
- #ifdef ODPLAT_DOS
- char *pszDir;
- BYTE *abtScreenBuffer;
- INT nDrive;
- tODScrnTextInfo TextInfo;
- #endif /* ODPLAT_DOS */
- /* Log function entry if running in trace mode. */
- TRACE(TRACE_API, "od_spawnvpe()");
- /* Initialize OpenDoors if it hasn't already been done. */
- if(!bODInitialized) od_init();
- #ifdef ODPLAT_DOS
- /* Ensure the nModeFlag is P_WAIT, which is the only valid value for */
- /* the MS-DOS version of OpenDoors. */
- if(nModeFlag != P_WAIT)
- {
- od_control.od_error = ERR_PARAMETER;
- return(-1);
- }
- /* Store current screen contents. */
- if((abtScreenBuffer = malloc(4000)) == NULL)
- {
- od_control.od_error = ERR_MEMORY;
- return(-1);
- }
- if((pszDir = malloc(256)) == NULL)
- {
- od_control.od_error = ERR_MEMORY;
- free(abtScreenBuffer);
- return(-1);
- }
- /* Store current display settings. */
- ODScrnGetTextInfo(&TextInfo);
- /* Set current output area to the full screen. */
- ODScrnSetBoundary(1,1,80,25);
- /* Store contents of entire screen. */
- ODScrnGetText(1, 1, 80, 25, (char *)abtScreenBuffer);
- /* Set the current display colour to grey on black. */
- ODScrnSetAttribute(0x07);
- /* Clear the screen if required. Otherwise, move the cursor to the */
- /* upper left corner of the screen. */
- if(od_control.od_clear_on_exit)
- {
- ODScrnClear();
- }
- else
- {
- ODScrnSetCursorPos(1, 1);
- }
- /* Store current directory. */
- strcpy(pszDir, "X:\\");
- pszDir[0] = 'A' + (nDrive = _getdrv());
- _getcd(0, (char *)pszDir + 3);
- #endif /* ODPLAT_DOS */
- /* Remember when spawned to program was executed. */
- nStartUnixTime = time(NULL);
- if(nModeFlag == P_WAIT)
- {
- /* Display the spawn message box under Win32. */
- #ifdef ODPLAT_WIN32
- pWindow = ODScrnShowMessage("Running sub-program...", 0);
- #endif /* ODPLAT_WIN32 */
- /* Wait for up to ten seconds for outbound buffer to drain. */
- ODWaitDrain(10000);
- #ifdef OD_MULTITHREADED
- /* Mutlithreaded versions of OpenDoors must shutdown the kernel */
- /* before closing the serial port. */
- ODKrnlShutdown();
- #endif /* OD_MULTITHREADED */
- /* Close serial port. */
- if(od_control.baud != 0)
- {
- #ifdef ODPLAT_WIN32
- /* Disable DTR response by the modem before closing the serial */
- /* port, if this is required. */
- ODInExDisableDTR();
- #endif /* ODPLAT_WIN32 */
- ODComClose(hSerialPort);
- }
- }
- /* Execute specified program with the specified arguments. */
- nToReturn = _spawnvpe(nModeFlag, pszPath, papszArg, papszEnv);
- if(nModeFlag == P_WAIT)
- {
- /* Re-open serial port. */
- if(od_control.baud != 0)
- {
- ODComOpen(hSerialPort);
- }
- #ifdef OD_MULTITHREADED
- /* Mutlithreaded versions of OpenDoors must shutdown the kernel */
- /* before closing the serial port, so reinitialize the kernel now. */
- ODKrnlInitialize();
- #endif /* OD_MULTITHREADED */
- if(!(bIsShell || od_control.od_spawn_freeze_time))
- {
- ODDWordDivide(&dwQuotient, NULL, time(NULL) - nStartUnixTime, 60L);
- od_control.user_timelimit -= (int)dwQuotient;
- }
- else
- {
- nNextTimeDeductTime += time(NULL) - nStartUnixTime;
- }
- /* Reset the time of the last input activity to the current time. */
- /* This will prevent an immediate inactity timeout, regardless of */
- /* how long the spawned-to program was active. */
- ODInQueueResetLastActivity(hODInputQueue);
- /* Clear inbound buffer. */
- od_clear_keybuffer();
- /* Remove the spawn message box under Win32. */
- #ifdef ODPLAT_WIN32
- ODScrnRemoveMessage(pWindow);
- #endif /* ODPLAT_WIN32 */
- }
- #ifdef ODPLAT_DOS
- /* Redisplay the door screen. */
- ODScrnPutText(1, 1, 80, 25, (char *)abtScreenBuffer);
- /* Restore cursor to old position. */
- ODScrnSetBoundary(TextInfo.winleft, TextInfo.wintop,
- TextInfo.winright, TextInfo.winbottom);
- ODScrnSetAttribute(TextInfo.attribute);
- ODScrnSetCursorPos(TextInfo.curx, TextInfo.cury);
- _setdrvcd(nDrive, pszDir);
- /* Free allocated space. */
- free(abtScreenBuffer);
- free(pszDir);
- #endif /* ODPLAT_DOS */
- /* Return appropriate value. */
- return(nToReturn);
- }
- #ifdef ODPLAT_DOS
- /* ----------------------------------------------------------------------------
- * _spawnvpe() *** PRIVATE FUNCTION ***
- *
- * Executes a child program in the MS-DOS environment, swapping the calling
- * program out of memory if enabled.
- *
- * Parameters: nModeFlag - Must be P_WAIT.
- *
- * pszPath - Name of program to execute.
- *
- * papszArgs - Array of command-line arguments.
- *
- * papszEnviron - Array of environment variables.
- *
- * Return: -1 on failure or the spawned-to program's return value on
- * success.
- */
- int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
- char *papszEnviron[])
- {
- char *e;
- char *p;
- char buf[80];
- int nReturnCode;
- _swappath = (char *)(strlen(od_control.od_swapping_path) == 0 ? NULL
- : (char *)od_control.od_swapping_path);
- _useems = od_control.od_swapping_noems;
- _swap = od_control.od_swapping_disable;
- if((nReturnCode=_spawnve(nModeFlag, pszPath, papszArgs, papszEnviron))!=-1
- || errno!=ENOENT || *pszPath=='\\' || *pszPath=='/'
- || *pszPath && *(pszPath+1)==':' || (e=getenv("PATH"))==NULL)
- {
- return(nReturnCode);
- }
- for (;;e++)
- {
- if((p=strchr(e,';'))!=NULL)
- {
- if(p-e > 66)
- {
- e=p;
- continue;
- }
- }
- else if(strlen(e)>66)
- {
- return( -1 );
- }
- p=buf;
- while(*e && *e!=';') *p++=*e++;
- if(p>buf)
- {
- if(*(p-1)!='\\' && *(p-1)!='/') *p++ = '\\';
- strcpy(p,pszPath);
- if((nReturnCode=_spawnve(nModeFlag,buf,papszArgs,papszEnviron))!=-1 || errno!=ENOENT)
- {
- return(nReturnCode);
- }
- }
- if(*e=='\0') return(-1);
- }
- }
- /* ----------------------------------------------------------------------------
- * addvect() *** PRIVATE FUNCTION ***
- *
- * Adds a vector to the vector table.
- *
- * Parameters: number - The vector number.
- *
- * opcode - Vector flags.
- *
- * Return: -1 on failure, or 0 on success.
- */
- int addvect(int number, int opcode)
- {
- 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 )
- _getvect( number, &vect->vseg, &vect->voff );
- return( 0 );
- }
- errno = ENOMEM;
- return( -1 );
- }
- /* ----------------------------------------------------------------------------
- * savevect() *** PRIVATE FUNCTION ***
- *
- * Saves current vector in vector table.
- *
- * Parameters: none
- *
- * Return: void
- */
- static void savevect(void)
- {
- VECTOR *vect1 = vectab1;
- VECTOR *vect2 = vectab2;
- while ( vect1->flag != 3 )
- {
- if ( vect1->flag != 2 )
- {
- vect2->number = vect1->number;
- vect2->flag = CURRENT;
- _getvect( vect1->number, &vect2->vseg, &vect2->voff );
- }
- else
- vect2->flag = 2; /* free */
- vect1++;
- vect2++;
- }
- vect2->flag = 3; /* end */
- }
- /* ----------------------------------------------------------------------------
- * testfile() *** PRIVATE FUNCTION ***
- *
- * Tests swap file.
- *
- * Parameters: p - Path.
- *
- * file - File name.
- *
- * handle - File handle.
- *
- * Return: 1 on failure.
- */
- static int testfile(char *p, char *file, int *handle)
- {
- unsigned int startno = tempno;
- int nDrive = ( *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 nReturnCode; /* return code */
- unsigned long dwQuotient;
- unsigned long remainder;
- if ( file + 2 == p )
- {
- *p++ = '\\';
- if ( _getcd( nDrive, p )) /* get current directory */
- return( 1 ); /* invalid drive */
- p = file + strlen( file );
- }
- else
- {
- *p = '\0';
- if ( ODFileAccessMode( 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;
- if ( _dskspace( nDrive, &bytes, &clusters ) != 0 )
- return( 1 ); /* invalid drive */
- ODDWordDivide(&dwQuotient, &remainder, swapsize, bytes);
- need = (int)dwQuotient;
- if ( remainder )
- 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 */
- ltoa(( long )tempno, p, 10 );
- }
- while ( !ODFileAccessMode( 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.
- */
- if (( nReturnCode = _create( file, handle )) == 80 )
- goto again;
- return( nReturnCode );
- }
- /* ----------------------------------------------------------------------------
- * tempfile() *** PRIVATE FUNCTION ***
- *
- * Creates a temporary swap file.
- *
- * Parameters: file - Filename
- *
- * handle - Handle to file.
- *
- * Return: 0 on success, or 1 on failure.
- */
- static int tempfile(char *file, int *handle)
- {
- char *s = _swappath;
- char *p = file;
- if ( s )
- {
- for ( ;; s++ )
- {
- while ( *s && *s != ';' )
- *p++ = *s++;
- if ( p > file )
- {
- if ( p == file + 1 || file[ 1 ] != ':' )
- {
- memmove( file + 2, file, ( int )( p - file ));
- *file = ( char )( _getdrv() + 'a' );
- file[ 1 ] = ':';
- p += 2;
- }
- if ( testfile( p, file, handle ) == 0 )
- return( 0 );
- p = file;
- }
- if ( *s == '\0' )
- break;
- }
- }
- else /* try the current directory */
- {
- *p++ = ( char )( _getdrv() + 'a' );
- *p++ = ':';
- if ( testfile( p, file, handle ) == 0 )
- return( 0 );
- }
- errno = EACCES;
- return( 1 );
- }
- /* ----------------------------------------------------------------------------
- * cmdenv() *** PRIVATE FUNCTION ***
- *
- * Constructs environment.
- *
- * Parameters: papszArgs - Array of arguments.
- *
- * papszEnviron - Array of environment variables to add.
- *
- * command - The command specified.
- *
- * env - Pointer to environment.
- *
- * memory - Allocated memory.
- *
- * Return: Environment length.
- */
- static int cmdenv(char **papszArgs, char **papszEnviron, char *command,
- char **env, char **memory)
- {
- char **vp;
- unsigned int elen = 0; /* environment length */
- char *p;
- int cnt;
- int len;
- /* construct environment */
- if ( papszEnviron == NULL )
- {
- char far *parent_env;
- char far *env_ptr;
- int nul_count;
- ASM mov ah, 0x62
- ASM int 0x21
- ASM push es
- ASM mov es, bx
- ASM mov ax, es:[0x2c]
- ASM pop es
- ASM mov word ptr parent_env, 0
- ASM mov word ptr parent_env + 2, ax
- env_ptr = parent_env;
- nul_count = 0;
- while(nul_count < 2)
- {
- if(*env_ptr)
- {
- nul_count = 0;
- }
- else
- {
- ++nul_count;
- }
- ++env_ptr;
- ++elen;
- }
- 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;
- len = elen;
- while(len--)
- {
- *p++ = *parent_env++;
- }
- }
- else
- {
- for ( vp = papszEnviron; *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;
- for ( vp = papszEnviron; *vp; vp++ )
- p = strchr( strcpy( p, *vp ), '\0' ) + 1;
- *p = '\0'; /* final element */
- }
- /* construct command-line */
- vp = papszArgs;
- p = command + 1;
- cnt = 0;
- if (vp!=NULL && *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 */
- }
- /* ----------------------------------------------------------------------------
- * doxspawn() *** PRIVATE FUNCTION ***
- *
- * Performs spawn using memory swapping.
- *
- * Parameters: pszPath - Path to command to exectute.
- *
- * papszArg - Array of arugments.
- *
- * papszEnviron - Pointer to the environment.
- *
- * Return: 0 on success, or -1 on failure.
- */
- static int doxspawn(char *pszPath, char *papszArgs[], char *papszEnviron[])
- {
- int nReturnCode = 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( papszArgs, papszEnviron, command, &env, &memory )) == -1 )
- return( -1 );
- if ( _swap == 0 )
- {
- if ( _useems == 0 )
- {
- if ( ems == 2 )
- ems = _chkems( "EMMXXXX0", &mapsize );
- if ( ems == 0 && ( mapbuf = malloc( mapsize )) == NULL )
- {
- errno = ENOMEM;
- free( memory );
- return( -1 );
- }
- }
- if (( nReturnCode = _xsize( _psp, &swapsize, &totalsize )) == 0 )
- {
- if ( _required == 0 || totalsize - swapsize - 272
- < (long)ODDWordShiftLeft(( long )_required , 10 ))
- {
- if ( ems == 0 && _useems == 0 )
- {
- pages = ( int )ODDWordShiftRight( swapsize , 14);
- if ((long)ODDWordShiftLeft(( long )pages , 14 ) < swapsize )
- pages++;
- if ( _savemap( mapbuf ) == 0 &&
- _getems( pages, &handle ) == 0 )
- *file = '\0'; /* use EMS */
- else if ( tempfile( file, &handle ) != 0 )
- nReturnCode = -1; /* don't do xspawn */
- }
- else if ( tempfile( file, &handle ) != 0 )
- nReturnCode = -1; /* don't do xspawn */
- }
- else
- doswap = 1; /* don't do swap */
- }
- else
- {
- errno = errtab[ nReturnCode ];
- nReturnCode = -1; /* don't do xspawn */
- }
- }
- else
- doswap = 1; /* don't do swap */
- if ( nReturnCode == 0 )
- {
- savevect(); /* save current vectors */
- nReturnCode = _xspawn( pszPath, command, env, vectab1, doswap, elen, file,
- handle );
- _setvect( vectab2 ); /* restore saved vectors */
- if ( nReturnCode == 0 )
- nReturnCode = _getrc(); /* get child return code */
- else
- {
- errno = errtab[ nReturnCode ];
- nReturnCode = -1;
- }
- /*
- * If EMS was used, restore the page-mapping state of the expanded
- * memory hardware.
- */
- if ( doswap == 0 && *file == '\0' && _restmap( mapbuf ) != 0 )
- {
- errno = EACCES;
- nReturnCode = -1;
- }
- }
- if ( mapbuf )
- free( mapbuf );
- free( memory );
- return( nReturnCode );
- }
- /* ----------------------------------------------------------------------------
- * _spawnve() *** PRIVATE FUNCTION ***
- *
- * Performs a spawn.
- *
- * Parameters: nModeFlag - Must be P_WAIT
- *
- * pszPath - Command to execute.
- *
- * papszArgs - Command line arguments.
- *
- * papszEnviron - Pointer to environment.
- *
- * Return: void
- */
- int _spawnve(int nModeFlag, char *pszPath, char *papszArgs[],
- char * papszEnviron[])
- {
- char *p;
- char *s;
- int nReturnCode = -1;
- char buf[ 80 ];
- if ( nModeFlag != P_WAIT )
- {
- errno = EINVAL;
- return( -1 );
- }
- p = strrchr( pszPath, '\\' );
- s = strrchr( pszPath, '/' );
- if ( p == NULL && s == NULL )
- p = pszPath;
- else if ( p == NULL || s > p )
- p = s;
- if ( strchr( p, '.' ))
- {
- if ( !ODFileAccessMode( pszPath, 0 ))
- nReturnCode = doxspawn( pszPath, papszArgs, papszEnviron );
- /* If file not found, access will have set errno to ENOENT. */
- }
- else
- {
- strcpy( buf, pszPath );
- strcat( buf, ".com" );
- if ( !ODFileAccessMode( buf, 0 ))
- nReturnCode = doxspawn( buf, papszArgs, papszEnviron );
- else
- {
- strcpy( strrchr( buf, '.' ), ".exe" );
- if ( !ODFileAccessMode( buf, 0 ))
- nReturnCode = doxspawn( buf, papszArgs, papszEnviron );
- /* If file not found, access will have set errno to ENOENT. */
- }
- }
- return( nReturnCode );
- }
- #endif /* ODPLAT_DOS */
- #ifdef ODPLAT_NIX
- /* ----------------------------------------------------------------------------
- * _spawnvpe() *** PRIVATE FUNCTION ***
- *
- * Executes a child program in the *nix environment.
- *
- * Parameters: nModeFlag - Must be P_WAIT or P_NOWAIT
- *
- * pszPath - Name of program to execute.
- *
- * papszArgs - Array of command-line arguments.
- *
- * papszEnviron - Array of environment variables.
- *
- * Return: -1 on failure or the spawned-to program's return value on
- * success.
- */
- int _spawnvpe(int nModeFlag, char *pszPath, char *papszArgs[],
- char *papszEnviron[])
- {
- pid_t child;
- int status;
- pid_t wret;
- struct sigaction act;
- child=fork();
- if(nModeFlag == P_WAIT) {
- /* require wait for child */
- act.sa_handler=SIG_IGN;
- sigemptyset(&(act.sa_mask));
- act.sa_flags=SA_NOCLDSTOP;
- sigaction(SIGCHLD,&act,NULL);
- }
- else {
- /* Ignore SIGCHLD for backgrounded spawned processes */
- act.sa_handler=SIG_IGN;
- sigemptyset(&(act.sa_mask));
- act.sa_flags=SA_NOCLDSTOP|SA_NOCLDWAIT;
- sigaction(SIGCHLD,&act,NULL);
- }
- if(!child) {
- /* Do the exec stuff here */
- execve(pszPath,papszArgs,papszEnviron);
- exit(-1); /* this should never happen! */
- }
- if(nModeFlag == P_WAIT) {
- wret=waitpid(child,&status,0);
- if(WIFEXITED(status)) {
- return(WEXITSTATUS(status));
- }
- return(-1);
- }
- return(0);
- }
- #endif /* ODPLAT_NIX */
|