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