[tg3] Recognize the BCM5789
[people/balajirrao/gpxe.git] / contrib / romid / setenvs.c
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.
5
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.
9
10    returns: 0 = OK,
11             1 = failure.
12    failure is not unlikely.  The env block may be full.  Or on some
13    systems the env block might not be found
14
15    SETENVS.C was written by Richard Marks <rmarks@KSP.unisys.COM>.
16 */
17
18
19 #include <stdio.h>
20 #include <dos.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 typedef struct {
25     char fill1[0x0A];
26     int *prev_term_handler;
27     int *prev_ctrl_c;
28     int *prev_crit_error;
29     char fill2[0x16];
30     int  envir_seg;
31 } psp;
32
33 typedef struct {
34     char  type;
35     int   psp_segment;
36     int   num_segments;
37     char  fill[11];
38     char  arena_data;
39 } arena;
40
41
42 #define NORMAL_ATYPE 0x4D
43 #define LAST_ATYPE   0x5A
44
45
46 static arena * get_next_arena (arena * ap) {
47     return( MK_FP( FP_SEG(ap)+1+ap->num_segments, 0) );
48 }
49
50 /* returns 0 if passed pointer is to an arena, else returns 1 */
51 static int is_valid_arena (arena * ap) {
52     arena * ap1;
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) )
57             return(0);
58     return (1);
59 }
60
61
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
66  */
67     arena * ap, * ap1;
68     int * temp;
69     int segment;
70
71     for (segment=0; segment<_CS;  segment++) {
72         ap = MK_FP(segment, 0);
73         if ( is_valid_arena (ap) == 0)  return (ap);
74     }
75     return(NULL);
76 } /* end get_first_arena */
77
78
79 static int is_valid_env (char * ad, int num_segs) {
80     char * base_ad;
81     base_ad = ad;
82     while ( (*ad) && (((ad-base_ad)>>4) < num_segs) ) {
83         if (strnicmp(ad, "COMSPEC=", 8)==0)  return(0);
84         ad += strlen(ad) + 1;
85     }
86     return (1);
87 }
88
89
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
94    segment */
95
96 arena * ap;
97 psp   * pspp, * pspc;
98 unsigned int i, ccseg;
99
100 /* set pspp to psp of this program */
101 pspp = MK_FP(_psp,0);
102
103 #ifdef DEBUG
104 printf("prog psp=%p\n",pspp);
105 #endif
106
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;
110
111 while (ccseg>i) {
112     pspc = MK_FP (ccseg, 0);
113     if ( is_valid_arena((arena *) pspc) == 0)  goto L1;
114     ccseg--;
115 }
116 return (NULL);
117
118 L1: pspc = MK_FP (++ccseg, 0);
119 #ifdef DEBUG
120 printf("comm.com=%p\n",pspc);
121 #endif
122
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 */
126
127 ap = MK_FP (pspc->envir_seg-1, 0);
128 i  = ap->num_segments;
129
130 if (is_valid_arena (ap) == 0) {
131     if (ap->psp_segment != FP_SEG(pspc))  goto L2;
132 } else {
133     i = 9;
134 }
135
136 if ( is_valid_env (&ap->arena_data, i) == 0 )
137     return (ap);
138
139 /* command.com did not so point, search thru all env blocks */
140
141 L2:
142 if ( (ap=get_first_arena()) != NULL ) {
143     while (ap->type != LAST_ATYPE) {
144 #ifdef DEBUG
145         printf("%p\n",ap);
146 #endif
147         if (ap->psp_segment == FP_SEG(pspc) &&
148             is_valid_env (&ap->arena_data, ap->num_segments)==0 )
149             return (ap);
150
151         ap = get_next_arena(ap);
152     }
153 } return(NULL);
154 }  /* end get_arena_of_environment */
155
156 /*****************************************************************************/
157
158 int settheenv(char * symbol, char * val) {
159 int total_size,
160     needed_size=0,
161     strlength;
162 char * sp, *op, *envir;
163 char symb_len=strlen(symbol);
164 char found=0;
165 arena * ap;
166
167 strupr(symbol);
168
169 /* first, can COMMAND.COM's envir block be found ? */
170 if ( (ap=get_arena_of_environment()) == NULL)
171     return(1);
172
173 /* search to end of the envir block, get sizes */
174 total_size = 16 * ap->num_segments;
175 envir = &ap->arena_data;
176 op=sp=envir;
177 while (*sp) {
178     strlength = strlen(sp)+1;
179     if ( *(sp+symb_len)=='='  &&
180          strnicmp(sp,symbol,symb_len)==0 )
181         found=1;
182     else {
183         needed_size += strlength;
184         if (found) strcpy(op,sp);
185         op = &op[strlength];
186     }
187     sp += strlength;
188 }
189 *op=0;
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 */
194
195     strcpy(op, symbol); strcat(op, "="); strcat(op, val);
196     op += strlen(op)+1;
197     *op = 0;
198 }
199 return(0);
200 } /* end setheenv subroutine */