home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / snip9707.zip / GLBL_ENV.C < prev    next >
C/C++ Source or Header  |  1997-07-05  |  11KB  |  371 lines

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