stan@ucla-an.UUCP (Stan Stead) (06/04/88)
Here is a solution for the problem of string length limitations within the environment. Enclosed are a set of source files for a program which will change the PATH (or any) environment variable for you. These have been only moderately tested. The code is in MSC 5.x and MASM 5.x. Use and enjoy. Please let us know about any improvements and/or bug fixes. Stan Stead and Rich Wilton Stanley W. Stead UCLA School of Medicine / Dept of Anesthesiology BELL: (213) 206-6238 ARPA: ucla-an!stan@ee.UCLA.EDU UUCP: {trwrb|ucla-cs|cepu}\ !ucla-an!stan UUCP: {ihnp4|decvax}!hermix/ <-=-=-=-=-=-=-=-=CUT HERE=-=-=-=-=-=-=-=> #! /bin/sh # To extract, remove mail header lines and type "sh filename" echo x - bigset.doc sed -e 's/^X//' > bigset.doc << '!FaR!OuT!' XBIGSET X Bigset is useful for expanding strings in the environment to any Xdesired length within the constraints of the size of the environment. The Xfiles listed contain a quick hack to modify the strings within the environment. XBasically to invoke, do bigset < bigpath.pth. Bigpath.pth contains the desired Xstrings by name. This routine works by searching the dos memory blocks for Xthe initial environment and then does serial copies to insert the string in Xthe environment block. This does not contain any comprehensive checking, so Xbe VERY careful. X X Rich Wilton & Stan Stead X XUCLA School of Medicine / Dept of Anesthesiology XBELL: (213) 206-6238 XARPA: ucla-an!stan@ee.UCLA.EDU XUUCP: {trwrb|ucla-cs|cepu}\ X !ucla-an!stan XUUCP: {ihnp4|decvax}!hermix/ !FaR!OuT! echo x - bigset.mak sed -e 's/^X//' > bigset.mak << '!FaR!OuT!' Xmcbscan.obj: mcbscan.asm X masm /mx /ml mcbscan; X Xstrncmpl.obj: strncmpl.asm X masm /mx /ml strncmpl; X Xmemmovel.obj: memmovel.asm X masm /mx /ml memmovel; X Xbigset.obj: bigset.c X cl /Zp /c bigset.c X Xbigset.exe: bigset.obj memmovel.obj strncmpl.obj mcbscan.obj X link /noi /map bigset memmovel strncmpl mcbscan; !FaR!OuT! echo x - bigpath.pth sed -e 's/^X//' > bigpath.pth << '!FaR!OuT!' Xpath=d:\aaaaaaaa\bbbbbbbb\cccccccc;d:\eeeeeeee\ffffffff\gggggggg;d:\hhhhhhhh\iiiiiiii\jjjjjjjj;d:\kkkkkkkk\llllllll\mmmmmmmm;d:\nnnnnnnn\oooooooo\pppppppp;d:\qqqqqqqq\rrrrrrrr\ssssssss;d:\tttttttt\uuuuuuuu\vvvvvvvv;d:\wwwwwwwwxxxxxxxx\yyyyyyyy;d:\dos;d:\utility !FaR!OuT! echo x - bigset.c sed -e 's/^X//' > bigset.c << '!FaR!OuT!' X/***************************************************************************** X* * X* Name: bigset.c * X* * X* Function: set an environment variable of arbitrary size * X* * X* Notes: execute as a DOS command; the environment string comes from * X* the standard input device * X* * X* WARNING: No syntax checking! * X* Authors: * X* Rich Wilton & Stan Stead * X* Department of Anesthesiology * X* UCLA School of Medicine * X* Los Angeles, CA 90024-1778 * X* * X* Bug Fixes or Modifications to: * X* ucla-an!stan@ee.ucla.edu * X* * X* Revisions: 6/3/1988 * X* * X*****************************************************************************/ X X#define MAXSIZE 1024 X X#include <dos.h> X#include <stdio.h> X#include <string.h> X#include <ctype.h> X Xunsigned int _psp; /* in MS C 5.x runtime library */ Xunsigned char NewEnvString[MAXSIZE]; /* buffer for new env string */ X X Xmain( int argc, char * argv[], char * envp[] ) X{ X unsigned int MCBScan(); /* returns 1st MCB segment */ X X struct /* NOTE: use /Zp switch */ X { X char IDbyte; X unsigned int PSPowner; X unsigned int BlockSize; X char Unused[11]; X char Data[1]; X } X far *MCB; X X X unsigned int far * LocalEnv; X unsigned int i,l,n; X unsigned char c; X X X /* get environment string from standard input */ X X for( i=0; ((c=getchar())!=EOF) && (c!='\n'); i++ ) X NewEnvString[i] = c; X X NewEnvString[i] = '\0'; /* make into ASCIIZ string */ X X if( i==0 ) X { X printf( "\nNull environment string: environment unchanged" ); X exit( 1 ); X } X X X /* make variable name uppercase */ X X for( i=0; NewEnvString[i] != '='; i++ ) X NewEnvString[i] = toupper( NewEnvString[i] ); X X X /* get pointer to local environment */ X X FP_SEG( LocalEnv ) = _psp; /* point to environment segment */ X FP_OFF( LocalEnv ) = 0x2C; X X FP_SEG( LocalEnv ) = *LocalEnv; /* point to environment */ X FP_OFF( LocalEnv ) = 0; X X X /* scan through allocated memory blocks for global environment */ X X FP_SEG( MCB ) = MCBScan(); /* point to first memory block */ X FP_OFF( MCB ) = 0x10; X X while( strncmpl( MCB, LocalEnv, 0x10 ) ) /* check 1st 16 bytes */ X { X FP_OFF( MCB ) = 0; X FP_SEG( MCB ) += MCB->BlockSize + 1; X FP_OFF( MCB ) = 0x10; X } X X l = /* length of env variable name */ X (int)strchr( NewEnvString, '=' ) - (int)NewEnvString; X X X /* update global environment */ X X for( i=0; envp[i]!=NULL; i++ ) X { X if( strncmp( envp[i], NewEnvString, l ) ) /* copy old strings */ X { X n = strlen( envp[i] ) + 1; X memmovel( MCB, (char far *)envp[i], n ); X FP_OFF( MCB ) += n; X } X } X X n = strlen( NewEnvString ) + 1; /* copy new string */ X memmovel( MCB, (char far *)NewEnvString, n ); X X FP_OFF( MCB ) += n; X MCB->IDbyte = '\0'; /* append one more null */ X} !FaR!OuT! echo x - mcbscan.asm sed -e 's/^X//' > mcbscan.asm << '!FaR!OuT!' X TITLE 'scan DOS memory for memory control blocks' X NAME mcbscan X PAGE 55,132 X; X; Module name: MCBScan X; X; Description: unsigned int MCBScan(); X; X; Notes: returns paragraph addr of 1st DOS memory control block X; (aka "arena header") X X; Authors: X; Rich Wilton & Stan Stead X; Department of Anesthesiology X; UCLA School of Medicine X; Los Angeles, CA 90024-1778 X; X; Bug Fixes or Modifications to: X; ucla-an!stan@ee.ucla.edu X; X; Revisions: 6/3/1988 X; X XSTART EQU 70h ; first paragraph to scan X X_TEXT SEGMENT byte public 'CODE' X ASSUME cs:_TEXT X X PUBLIC _MCBScan X_MCBScan PROC near X X push bp X mov bp,sp X push di X push si X push ds X X; 1st segment to search is START; last segment is this program's env block X X mov ah,51h X int 21h ; BX = PSP X mov ds,bx X mov cx,ds:[2ch] ; CX = environment segment X dec cx ; CX = last paragraph to search X X mov ax,START X X; loop through memory, paragraph by paragraph X XL01: mov ds,ax ; DS:[0] -> first possible block X cmp byte ptr ds:[0],'M' X je L03 X XL02: inc ax X cmp ax,cx X jb L01 X jmp short L05 ; exit with this program's env block X XL03: mov bx,ax ; BX = possible "hit" X XL04: add bx,ds:[3] X inc bx ; BX = possible next in chain X cmp bx,cx X je L05 ; success X X cmp ax,bx X je L02 ; circular "chain" -- keep trying X X mov ds,bx X cmp byte ptr ds:[0],'M' X je L04 ; 'M' found so continue chain X jmp L02 ; 'M' not found so keep trying X XL05: pop ds X pop si X pop di X pop bp X ret X X_MCBScan ENDP X X_TEXT ENDS X X END !FaR!OuT! echo x - memmovel.asm sed -e 's/^X//' > memmovel.asm << '!FaR!OuT!' X TITLE 'string copy routine' X NAME memmovel X PAGE 55,132 X; X; Module name: memmovel X; X; Description: void * memmovel( char far * s1, char far * s2, unsigned int n ); X; X; Notes: like memmove but uses far pointers X; X X; Authors: X; Rich Wilton & Stan Stead X; Department of Anesthesiology X; UCLA School of Medicine X; Los Angeles, CA 90024-1778 X; X; Bug Fixes or Modifications to: X; ucla-an!stan@ee.ucla.edu X; X; Revisions: 6/3/1988 X; X XARG1 EQU [bp+4] XARG2 EQU [bp+6] XARG3 EQU [bp+8] XARG4 EQU [bp+10] XARG5 EQU [bp+12] X X_TEXT SEGMENT byte public 'CODE' X ASSUME cs:_TEXT X X PUBLIC _memmovel X X_memmovel PROC near X X push bp X mov bp,sp X push si X push di X push ds X X mov di,ARG1 X mov es,ARG2 ; DS:SI -> s1 (destination) X mov si,ARG3 X mov ds,ARG4 ; ES:DI -> s2 (source) X mov cx,ARG5 ; CX = number of bytes to move X X mov ax,si X mov dx,ds ; DX:AX -> source X X cld ; set autoincrement X shr cx,1 ; CX = number of words to move X ; cf = rightmost bit X rep movsw ; move string X rcl cx,1 ; CX = rightmost bit X rep movsb ; move last byte if needed X X pop ds X pop di X pop si X pop bp X ret X X_memmovel ENDP X X_TEXT ENDS X X END !FaR!OuT! echo x - strncmpl.asm sed -e 's/^X//' > strncmpl.asm << '!FaR!OuT!' X TITLE 'string compare routine' X NAME strncmpl X PAGE 55,132 X; X; Module name: strncmpl X; X; Description: int strncmpl( char far * s1, char far * s2, unsigned int n ); X; X; Notes: works like strncmp but uses far pointers X; X; Authors: X; Rich Wilton & Stan Stead X; Department of Anesthesiology X; UCLA School of Medicine X; Los Angeles, CA 90024-1778 X; X; Bug Fixes or Modifications to: X; ucla-an!stan@ee.ucla.edu X; X; Revisions: 6/3/1988 X; X XARG1 EQU [bp+4] XARG2 EQU [bp+6] XARG3 EQU [bp+8] XARG4 EQU [bp+10] XARG5 EQU [bp+12] X X_TEXT SEGMENT byte public 'CODE' X ASSUME cs:_TEXT X X PUBLIC _strncmpl X X_strncmpl PROC near X X push bp X mov bp,sp X push si X push di X push ds X X mov si,ARG1 X mov ds,ARG2 ; DS:SI -> s1 X mov di,ARG3 X mov es,ARG4 ; ES:DI -> s2 X mov cx,ARG5 ; CX = number of bytes to compare X xor ax,ax ; AX = 0 X X repz cmpsb ; compare strings X jz L01 ; exit with AX=0 if strings are equal X X mov ax,1 ; AX = 1 X jnb L01 ; exit if s1 > s2 X X neg ax ; AX = -1 (s1 < s2) X XL01: pop ds X pop di X pop si X pop bp X ret X X_strncmpl ENDP X X_TEXT ENDS X X END !FaR!OuT! exit