home *** CD-ROM | disk | FTP | other *** search
/ Power Programming / powerprogramming1994.iso / progtool / microcrn / issue_42.arc / GLOBENV.C < prev    next >
Text File  |  1988-05-20  |  8KB  |  242 lines

  1. /*   Support code for C column in Micro C issue #42
  2.  
  3.      Module:      GlobEnv (Global Environment Access)
  4.  
  5.      Version:     1.02
  6.      Date:        April 11, 1988
  7.  
  8.      Compilers:   Microsoft C v5.10
  9.                   Turbo C 1.5
  10.                   Datalight/Zortech Optimum-C (requires -a compiler switch)
  11.  
  12.      Environment: generic MS-DOS, version 2.1 and higher
  13.  
  14.      Allows direct access to the global (system) environment. This module
  15.      has been tested with MS-DOS versions 2.11, 3.10, 3.2x, and 3.30.
  16.  
  17.      Copyright (c) 1988 by Scott Robert Ladd.
  18.      This source-code file is released for non-commercial use by anyone
  19.      who wants to use it. No warranties are expressed or implied.
  20. */
  21.  
  22. #include "stddef.h"
  23. #include "string.h"
  24.  
  25. #define TRUE  -1
  26. #define FALSE  0
  27.  
  28. /* external pointer to Program Segment Prefix (PSP) */
  29. extern unsigned _psp;
  30.  
  31. /* structures for PSP and DOS Memory Control Block (MCB) */
  32. typedef struct
  33.      {
  34.      char fill1[22];
  35.      unsigned parent_seg; /* segment of the parent of the current program */
  36.      char fill2[20];
  37.      unsigned env_seg;    /* environment segment for current program */
  38.      }
  39.      PSP;
  40.  
  41. /* This structure needs to be compiled exactly as shown -- no aligning!  */
  42. /* The pack() pragma ensures Microsoft C will byte-align this structure. */
  43. /* Since most compilers have no such pargma, this module must be compiled */
  44. /* with BYTE alignment. This goes for Turbo C and Datalight C. */
  45. #pragma pack(1)
  46. typedef struct
  47.      {
  48.      char indicator;     /* indicates whether this block is in chain */
  49.      unsigned PSP_seg;   /* the PSP segment of this block's owner */
  50.      unsigned block_len; /* the size (in paragraphs) of this block */
  51.      }
  52.      MCB;
  53. #pragma pack()
  54.  
  55. /* global variables */
  56. static char far *envptr;    /* pointer to first byte of global env. */
  57. static unsigned int envlen; /* length of global environment */
  58. static int initdone=FALSE;  /* indicates whether the module is initialized */
  59.  
  60. /* function prototypes */
  61. char *getgenv(char *varname);
  62. int   putgenv(char *varname, char *vartext);
  63. int   delgenv(char *varname);
  64.  
  65. static void findgenv(void);
  66.  
  67. /*
  68.      getgenv : Returns a pointer to the value of the environment variable
  69.                pointed to by varname. If the string is not found, NULL is
  70.                returned. Note that each call to this function erases the
  71.                array s, destroying any previous variable value.
  72. */
  73. char *getgenv(char *varname)
  74.      {
  75.      char far *e;
  76.      char *v;
  77.      static char s[128];
  78.      register int i;
  79.  
  80.      /* has the module been initialized? If not, do it! */
  81.      if (!initdone)
  82.           findgenv();
  83.  
  84.      e = envptr;
  85.  
  86.      /* search for varname */
  87.      while (*e)
  88.           {
  89.           v = varname;
  90.           for (;(*e == *v) && (*e != '=') && *e && *v; ++e, ++v);
  91.           if ((!*v) && (*e == '=')) /* varname found */
  92.                {
  93.                ++e;
  94.                /* copy value to s */
  95.                /* can't use strcpy() due to possibly different-sized pointers */
  96.                for (i = 0; (i < 127) && *e; ++i)
  97.                     {
  98.                     s[i] = *e;
  99.                     ++e;
  100.                     }
  101.                if (i < 127)
  102.                    s[i] = 0;
  103.                return s; /* contains value of varname */
  104.                }
  105.           /* skip to the next environment variable */
  106.           for (; *e; ++e);
  107.           ++e;
  108.           }
  109.  
  110.      /* varname wasn't found */
  111.      return NULL;
  112.      }
  113.  
  114. /*
  115.      putgenv : Varstring is built from the variable name (varname) and vartext.
  116.                Stores the varstring into the current global environment.
  117.                Returns -1 if there is not enough room in the environment for
  118.                the new string; otherwise, 0 is returned.
  119. */
  120. int putgenv(char *varname, char *vartext)
  121.      {
  122.      char far *e;
  123.      unsigned int l;
  124.      char varstring[256];
  125.      char *v;
  126.  
  127.      /* has the module been initialized? If not, do it! */
  128.      if (!initdone)
  129.           findgenv();
  130.  
  131.      /* make a complete environment string from the components given */
  132.      strcpy(varstring,varname);
  133.      strupr(varstring); /* make sure the name of the variable is uppercase */
  134.      strcat(varstring,"=");
  135.      strcat(varstring,vartext);
  136.  
  137.      /* delete any existing variables of the same name */
  138.      delgenv(varname);
  139.  
  140.      /* find the end of the current variables (mark by two nulls) */
  141.      for (e = envptr, l = 0; !(!*e && !*(e+1)); ++e, ++l);
  142.  
  143.      /* get the amount of remaining space */
  144.      l = envlen - l;
  145.  
  146.      /* if the new variable won't fit, return an error */
  147.      if (l < strlen(varstring))
  148.           return -1;
  149.  
  150.      v = varstring;
  151.      /* otherwise, copy varstring onto the end of the current environment */
  152.      for (++e; *v; *e++ = *v++);
  153.  
  154.      /* and end the environment with two NUL bytes */
  155.      *e = 0;
  156.      ++e;
  157.      *e = 0;
  158.  
  159.      /* it worked! */
  160.      return 0;
  161.      }
  162.  
  163. /*
  164.     delgenv : Deletes a global environment variable.
  165. */
  166. int delgenv(char *varname)
  167.      {
  168.      char far *e1; /* used in search & marks beginning of next variable */
  169.      char far *e2; /* marks beginning of the variable */
  170.      char *v;      /* varname pointer used in serach */
  171.      int searching = TRUE; /* flag to indicate serach end */
  172.  
  173.      /* has the module been initialized? If not, do it! */
  174.      if (!initdone)
  175.           findgenv();
  176.  
  177.      e1 = envptr;
  178.  
  179.      /* find the beginning of the variable to be deleted */
  180.      while (*e1 && searching)
  181.           {
  182.           v = varname;
  183.           e2 = e1;
  184.           for (;(*e1 == *v) && (*e1 != '=') && *e1 && *v; ++e1, ++v);
  185.           if ((!*v) && (*e1 == '='))
  186.                searching = FALSE; /* the variable we want was found! */
  187.           for (; *e1; ++e1);
  188.           ++e1;
  189.           }
  190.  
  191.      /* if varname wasn't found, return with an error */
  192.      if (!*e1 && searching)
  193.           return -1;
  194.  
  195.      /* otherwise, copy the remainder of the environment over varname */
  196.      for (; !(!*e1 && !*(e1+1)); *e2++ = *e1++);
  197.  
  198.      /* end the environment with double NUL bytes */
  199.      *e2 = 0;
  200.      ++e2;
  201.      *e2 = 0;
  202.  
  203.      /* it worked */
  204.      return 0;
  205.      }
  206.  
  207. /*
  208.      findgenv : This function must be called before the other functions
  209.                 in the module will work.
  210. */
  211. static void findgenv()
  212.      {
  213.      PSP far *curPSP; /* current PSP */
  214.      PSP far *parPSP; /* parent  PSP */
  215.      MCB far *parMCB; /* parent  MCB */
  216.      MCB far *envMCB; /* environment MCB */
  217.  
  218.      /* set pointers to the PSPs of the current program and its parent */
  219.      curPSP = (PSP far *)((long)_psp << 16);
  220.      parPSP = (PSP far *)((long)(curPSP->parent_seg) << 16);
  221.  
  222.      if (parPSP->env_seg == 0)
  223.           {
  224.           /* the environment is in the block after the parent program */
  225.           parMCB = (MCB  far *)((long)parPSP - 0x10000L);
  226.           envptr = (char far *)((long)parPSP + 0x10000L + ((long)parMCB->block_len << 16));
  227.           }
  228.        else
  229.           /* we have a direct pointer to the environment */
  230.           envptr = (char far *)((long)(parPSP->env_seg) << 16);
  231.  
  232.      /* the MCB of the environment is one segment lower in memory */
  233.      envMCB = (MCB far *)((long)(envptr) - 0x10000L);
  234.  
  235.      /* save the length of the environment */
  236.      envlen = envMCB->block_len;
  237.  
  238.      /* make sure the other functions know that findgenv is done */
  239.      initdone = TRUE;
  240.      }
  241.  
  242.