/*--------------------------------------------------------------------------*/ /* */ /* */ /* ------------ Bit-Bucket Software, Co. */ /* \ 10001101 / Writers and Distributors of */ /* \ 011110 / Freely Available Software. */ /* \ 1011 / */ /* ------ */ /* */ /* (C) Copyright 1987-96, Bit Bucket Software Co. */ /* */ /* This module was originally written by Bob Hartman */ /* */ /* BinkleyTerm "Spawn" module */ /* */ /* */ /* For complete details of the licensing restrictions, please refer */ /* to the License agreement, which is published in its entirety in */ /* the MAKEFILE and BT.C, and also contained in the file LICENSE.260. */ /* */ /* USE OF THIS FILE IS SUBJECT TO THE RESTRICTIONS CONTAINED IN THE */ /* BINKLEYTERM LICENSING AGREEMENT. IF YOU DO NOT FIND THE TEXT OF */ /* THIS AGREEMENT IN ANY OF THE AFOREMENTIONED FILES, OR IF YOU DO */ /* NOT HAVE THESE FILES, YOU SHOULD IMMEDIATELY CONTACT BIT BUCKET */ /* SOFTWARE CO. AT ONE OF THE ADDRESSES LISTED BELOW. IN NO EVENT */ /* SHOULD YOU PROCEED TO USE THIS FILE WITHOUT HAVING ACCEPTED THE */ /* TERMS OF THE BINKLEYTERM LICENSING AGREEMENT, OR SUCH OTHER */ /* AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO. */ /* */ /* */ /* You can contact Bit Bucket Software Co. at any one of the following */ /* addresses: */ /* */ /* Bit Bucket Software Co. FidoNet 1:104/501, 1:343/491 */ /* P.O. Box 460398 AlterNet 7:42/1491 */ /* Aurora, CO 80046 BBS-Net 86:2030/1 */ /* Internet f491.n343.z1.fidonet.org */ /* */ /* Please feel free to contact us at any time to share your comments about */ /* our software and/or licensing policies. */ /* */ /*--------------------------------------------------------------------------*/ /* Include this file before any other includes or defines! */ #include "includes.h" #ifdef DOS16 /* Include MOVEAPI file if this is C7 or C8 under DOS. */ #ifdef MOVE_OVERLAYS #include <../source/move/moveapi.h> #endif /* We now use Thomas Wagner's EXEC module to do our swapping. There's probably no good reason why we can't just hack our code to work with his as distributed. We'll put that on the wishlist. For now, we hacked his and you'll find the appropriate excerpts below. EXEC.H: EXEC function with memory swap - Main function header file. Public domain software by Thomas Wagner Ferrari electronic GmbH Beusselstrasse 27 D-1000 Berlin 21 Germany */ extern int do_exec (char *xfn, char *pars, int spawn, unsigned needed, char **envp); /* The EXEC function. Parameters: xfn is a string containing the name of the file to be executed. pars The program parameters. spawn If 0, the function will terminate after the EXECed program returns, the function will not return. NOTE: If the program file is not found, the function will always return with the appropriate error code, even if 'spawn' is 0. If non-0, the function will return after executing the program. If necessary (see the "needed" parameter), memory will be swapped out before executing the program. For swapping, spawn must contain a combination of the following flags: USE_EMS (0x01) - allow EMS swap USE_XMS (0x02) - allow XMS swap USE_FILE (0x04) - allow File swap The order of trying the different swap methods can be controlled with one of the flags EMS_FIRST (0x00) - EMS, XMS, File (default) XMS_FIRST (0x10) - XMS, EMS, File If swapping is to File, the attribute of the swap file can be set to "hidden", so users are not irritated by strange files appearing out of nowhere with the flag HIDE_FILE (0x40) - create swap file as hidden and the behaviour on Network drives can be changed with NO_PREALLOC (0x100) - don't preallocate CHECK_NET (0x200) - don't preallocate if file on net. This checking for Network is mainly to compensate for a strange slowdown on Novell networks when preallocating a file. You can either set NO_PREALLOC to avoid allocation in any case, or let the prep_swap routine decide whether to do preallocation or not depending on the file being on a network drive (this will only work with DOS 3.1 or later). needed The memory needed for the program in paragraphs (16 Bytes). If not enough memory is free, the program will be swapped out. Use 0 to never swap, 0xffff to always swap. If 'spawn' is 0, this parameter is irrelevant. envp The environment to be passed to the spawned program. If this parameter is NULL, a copy of the parent's environment is used (i.e. 'putenv' calls have no effect). If non-NULL, envp must point to an array of pointers to strings, terminated by a NULL pointer (the standard variable 'environ' may be used). Return value: 0x0000..00FF: The EXECed Program's return code 0x0101: Error preparing for swap: no space for swapping 0x0102: Error preparing for swap: program too low in memory 0x0200: Program file not found 0x03xx: DOS-error-code xx calling EXEC 0x0400: Error allocating environment buffer 0x0500: Swapping requested, but prep_swap has not been called or returned an error. 0x0501: MCBs don't match expected setup 0x0502: Error while swapping out */ /* Return codes (only upper byte significant) */ #define RC_PREPERR 0x0100 #define RC_NOFILE 0x0200 #define RC_EXECERR 0x0300 #define RC_ENVERR 0x0400 #define RC_SWAPERR 0x0500 /* Swap method and option flags */ #define USE_EMS 0x01 #define USE_XMS 0x02 #define USE_FILE 0x04 #define EMS_FIRST 0x00 #define XMS_FIRST 0x10 #define HIDE_FILE 0x40 #define NO_PREALLOC 0x100 #define CHECK_NET 0x200 #define USE_ALL (USE_EMS | USE_XMS | USE_FILE) #endif void b_spawn (char *cmd_str) { char this_dir[80]; #ifdef DOS16 char *command; char *p; #ifndef __TURBOC__ unsigned j; #endif /* ifndef __TURBOC__ */ #ifdef __ZTC__ char **environ; #endif #else /* ifdef DOS16 */ char *comspec; #endif /* ifdef DOS16 */ #ifndef UCT_DIFFERENTIAL if (saved_TZ != NULL) { (void) putenv (saved_TZ); tzset (); } #endif /* Save where we are in the status and cost logs */ if (status_log != NULL) { (void) fflush (status_log); (void) real_flush (fileno (status_log)); } if (cost_log != NULL) { (void) fflush (cost_log); (void) real_flush (fileno (cost_log)); } need_update = 0; /* Save where we are */ (void) getcwd (this_dir, 79); #ifndef DOS16 if (cmd_str) system (cmd_str); else { comspec = getenv ("COMSPEC"); if (comspec) spawnlp (P_WAIT, comspec, comspec, NULL); } #ifdef OS_2 DosSelectDisk ((USHORT) (*this_dir - 'A' + 1)); #endif #ifdef _WIN32 _chdrive ((int) (*this_dir - 'A' + 1)); #endif chdir (this_dir); #else /* ifndef DOS16 */ if ((p = getenv ("COMSPEC")) == NULL) p = "COMMAND.COM"; #ifdef __ZTC__ environ = NULL; #endif if (swapdir == NULL) { if (cmd_str != NULL) (void) system (cmd_str); else (void) spawnlp (P_WAIT, p, p, NULL); } else { #ifdef MOVE_OVERLAYS _movepause (); #endif if (cmd_str != NULL) { command = calloc (1, strlen (cmd_str) + 4); if (command != NULL) { (void) strcpy (command, "/c "); (void) strcat (command, cmd_str); (void) do_exec (p, command, USE_ALL, 0xffff, environ); free (command); } } else (void) do_exec (p, "", USE_ALL, 0xffff, environ); #ifdef MOVE_OVERLAYS _moveresume (); #endif } /* Go back to the proper directory */ #ifdef __TURBOC__ setdisk ((unsigned) (this_dir[0] - 'A')); #else /* __TURBOC__ */ _dos_setdrive ((unsigned) ((int) this_dir[0] - 'A' + 1), &j); #endif /* __TURBOC__ */ (void) chdir (this_dir); #endif /* DOS16 */ #ifndef UCT_DIFFERENTIAL if (saved_TZ != NULL) { (void) putenv ("TZ=GMT0"); tzset (); } #endif } #ifdef DOS16 /* EXEC.C: EXEC function with memory swap - Prepare parameters. Public domain software by Thomas Wagner Ferrari electronic GmbH Beusselstrasse 27 D-1000 Berlin 21 Germany BIXname: twagner */ #define SWAP_FILENAME "$$AAAAAA.AAA" /* internal flags for prep_swap */ #define CREAT_TEMP 0x0080 #define DONT_SWAP_ENV 0x4000 #ifndef __TURBOC__ #define stpcpy(d,s) (strcpy (d, s), d + strlen (s)) #endif #ifdef __cplusplus extern "C" int #else extern int _cdecl #endif do_spawn (int swapping, /* swap if non-0 */ char *xeqfn, /* file to execute */ char *cmdtail, /* command tail string */ unsigned envlen, /* environment length */ char *envp); /* environment pointer */ #ifdef __cplusplus extern "C" int #else extern int _cdecl #endif prep_swap (int method, /* swap method */ char *swapfn); /* swap file name and/or path */ int do_exec (char *exfn, char *epars, int spwn, unsigned needed, char **envp) { static char swapfn[82]; static char execfn[82]; unsigned avail; union REGS regs; unsigned envlen; int rc; int idx; char **env; char *ep, *envptr, *envbuf; int swapping; (void) strcpy (execfn, exfn); /* Now create a copy of the environment if the user wants it. */ envlen = 0; envptr = envbuf = NULL; if (envp != NULL) for (env = envp; *env != NULL; env++) envlen += strlen (*env) + 1; if (envlen) { /* round up to paragraph, and alloc another paragraph leeway */ envlen = (envlen + 32) & 0xfff0; envbuf = (char *) malloc (envlen); if (envbuf == NULL) return RC_ENVERR; /* align to paragraph */ envptr = envbuf; if (FP_OFF (envptr) & 0x0f) envptr += 16 - (FP_OFF (envptr) & 0x0f); ep = envptr; for (env = envp; *env != NULL; env++) { ep = stpcpy (ep, *env) + 1; } *ep = 0; } if (!spwn) swapping = -1; else { /* Determine amount of free memory */ regs.x.ax = 0x4800; regs.x.bx = 0xffff; (void) intdos (®s, ®s); avail = regs.x.bx; /* No swapping if available memory > needed */ if (needed < avail) swapping = 0; else { /* Swapping necessary, use 'TMP' or 'TEMP' environment variable to determine swap file path if defined. */ swapping = spwn; if (spwn & USE_FILE) { (void) strcpy (swapfn, swapdir); if (_osmajor >= 3) swapping |= CREAT_TEMP; else { (void) strcat (swapfn, SWAP_FILENAME); idx = strlen (swapfn) - 1; while (dexists (swapfn)) { if (swapfn[idx] == 'Z') idx--; if (swapfn[idx] == '.') idx--; swapfn[idx]++; } } } } } /* All set up, ready to go. */ if (swapping > 0) { if (!envlen) swapping |= DONT_SWAP_ENV; rc = prep_swap (swapping, swapfn); if (rc < 0) return RC_PREPERR | -rc; } rc = do_spawn (swapping, execfn, epars, envlen, envptr); /* Free the environment buffer if it was allocated. */ if (envlen) free (envbuf); return rc; } #endif /* ifdef DOS16 */