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
|
/* subroutine to put a value string into an environment symbol.
Uses the controling command.com environment, not the programs.
This means that the env variable is set so other routines in
a .BAT file may use it.
call: settheenv (char * symbol, char * val);
symbol is an asciiz string containing the env variable name,
val is an asciiz string containing the value to assign to this vbl.
returns: 0 = OK,
1 = failure.
failure is not unlikely. The env block may be full. Or on some
systems the env block might not be found
SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>.
*/
#include <stdio.h>
#include <dos.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
char fill1[0x0A];
int *prev_term_handler;
int *prev_ctrl_c;
int *prev_crit_error;
char fill2[0x16];
int envir_seg;
} psp;
typedef struct {
char type;
int psp_segment;
int num_segments;
char fill[11];
char arena_data;
} arena;
#define NORMAL_ATYPE 0x4D
#define LAST_ATYPE 0x5A
static arena * get_next_arena (arena * ap) {
return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
}
/* returns 0 if passed pointer is to an arena, else returns 1 */
static int is_valid_arena (arena * ap) {
arena * ap1;
if (ap->type == NORMAL_ATYPE &&
(ap1=get_next_arena(ap))->type == NORMAL_ATYPE &&
( (ap1=get_next_arena(ap1))->type == NORMAL_ATYPE ||
ap1->type == LAST_ATYPE) )
return(0);
return (1);
}
static arena * get_first_arena () {
/* return pointer to the first arena.
* scan memory for a 0x4D on a segment start,
* see if this points to another two levels of arena
*/
arena * ap, * ap1;
int * temp;
int segment;
for (segment=0; segment<_CS; segment++) {
ap = MK_FP(segment, 0);
if ( is_valid_arena (ap) == 0) return (ap);
}
return(NULL);
} /* end get_first_arena */
static int is_valid_env (char * ad, int num_segs) {
char * base_ad;
base_ad = ad;
while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) {
if (strnicmp(ad, "COMSPEC=", 8)==0) return(0);
ad += strlen(ad) + 1;
}
return (1);
}
static arena * get_arena_of_environment () {
/* to get the arena of first environment block:
First get segment of COMMAND.COM from segment of previous critical err code.
Then scan all the arenas for an environment block with a matching PSP
segment */
arena * ap;
psp * pspp, * pspc;
unsigned int i, ccseg;
/* set pspp to psp of this program */
pspp = MK_FP(_psp,0);
#ifdef DEBUG
printf("prog psp=%p\n",pspp);
#endif
/* set pspc to psp of COMMAND.COM, back up a bit to get it if needed */
ccseg = FP_SEG (pspp->prev_crit_error);
if ( (i=ccseg-32) < 60) i=60;
while (ccseg>i) {
pspc = MK_FP (ccseg, 0);
if ( is_valid_arena((arena *) pspc) == 0) goto L1;
ccseg--;
}
return (NULL);
L1: pspc = MK_FP (++ccseg, 0);
#ifdef DEBUG
printf("comm.com=%p\n",pspc);
#endif
/* first see if env seg in command.com points to valid env block
if env seg is in a valid arena, then arena must point to this command.com
else assume env block is fabricated like for 4DOS, use 128 bytes */
ap = MK_FP (pspc->envir_seg-1, 0);
i = ap->num_segments;
if (is_valid_arena (ap) == 0) {
if (ap->psp_segment != FP_SEG(pspc)) goto L2;
} else {
i = 9;
}
if ( is_valid_env (&ap->arena_data, i) == 0 )
return (ap);
/* command.com did not so point, search thru all env blocks */
L2:
if ( (ap=get_first_arena()) != NULL ) {
while (ap->type != LAST_ATYPE) {
#ifdef DEBUG
printf("%p\n",ap);
#endif
if (ap->psp_segment == FP_SEG(pspc) &&
is_valid_env (&ap->arena_data, ap->num_segments)==0 )
return (ap);
ap = get_next_arena(ap);
}
} return(NULL);
} /* end get_arena_of_environment */
/*****************************************************************************/
int settheenv(char * symbol, char * val) {
int total_size,
needed_size=0,
strlength;
char * sp, *op, *envir;
char symb_len=strlen(symbol);
char found=0;
arena * ap;
strupr(symbol);
/* first, can COMMAND.COM's envir block be found ? */
if ( (ap=get_arena_of_environment()) == NULL)
return(1);
/* search to end of the envir block, get sizes */
total_size = 16 * ap->num_segments;
envir = &ap->arena_data;
op=sp=envir;
while (*sp) {
strlength = strlen(sp)+1;
if ( *(sp+symb_len)=='=' &&
strnicmp(sp,symbol,symb_len)==0 )
found=1;
else {
needed_size += strlength;
if (found) strcpy(op,sp);
op = &op[strlength];
}
sp += strlength;
}
*op=0;
if (strlen(val) > 0) {
needed_size += 3 + strlen(symbol) + strlen(val);
if (needed_size > total_size)
return(1); /* could mess with environment expansion here */
strcpy(op, symbol); strcat(op, "="); strcat(op, val);
op += strlen(op)+1;
*op = 0;
}
return(0);
} /* end setheenv subroutine */
|