home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1996 October / PCO_10.ISO / filesbbs / bsrc_260.arj / SRC.ZIP / b_spawn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-23  |  13.5 KB  |  474 lines

  1. /*--------------------------------------------------------------------------*/
  2. /*                                                                          */
  3. /*                                                                          */
  4. /*      ------------         Bit-Bucket Software, Co.                       */
  5. /*      \ 10001101 /         Writers and Distributors of                    */
  6. /*       \ 011110 /          Freely Available<tm> Software.                 */
  7. /*        \ 1011 /                                                          */
  8. /*         ------                                                           */
  9. /*                                                                          */
  10. /*              (C) Copyright 1987-96, Bit Bucket Software Co.              */
  11. /*                                                                          */
  12. /*            This module was originally written by Bob Hartman             */
  13. /*                                                                          */
  14. /*                        BinkleyTerm "Spawn" module                        */
  15. /*                                                                          */
  16. /*                                                                          */
  17. /*    For complete  details  of the licensing restrictions, please refer    */
  18. /*    to the License  agreement,  which  is published in its entirety in    */
  19. /*    the MAKEFILE and BT.C, and also contained in the file LICENSE.260.    */
  20. /*                                                                          */
  21. /*    USE  OF THIS FILE IS SUBJECT TO THE  RESTRICTIONS CONTAINED IN THE    */
  22. /*    BINKLEYTERM  LICENSING  AGREEMENT.  IF YOU DO NOT FIND THE TEXT OF    */
  23. /*    THIS  AGREEMENT IN ANY OF THE  AFOREMENTIONED FILES,  OR IF YOU DO    */
  24. /*    NOT HAVE THESE FILES,  YOU  SHOULD  IMMEDIATELY CONTACT BIT BUCKET    */
  25. /*    SOFTWARE CO.  AT ONE OF THE  ADDRESSES  LISTED BELOW.  IN NO EVENT    */
  26. /*    SHOULD YOU  PROCEED TO USE THIS FILE  WITHOUT HAVING  ACCEPTED THE    */
  27. /*    TERMS  OF  THE  BINKLEYTERM  LICENSING  AGREEMENT,  OR  SUCH OTHER    */
  28. /*    AGREEMENT AS YOU ARE ABLE TO REACH WITH BIT BUCKET SOFTWARE, CO.      */
  29. /*                                                                          */
  30. /*                                                                          */
  31. /* You can contact Bit Bucket Software Co. at any one of the following      */
  32. /* addresses:                                                               */
  33. /*                                                                          */
  34. /* Bit Bucket Software Co.        FidoNet  1:104/501, 1:343/491             */
  35. /* P.O. Box 460398                AlterNet 7:42/1491                        */
  36. /* Aurora, CO 80046               BBS-Net  86:2030/1                        */
  37. /*                                Internet f491.n343.z1.fidonet.org         */
  38. /*                                                                          */
  39. /* Please feel free to contact us at any time to share your comments about  */
  40. /* our software and/or licensing policies.                                  */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43.  
  44. /* Include this file before any other includes or defines! */
  45.  
  46. #include "includes.h"
  47.  
  48. #ifdef DOS16
  49.  
  50. /* Include MOVEAPI file if this is C7 or C8 under DOS. */
  51.  
  52. #ifdef MOVE_OVERLAYS
  53. #include <../source/move/moveapi.h>
  54. #endif
  55.  
  56. /*
  57.  
  58.    We now use Thomas Wagner's EXEC module to do our swapping.
  59.    There's probably no good reason why we can't just hack our
  60.    code to work with his as distributed. We'll put that on the
  61.    wishlist. For now, we hacked his and you'll find the
  62.    appropriate excerpts below.
  63.  
  64.  
  65.  
  66.    EXEC.H: EXEC function with memory swap - Main function header file.
  67.  
  68.    Public domain software by
  69.  
  70.         Thomas Wagner
  71.         Ferrari electronic GmbH
  72.         Beusselstrasse 27
  73.         D-1000 Berlin 21
  74.         Germany
  75. */
  76.  
  77. extern int do_exec (char *xfn, char *pars, int spawn, unsigned needed,
  78.     char **envp);
  79.  
  80. /*
  81.    The EXEC function.
  82.  
  83.       Parameters:
  84.  
  85.          xfn      is a string containing the name of the file
  86.                   to be executed.
  87.  
  88.          pars     The program parameters.
  89.  
  90.          spawn    If 0, the function will terminate after the
  91.                   EXECed program returns, the function will not return.
  92.  
  93.                   NOTE: If the program file is not found, the function
  94.                         will always return with the appropriate error
  95.                         code, even if 'spawn' is 0.
  96.  
  97.                   If non-0, the function will return after executing the
  98.                   program. If necessary (see the "needed" parameter),
  99.                   memory will be swapped out before executing the program.
  100.                   For swapping, spawn must contain a combination of the
  101.                   following flags:
  102.  
  103.                      USE_EMS  (0x01)  - allow EMS swap
  104.                      USE_XMS  (0x02)  - allow XMS swap
  105.                      USE_FILE (0x04)  - allow File swap
  106.  
  107.                   The order of trying the different swap methods can be
  108.                   controlled with one of the flags
  109.  
  110.                      EMS_FIRST (0x00) - EMS, XMS, File (default)
  111.                      XMS_FIRST (0x10) - XMS, EMS, File
  112.  
  113.                   If swapping is to File, the attribute of the swap file
  114.                   can be set to "hidden", so users are not irritated by
  115.                   strange files appearing out of nowhere with the flag
  116.  
  117.                      HIDE_FILE (0x40)    - create swap file as hidden
  118.  
  119.                   and the behaviour on Network drives can be changed with
  120.  
  121.                      NO_PREALLOC (0x100) - don't preallocate
  122.                      CHECK_NET (0x200)   - don't preallocate if file on net.
  123.  
  124.                   This checking for Network is mainly to compensate for
  125.                   a strange slowdown on Novell networks when preallocating
  126.                   a file. You can either set NO_PREALLOC to avoid allocation
  127.                   in any case, or let the prep_swap routine decide whether
  128.                   to do preallocation or not depending on the file being
  129.                   on a network drive (this will only work with DOS 3.1 or
  130.                   later).
  131.  
  132.          needed   The memory needed for the program in paragraphs (16 Bytes).
  133.                   If not enough memory is free, the program will
  134.                   be swapped out.
  135.                   Use 0 to never swap, 0xffff to always swap.
  136.                   If 'spawn' is 0, this parameter is irrelevant.
  137.  
  138.          envp     The environment to be passed to the spawned
  139.                   program. If this parameter is NULL, a copy
  140.                   of the parent's environment is used (i.e.
  141.                   'putenv' calls have no effect). If non-NULL,
  142.                   envp must point to an array of pointers to
  143.                   strings, terminated by a NULL pointer (the
  144.                   standard variable 'environ' may be used).
  145.  
  146.       Return value:
  147.  
  148.          0x0000..00FF: The EXECed Program's return code
  149.          0x0101:       Error preparing for swap: no space for swapping
  150.          0x0102:       Error preparing for swap: program too low in memory
  151.          0x0200:       Program file not found
  152.          0x03xx:       DOS-error-code xx calling EXEC
  153.          0x0400:       Error allocating environment buffer
  154.          0x0500:       Swapping requested, but prep_swap has not
  155.                        been called or returned an error.
  156.          0x0501:       MCBs don't match expected setup
  157.          0x0502:       Error while swapping out
  158. */
  159.  
  160. /* Return codes (only upper byte significant) */
  161.  
  162. #define RC_PREPERR   0x0100
  163. #define RC_NOFILE    0x0200
  164. #define RC_EXECERR   0x0300
  165. #define RC_ENVERR    0x0400
  166. #define RC_SWAPERR   0x0500
  167.  
  168. /* Swap method and option flags */
  169.  
  170. #define USE_EMS      0x01
  171. #define USE_XMS      0x02
  172. #define USE_FILE     0x04
  173. #define EMS_FIRST    0x00
  174. #define XMS_FIRST    0x10
  175. #define HIDE_FILE    0x40
  176. #define NO_PREALLOC  0x100
  177. #define CHECK_NET    0x200
  178.  
  179. #define USE_ALL      (USE_EMS | USE_XMS | USE_FILE)
  180.  
  181. #endif
  182.  
  183. void 
  184. b_spawn (char *cmd_str)
  185. {
  186.     char this_dir[80];
  187.  
  188. #ifdef DOS16
  189.     char *command;
  190.     char *p;
  191.  
  192. #ifndef __TURBOC__
  193.     unsigned j;
  194.  
  195. #endif                            /* ifndef __TURBOC__ */
  196. #ifdef __ZTC__
  197.     char **environ;
  198.  
  199. #endif
  200.  
  201. #else                            /* ifdef DOS16 */
  202.     char *comspec;
  203.  
  204. #endif                            /* ifdef DOS16 */
  205.  
  206. #ifndef UCT_DIFFERENTIAL
  207.  
  208.     if (saved_TZ != NULL)
  209.     {
  210.         (void) putenv (saved_TZ);
  211.         tzset ();
  212.     }
  213.  
  214. #endif
  215.  
  216.     /* Save where we are in the status and cost logs */
  217.  
  218.     if (status_log != NULL)
  219.     {
  220.         (void) fflush (status_log);
  221.         (void) real_flush (fileno (status_log));
  222.     }
  223.  
  224.     if (cost_log != NULL)
  225.     {
  226.         (void) fflush (cost_log);
  227.         (void) real_flush (fileno (cost_log));
  228.     }
  229.     need_update = 0;
  230.  
  231.     /* Save where we are */
  232.     (void) getcwd (this_dir, 79);
  233.  
  234. #ifndef DOS16
  235.  
  236.     if (cmd_str)
  237.         system (cmd_str);
  238.     else
  239.     {
  240.         comspec = getenv ("COMSPEC");
  241.         if (comspec)
  242.             spawnlp (P_WAIT, comspec, comspec, NULL);
  243.     }
  244. #ifdef OS_2
  245.     DosSelectDisk ((USHORT) (*this_dir - 'A' + 1));
  246. #endif
  247. #ifdef _WIN32
  248.     _chdrive ((int) (*this_dir - 'A' + 1));
  249. #endif
  250.     chdir (this_dir);
  251.  
  252. #else                            /* ifndef DOS16 */
  253.  
  254.     if ((p = getenv ("COMSPEC")) == NULL)
  255.         p = "COMMAND.COM";
  256.  
  257. #ifdef __ZTC__
  258.     environ = NULL;
  259. #endif
  260.  
  261.     if (swapdir == NULL)
  262.     {
  263.         if (cmd_str != NULL)
  264.             (void) system (cmd_str);
  265.         else
  266.             (void) spawnlp (P_WAIT, p, p, NULL);
  267.     }
  268.     else
  269.     {
  270. #ifdef MOVE_OVERLAYS
  271.         _movepause ();
  272. #endif
  273.         if (cmd_str != NULL)
  274.         {
  275.             command = calloc (1, strlen (cmd_str) + 4);
  276.             if (command != NULL)
  277.             {
  278.                 (void) strcpy (command, "/c ");
  279.                 (void) strcat (command, cmd_str);
  280.                 (void) do_exec (p, command, USE_ALL, 0xffff, environ);
  281.                 free (command);
  282.             }
  283.         }
  284.         else
  285.             (void) do_exec (p, "", USE_ALL, 0xffff, environ);
  286.  
  287. #ifdef MOVE_OVERLAYS
  288.         _moveresume ();
  289. #endif
  290.     }
  291.  
  292.     /* Go back to the proper directory */
  293. #ifdef __TURBOC__
  294.     setdisk ((unsigned) (this_dir[0] - 'A'));
  295. #else                            /* __TURBOC__ */
  296.     _dos_setdrive ((unsigned) ((int) this_dir[0] - 'A' + 1), &j);
  297. #endif                            /* __TURBOC__ */
  298.     (void) chdir (this_dir);
  299.  
  300. #endif                            /* DOS16 */
  301.  
  302. #ifndef UCT_DIFFERENTIAL
  303.  
  304.     if (saved_TZ != NULL)
  305.     {
  306.         (void) putenv ("TZ=GMT0");
  307.         tzset ();
  308.     }
  309.  
  310. #endif
  311.  
  312. }
  313.  
  314. #ifdef DOS16
  315.  
  316. /*
  317.    EXEC.C: EXEC function with memory swap - Prepare parameters.
  318.  
  319.    Public domain software by
  320.  
  321.         Thomas Wagner
  322.         Ferrari electronic GmbH
  323.         Beusselstrasse 27
  324.         D-1000 Berlin 21
  325.         Germany
  326.  
  327.         BIXname: twagner
  328. */
  329.  
  330. #define SWAP_FILENAME "$$AAAAAA.AAA"
  331.  
  332. /* internal flags for prep_swap */
  333.  
  334. #define CREAT_TEMP      0x0080
  335. #define DONT_SWAP_ENV   0x4000
  336.  
  337. #ifndef __TURBOC__
  338. #define stpcpy(d,s)     (strcpy (d, s), d + strlen (s))
  339. #endif
  340.  
  341. #ifdef __cplusplus
  342. extern "C" int
  343. #else
  344. extern int _cdecl
  345. #endif
  346.  do_spawn (int swapping,        /* swap if non-0 */
  347.     char *xeqfn,                /* file to execute */
  348.     char *cmdtail,                /* command tail string */
  349.     unsigned envlen,            /* environment length */
  350.     char *envp);                /* environment pointer */
  351.  
  352. #ifdef __cplusplus
  353. extern "C" int
  354. #else
  355. extern int _cdecl
  356. #endif
  357.  prep_swap (int method,            /* swap method */
  358.     char *swapfn);                /* swap file name and/or path */
  359.  
  360. int 
  361. do_exec (char *exfn, char *epars, int spwn, unsigned needed, char **envp)
  362. {
  363.     static char swapfn[82];
  364.     static char execfn[82];
  365.     unsigned avail;
  366.     union REGS regs;
  367.     unsigned envlen;
  368.     int rc;
  369.     int idx;
  370.     char **env;
  371.     char *ep, *envptr, *envbuf;
  372.     int swapping;
  373.  
  374.     (void) strcpy (execfn, exfn);
  375.  
  376.     /* Now create a copy of the environment if the user wants it. */
  377.  
  378.     envlen = 0;
  379.     envptr = envbuf = NULL;
  380.  
  381.     if (envp != NULL)
  382.         for (env = envp; *env != NULL; env++)
  383.             envlen += strlen (*env) + 1;
  384.  
  385.     if (envlen)
  386.     {
  387.         /* round up to paragraph, and alloc another paragraph leeway */
  388.         envlen = (envlen + 32) & 0xfff0;
  389.         envbuf = (char *) malloc (envlen);
  390.         if (envbuf == NULL)
  391.             return RC_ENVERR;
  392.  
  393.         /* align to paragraph */
  394.         envptr = envbuf;
  395.         if (FP_OFF (envptr) & 0x0f)
  396.             envptr += 16 - (FP_OFF (envptr) & 0x0f);
  397.         ep = envptr;
  398.  
  399.         for (env = envp; *env != NULL; env++)
  400.         {
  401.             ep = stpcpy (ep, *env) + 1;
  402.         }
  403.         *ep = 0;
  404.     }
  405.  
  406.     if (!spwn)
  407.         swapping = -1;
  408.     else
  409.     {
  410.         /* Determine amount of free memory */
  411.  
  412.         regs.x.ax = 0x4800;
  413.         regs.x.bx = 0xffff;
  414.         (void) intdos (®s, ®s);
  415.         avail = regs.x.bx;
  416.  
  417.         /* No swapping if available memory > needed */
  418.  
  419.         if (needed < avail)
  420.             swapping = 0;
  421.         else
  422.         {
  423.             /* Swapping necessary, use 'TMP' or 'TEMP' environment variable
  424.            to determine swap file path if defined. */
  425.  
  426.             swapping = spwn;
  427.             if (spwn & USE_FILE)
  428.             {
  429.                 (void) strcpy (swapfn, swapdir);
  430.  
  431.                 if (_osmajor >= 3)
  432.                     swapping |= CREAT_TEMP;
  433.                 else
  434.                 {
  435.                     (void) strcat (swapfn, SWAP_FILENAME);
  436.                     idx = strlen (swapfn) - 1;
  437.                     while (dexists (swapfn))
  438.                     {
  439.                         if (swapfn[idx] == 'Z')
  440.                             idx--;
  441.                         if (swapfn[idx] == '.')
  442.                             idx--;
  443.                         swapfn[idx]++;
  444.                     }
  445.                 }
  446.             }
  447.         }
  448.     }
  449.  
  450.     /* All set up, ready to go. */
  451.  
  452.     if (swapping > 0)
  453.     {
  454.         if (!envlen)
  455.             swapping |= DONT_SWAP_ENV;
  456.  
  457.         rc = prep_swap (swapping, swapfn);
  458.         if (rc < 0)
  459.             return RC_PREPERR | -rc;
  460.     }
  461.  
  462.     rc = do_spawn (swapping, execfn, epars, envlen, envptr);
  463.  
  464.     /* Free the environment buffer if it was allocated. */
  465.  
  466.     if (envlen)
  467.         free (envbuf);
  468.  
  469.     return rc;
  470. }
  471.  
  472. #endif                            /* ifdef DOS16 */
  473.  
  474.