1 /* subroutine to put a value string into an environment symbol.
2 Uses the controling command.com environment, not the programs.
3 This means that the env variable is set so other routines in
4 a .BAT file may use it.
6 call: settheenv (char * symbol, char * val);
7 symbol is an asciiz string containing the env variable name,
8 val is an asciiz string containing the value to assign to this vbl.
12 failure is not unlikely. The env block may be full. Or on some
13 systems the env block might not be found
15 SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>.
26 int *prev_term_handler
;
42 #define NORMAL_ATYPE 0x4D
43 #define LAST_ATYPE 0x5A
46 static arena
* get_next_arena (arena
* ap
) {
47 return( MK_FP( FP_SEG(ap
)+1+ap
->num_segments
, 0) );
50 /* returns 0 if passed pointer is to an arena, else returns 1 */
51 static int is_valid_arena (arena
* ap
) {
53 if (ap
->type
== NORMAL_ATYPE
&&
54 (ap1
=get_next_arena(ap
))->type
== NORMAL_ATYPE
&&
55 ( (ap1
=get_next_arena(ap1
))->type
== NORMAL_ATYPE
||
56 ap1
->type
== LAST_ATYPE
) )
62 static arena
* get_first_arena () {
63 /* return pointer to the first arena.
64 * scan memory for a 0x4D on a segment start,
65 * see if this points to another two levels of arena
71 for (segment
=0; segment
<_CS
; segment
++) {
72 ap
= MK_FP(segment
, 0);
73 if ( is_valid_arena (ap
) == 0) return (ap
);
76 } /* end get_first_arena */
79 static int is_valid_env (char * ad
, int num_segs
) {
82 while ( (*ad
) && (((ad
-base_ad
)>>4) < num_segs
) ) {
83 if (strnicmp(ad
, "COMSPEC=", 8)==0) return(0);
90 static arena
* get_arena_of_environment () {
91 /* to get the arena of first environment block:
92 First get segment of COMMAND.COM from segment of previous critical err code.
93 Then scan all the arenas for an environment block with a matching PSP
98 unsigned int i
, ccseg
;
100 /* set pspp to psp of this program */
101 pspp
= MK_FP(_psp
,0);
104 printf("prog psp=%p\n",pspp
);
107 /* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */
108 ccseg
= FP_SEG (pspp
->prev_crit_error
);
109 if ( (i
=ccseg
-32) < 60) i
=60;
112 pspc
= MK_FP (ccseg
, 0);
113 if ( is_valid_arena((arena
*) pspc
) == 0) goto L1
;
118 L1
: pspc
= MK_FP (++ccseg
, 0);
120 printf("comm.com=%p\n",pspc
);
123 /* first see if env seg in command.com points to valid env block
124 if env seg is in a valid arena, then arena must point to this command.com
125 else assume env block is fabricated like for 4DOS, use 128 bytes */
127 ap
= MK_FP (pspc
->envir_seg
-1, 0);
128 i
= ap
->num_segments
;
130 if (is_valid_arena (ap
) == 0) {
131 if (ap
->psp_segment
!= FP_SEG(pspc
)) goto L2
;
136 if ( is_valid_env (&ap
->arena_data
, i
) == 0 )
139 /* command.com did not so point, search thru all env blocks */
142 if ( (ap
=get_first_arena()) != NULL
) {
143 while (ap
->type
!= LAST_ATYPE
) {
147 if (ap
->psp_segment
== FP_SEG(pspc
) &&
148 is_valid_env (&ap
->arena_data
, ap
->num_segments
)==0 )
151 ap
= get_next_arena(ap
);
154 } /* end get_arena_of_environment */
156 /*****************************************************************************/
158 int settheenv(char * symbol
, char * val
) {
162 char * sp
, *op
, *envir
;
163 char symb_len
=strlen(symbol
);
169 /* first, can COMMAND.COM's envir block be found ? */
170 if ( (ap
=get_arena_of_environment()) == NULL
)
173 /* search to end of the envir block, get sizes */
174 total_size
= 16 * ap
->num_segments
;
175 envir
= &ap
->arena_data
;
178 strlength
= strlen(sp
)+1;
179 if ( *(sp
+symb_len
)=='=' &&
180 strnicmp(sp
,symbol
,symb_len
)==0 )
183 needed_size
+= strlength
;
184 if (found
) strcpy(op
,sp
);
190 if (strlen(val
) > 0) {
191 needed_size
+= 3 + strlen(symbol
) + strlen(val
);
192 if (needed_size
> total_size
)
193 return(1); /* could mess with environment expansion here */
195 strcpy(op
, symbol
); strcat(op
, "="); strcat(op
, val
);
200 } /* end setheenv subroutine */