B_SPAWN.C

13.9 KB bb7e38d68c9b5638…
/*--------------------------------------------------------------------------*/
/*                                                                          */
/*                                                                          */
/*      ------------         Bit-Bucket Software, Co.                       */
/*      \ 10001101 /         Writers and Distributors of                    */
/*       \ 011110 /          Freely Available<tm> Software.                 */
/*        \ 1011 /                                                          */
/*         ------                                                           */
/*                                                                          */
/*  (C) Copyright 1987-91, Bit Bucket Software Co., a Delaware Corporation. */
/*                                                                          */
/*                                                                          */
/*            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.250.    */
/*                                                                          */
/*    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:491/0                          */
/* 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"

#ifndef OS_2
/*

   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];

#ifndef OS_2
   char *command;
   char *p;
#ifndef __TURBOC__
   unsigned j;
#endif /* ifndef __TURBOC__ */
#ifdef __ZTC__
   char **environ;
#endif

#else /* ifndef OS_2 */
   char *comspec;
#endif /* ifndef OS_2 */

   if (saved_TZ != NULL)
      {
      (void) putenv (saved_TZ);
      tzset ();
      }

   /* Save where we are */
   (void) fflush (status_log);
   (void) real_flush (fileno (status_log));
   need_update = 0;

   /* Save where we are */
   (void) getcwd (this_dir, 79);

#ifdef OS_2

   if (cmd_str)
      system (cmd_str);
   else
      {
      comspec = getenv("COMSPEC");
      if (comspec)
   spawnlp (P_WAIT, comspec, comspec, NULL);
      }
   DosSelectDisk (*this_dir - 'A' + 1);
   chdir (this_dir);

#else   /* ifdef OS_2 */

   if ((p = getenv ("COMSPEC")) == NULL)
      p = "COMMAND.COM";

#ifdef MEWEL
   VidShowCursor();
#endif

#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
      {
      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);

      }

   /* 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 /* OS_2 */

   if (saved_TZ != NULL)
      {
      (void) putenv ("TZ=GMT0");
      tzset ();
      }
#ifdef MEWEL
  VidHideCursor();
  WinDrawAllWindows();
#endif

}

#ifndef OS_2

/*
   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 (&regs, &regs);
      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 /* ifndef OS_2 */