home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / MAP_S1.ZIP / GLBL_ENV.C < prev    next >
C/C++ Source or Header  |  1988-06-25  |  10KB  |  347 lines

  1. /*****************************************************************************
  2.    This code is based upon the program SETPATH.PAS (located in BPROGA) by
  3.    David Dubois [71401,747]
  4.  
  5.    This Turbo C version is written by Peter Thomas [75716,2377]
  6.  
  7.    This series of routines are designed to Locate, Retrieve, Update, and
  8.    Remove "Variables" from the MASTER copy of the DOS Environment table.
  9.    The routines have been written in a manner that avoids linking any
  10.    EXTERNAL routines for string manipulation, and thus should be independent
  11.    of memory model being used.
  12.  
  13.    Be careful that changes made to the Environment with these routines
  14.    ONLY OCCUR IN THE MASTER COPY, and that if COMMAND.COM is spawned
  15.    from a routine that has changed the environment, NO CHANGES WILL BE
  16.    SEEN IN THE ENVIRONMENT. This is most apparent when this program is run
  17.    in the INTEGRATED environment: changes made by this technique will
  18.    not appear if the "OS Shell" is invoked, and will only appear on exit
  19.    from TC.
  20.  
  21.    For full documentation on the techniques used here can be found in the
  22.    file COMENV.ARC located in LIB 2 of BPROGA on Compuserve.
  23.  
  24.    As David Dubois says:
  25.  
  26.   I hereby dedicate this knowledge to the public domain. Feel free to use
  27.   it, but if you do, please mention my name. There are no guarantees, and
  28.   in fact, I wouldn't bet a dollar that it will work every time.
  29.  
  30.   That this works at all is based on experimental, rather than properly
  31.   documented, evidence. There are no guarantees. But then, its free.
  32.  
  33. *****************************************************************************/
  34.  
  35. #include <dos.h>
  36. #include <alloc.h>
  37.  
  38. /*
  39.  *   Mstr_FindEnvironment:
  40.  *     Scans for the "Master" Environment area, and returns
  41.  *     a pointer to it, and the size of the environment.
  42. */
  43. void Mstr_FindEnvironment ( char far **Env , unsigned *EnvSize )
  44. {
  45.    unsigned int far *CommandSeg, far *TempSeg ;
  46.    char far *BlockSeg ;
  47.  
  48.    /*
  49.     *  Scan through PSP's looking for a block that is its own father.
  50.     *  This block is the PSP of COMMAND.COM
  51.    */
  52.   TempSeg = MK_FP ( _psp , 0 ) ;
  53.    do
  54.    {
  55.      CommandSeg = TempSeg ;
  56.      TempSeg = MK_FP ( *(TempSeg+8) , 0 ) ;
  57.    }
  58.    while ( TempSeg != CommandSeg ) ;
  59.  
  60.    /*
  61.     *  Scan forward through memory looking for the correct MSB.
  62.     *  This will have COMMAND.COM's PSP as owner, and begin with
  63.     *  the character M
  64.    */
  65.    BlockSeg = (char far *)CommandSeg ;
  66.    do
  67.    {
  68.     BlockSeg = MK_FP ( FP_SEG(BlockSeg)+1 , 0 ) ;
  69.    }
  70.    while ( ( *(unsigned int far *)(BlockSeg+1) != FP_SEG ( CommandSeg ) ) ||
  71.            ( *BlockSeg != 'M' ) ) ;
  72.  
  73.    /*
  74.     *  The environment is the NEXT segment of memory
  75.     *  and bytes 4 and 5 are the size in paragraphs
  76.    */
  77.    *Env = MK_FP ( FP_SEG(BlockSeg)+1 , 0 ) ;
  78.    *EnvSize = 16 * *(unsigned int far *)(BlockSeg+3) ;
  79. }
  80.  
  81. /*
  82.  *   Mstr_getenv:
  83.  *     Scans the "Master" Environment for a given "sub string"
  84.  *     and returns a pointer to it.
  85.  *     Similar to Turbo routine "getenv" but uses the Master copy of the
  86.  *     environment table.
  87. */
  88. char far *Mstr_getenv (char far *Env , char far *name)
  89. {
  90.    char far *Sub_Env, far *str1, far *str2 ;
  91.  
  92.    /*
  93.     *  Start at the beginning of the environment
  94.    */
  95.    Sub_Env = Env ;
  96.  
  97.    /*
  98.     *  While the "sub string" we're looking at is non-zero
  99.    */
  100.    for ( ; *Sub_Env ; )
  101.    {
  102.      /*
  103.       *  Simulate a "strcmp" on the "sub string" of the environment
  104.       *  and the string we're looking for
  105.      */
  106.      for ( str1 = Sub_Env , str2 = name ;
  107.            (*str1) && (*str2) && ( *str1 == *str2) ;
  108.            str1++ , str2++ ) ;
  109.      /*
  110.       *  If we reached the end of the string we're looing for
  111.       *  we've found the correct portion of the environment.
  112.       *  Return the ptr to the start of this "sub string"
  113.      */
  114.      if ( !*str2 )
  115.        return ( Sub_Env ) ;
  116.  
  117.      /*
  118.       *  Otherwise, advance to the next "sub string" in the environment
  119.       *  by performing a "strchr" function
  120.      */
  121.      for ( ; *(Sub_Env++) ; ) ;
  122.    }
  123.  
  124.    /*
  125.     *  Obviously, the string is not present in the environment.
  126.     *  Return this fact.
  127.    */
  128.   return ( NULL ) ;
  129. }
  130.  
  131. /*
  132.  *   Mstr_delenv:
  133.  *     Scans the "Master" Environment for a given "sub string"
  134.  *     and removes it.
  135. */
  136. int Mstr_delenv (char far *Env , unsigned EnvSize , char far *name)
  137. {
  138.    char far *Sub_Env , far *New_Env ;
  139.    char huge *Dest , far *Src , huge *End_Env ;
  140.  
  141.    int Done  ;
  142.    unsigned Ctr ;
  143.  
  144.    /*
  145.     *  Allocate a chunk of storage to act as a "working" copy of
  146.     *  the Environment table
  147.    */
  148.    New_Env = farmalloc ( EnvSize ) ;
  149.  
  150.    /*
  151.     *  Copy the data from the Master to Working copy of the
  152.     *  Environment table.
  153.     *  Simulates a "memcpy" function.
  154.    */
  155.    for ( Src = Env , Dest = (char far *)New_Env , Ctr = 0 ;
  156.          Ctr < EnvSize ;
  157.          *(Dest++) = *(Src++) , Ctr++ ) ;
  158.  
  159.    /*
  160.     *  Scan the working copy of the environment for the desired
  161.     *  sub string
  162.    */
  163.    Sub_Env = Mstr_getenv ( New_Env , name ) ;
  164.  
  165.    if ( Sub_Env == NULL )
  166.    {
  167.      /*
  168.       *  If not found, do nothing
  169.      */
  170.      Done = -1 ;
  171.    } else {
  172.      /*
  173.       *  Locate the end of the string to delete
  174.       *  Simulate a "strchr" call
  175.      */
  176.      for ( Src = Sub_Env ; *(Src++) ; ) ;
  177.  
  178.      /*
  179.       *  Move the rest of the environment back over the "sub string"
  180.       *  being deleted.
  181.       *  Simulated "memcpy" function.
  182.       *  Huge pointers used for pointer comparison purposes.
  183.      */
  184.      for ( Dest = (char huge *)Sub_Env , End_Env = (char huge *) (New_Env + EnvSize ) ;
  185.          ( Dest < End_Env ) ;
  186.          *(Dest++) = *(Src++) ) ;
  187.  
  188.      /*
  189.       *  Copy the data from the Working to Master copy of the
  190.       *  Environment table.
  191.       *  Simulates a "memcpy" function.
  192.      */
  193.      for ( Src = New_Env , Dest = (char huge *)Env , Ctr = 0 ;
  194.          Ctr < EnvSize ;
  195.          *(Dest++) = *(Src++) , Ctr++ ) ;
  196.  
  197.      /*
  198.       *  Signal all done
  199.      */
  200.      Done = 0 ;
  201.    }
  202.  
  203.    /*
  204.     *  Free all working storage
  205.    */
  206.    farfree ( New_Env ) ;
  207.  
  208.    return ( Done ) ;
  209. }
  210.  
  211. /*
  212.  *   Mstr_putenv:
  213.  *     Adds/Replaces a given "sub string" in the Master Environment.
  214.  *     Similar to Turbo routine "putenv" but uses the Master copy of the
  215.  *     environment table.
  216. */
  217. int Mstr_putenv (char far *Env , unsigned EnvSize , char far *name )
  218. {
  219.    char far *Sub_Env , far *Temp_Name ;
  220.    char huge *Dest , far *Src , huge *End_Env ;
  221.    int Done ;
  222.  
  223.    /*
  224.     *  Allocate a chunk of storage to create the Variable name to add
  225.     *  to the Environment table
  226.    */
  227.    Temp_Name = farmalloc ( 256 ) ;
  228.  
  229.    /*
  230.     *  Extract only the Name portion of the data to add to the Environment
  231.    */
  232.    for ( Src = name , Dest = Temp_Name ;
  233.          *Src && ( *Src != '=' ) ;
  234.         *(Dest++) = *(Src++) ) ;
  235.  
  236.    /*
  237.     *  Ensure that the resulting name is well formed.
  238.    */
  239.    *(Dest++) = '=' ;
  240.    *Dest = 0 ;
  241.  
  242.    /*
  243.     *  Delete this sub string if found in the environment
  244.    */
  245.    Mstr_delenv ( Env , EnvSize , Temp_Name ) ;
  246.  
  247.    /*
  248.     *  Locate the END of the Master table by locating a zero length
  249.     *  String in it
  250.    */
  251.    Sub_Env = Env ;
  252.    for ( ; *Sub_Env ; )
  253.    {
  254.      for ( ; *(Sub_Env++) ; ) ;
  255.    }
  256.  
  257.    /*
  258.     *  Add the new string to the END of the existing environment, with
  259.     *  trincation IF needed
  260.    */
  261.    for ( Dest = (char huge *)(Sub_Env) , Src = name , End_Env = (char huge *) (Env + EnvSize ) ;
  262.          ( Dest < End_Env ) && (*Src) ;
  263.          *(Dest++) = *(Src++) ) ;
  264.  
  265.    Done = -1 ;
  266.    if ( !*Src )
  267.    {
  268.      /*
  269.       *  If the string to add was FULLY added, ensure that the
  270.       *  newly updated environment is properly finished
  271.      */
  272.      Done = 0 ;
  273.      *(Dest++) = 0 ;
  274.      *Dest = 0 ;
  275.    }
  276.  
  277.    /*
  278.     *  As a real safety measure, ensure that the FINAL two bytes of the
  279.     *  Environment are both 0. This will finish the last string AND
  280.     *  ensure that a zero length string is also present
  281.    */
  282.    *(End_Env-1) = 0 ;
  283.   *(End_Env-2) = 0 ;
  284.  
  285.    /*
  286.     *  Free all working storage
  287.    */
  288.    farfree ( Temp_Name ) ;
  289.  
  290.    return ( Done ) ;
  291. }
  292.  
  293. main()
  294. {
  295.   char far *Env ;
  296.    unsigned EnvSize ;
  297.  
  298.    /*
  299.     *  Locate the Master Table
  300.    */
  301.    Mstr_FindEnvironment ( &Env, &EnvSize ) ;
  302.  
  303.    /*
  304.     *  Describe what we've just found
  305.    */
  306.    printf ( "Env = %Fp Size = %u\n\n" , Env , EnvSize ) ;
  307.  
  308.    /*
  309.     *  Search for, and display LOCATIONS of PATH, FRED and BERT
  310.    */
  311.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  312.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  313.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  314.  
  315.    /*
  316.     *  Add FRED and BERT to the environment
  317.    */
  318.    Mstr_putenv ( Env , EnvSize , "FRED=fred" ) ;
  319.    Mstr_putenv ( Env , EnvSize , "BERT=bert" ) ;
  320.  
  321.    printf ( "\nAdded FRED and BERT to environment\n" ) ;
  322.  
  323.    /*
  324.     *  Search for, and display LOCATIONS of PATH ,FRED and BERT
  325.    */
  326.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  327.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  328.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  329.  
  330.    /*
  331.     *  Delete FRED from the environment
  332.    */
  333.    Mstr_delenv ( Env , EnvSize , "FRED=" ) ;
  334.  
  335.    printf ( "\nDeleted FRED= from the environment\n" ) ;
  336.  
  337.    /*
  338.     *  Search for, and display LOCATIONS of PATH, FRED, and BERT
  339.    */
  340.    printf ( "Search for PATH= returns %Fp\n",  Mstr_getenv ( Env , "PATH=" ) ) ;
  341.    printf ( "Search for FRED= returns %Fp\n",  Mstr_getenv ( Env , "FRED=" ) ) ;
  342.    printf ( "Search for BERT= returns %Fp\n",  Mstr_getenv ( Env , "BERT=" ) ) ;
  343.  
  344.    printf ( "\nIssue the DOS command SET and see that BERT is now set\n" ) ;
  345.  
  346. }
  347.