1 /*
2 Copyright (c) 1990-2000 Info-ZIP. All rights reserved.
3
4 See the accompanying file LICENSE, version 2000-Apr-09 or later
5 (the contents of which are also included in zip.h) for terms of use.
6 If, for some reason, all these files are missing, the Info-ZIP license
7 also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html
8 */
9 /*
10
11 This file implements the getenv() function.
12
13 # Background:
14 # Under Unix: Each Process (= running Program) has a set of
15 # associated variables. The variables are called enviroment
16 # variables and, together, constitute the process environment.
17 # These variables include the search path, the terminal type,
18 # and the user's login name.
19
20 # Unfortunatelly the MacOS has no equivalent. So we need
21 # a file to define the environment variables.
22 # Name of this file is "MacZip.Env". It can be placed
23 # in the current folder of MacZip or in the
24 # preference folder of the system disk.
25 # If MacZip founds the "MacZip.Env" file in the current
26 # the folder of MacZip the "MacZip.Env" file in the
27 # preference folder will be ignored.
28
29 # An environment variable has a name and a value:
30 # Name=Value
31 # Note: Spaces are significant:
32 # ZIPOPT=-r and
33 # ZIPOPT = -r are different !!!
34
35
36 */
37
38 /*****************************************************************************/
39 /* Includes */
40 /*****************************************************************************/
41
42 #include <stdio.h>
43 #include <string.h>
44 #include <stdlib.h>
45 #include <time.h>
46 #include <unix.h>
47 #include <Files.h>
48 #include <Folders.h>
49
50 #include "pathname.h"
51 #include "helpers.h"
52
53 /*****************************************************************************/
54 /* Module level Vars */
55 /*****************************************************************************/
56
57 static char ListAllKeyValues = 0;
58 static unsigned LineNumber = 0;
59 static char CompletePath[NAME_MAX];
60 Boolean IgnoreEnvironment = false; /* used by dialog.c and initfunc.c
61 of the Mainapp */
62
63 /*****************************************************************************/
64 /* Macros, typedefs */
65 /*****************************************************************************/
66
67 typedef struct _EnviromentPair {
68 char *key;
69 char *value;
70 } EnviromentPair;
71
72
73 #define MAX_COMMAND 1024
74
75
76 /*****************************************************************************/
77 /* Prototypes */
78 /*****************************************************************************/
79
80
81 int get_char(FILE *file);
82 void unget_char(int ch,FILE *file);
83 int get_string(char *string,int size, FILE *file, char *terms);
84 void skip_comments(FILE *file);
85 char *load_entry(FILE *file);
86 char *getenv(const char *name);
87 EnviromentPair *ParseLine(char *line);
88 OSErr FSpFindFolder_Name(short vRefNum, OSType folderType,
89 Boolean createFolder,FSSpec *spec, unsigned char *name);
90 FILE * FSp_fopen(ConstFSSpecPtr spec, const char * open_mode);
91 void ShowAllKeyValues(void);
92 void Set_LineNum(unsigned ln);
93
94 /*****************************************************************************/
95 /* Functions */
96 /*****************************************************************************/
97
98
99 /* get_string(str, max, file, termstr) : like fgets() but
100 * (1) has terminator string which should include \n
101 * (2) will always leave room for the null
102 * (3) uses get_char() so LineNumber will be accurate
103 * (4) returns EOF or terminating character, whichever
104 */
get_string(char * string,int size,FILE * file,char * terms)105 int get_string(char *string, int size, FILE *file, char *terms)
106 {
107 int ch;
108
109 while (EOF != (ch = get_char(file)) && !strchr(terms, ch)) {
110 if (size > 1) {
111 *string++ = (char) ch;
112 size--;
113 }
114 }
115
116 if (size > 0)
117 {
118 *string = '\0';
119 }
120
121 return ch;
122 }
123
124
125
126
Set_LineNum(unsigned ln)127 void Set_LineNum(unsigned ln)
128 {
129 LineNumber = ln;
130 }
131
132
133
134 /* get_char(file) : like getc() but increment LineNumber on newlines
135 */
get_char(FILE * file)136 int get_char(FILE *file)
137 {
138 int ch;
139
140 ch = getc(file);
141 if (ch == '\n')
142 {
143 Set_LineNum(LineNumber + 1);
144 }
145
146 return ch;
147 }
148
149
150
151
152 /* skip_comments(file) : read past comment (if any)
153 */
skip_comments(FILE * file)154 void skip_comments(FILE *file)
155 {
156 int ch;
157
158 while (EOF != (ch = get_char(file)))
159 {
160 /* ch is now the first character of a line.
161 */
162
163 while (ch == ' ' || ch == '\t')
164 {
165 ch = get_char(file);
166 }
167
168 if (ch == EOF)
169 {
170 break;
171 }
172
173 /* ch is now the first non-blank character of a line.
174 */
175
176 if (ch != '\n' && ch != '#')
177 {
178 break;
179 }
180
181 /* ch must be a newline or comment as first non-blank
182 * character on a line.
183 */
184
185 while (ch != '\n' && ch != EOF)
186 {
187 ch = get_char(file);
188 }
189
190 /* ch is now the newline of a line which we're going to
191 * ignore.
192 */
193 }
194
195 if (ch != EOF)
196 {
197 unget_char(ch, file);
198 }
199 }
200
201
202
203
204 /* unget_char(ch, file) : like ungetc but do LineNumber processing
205 */
unget_char(int ch,FILE * file)206 void unget_char(int ch, FILE *file)
207 {
208 ungetc(ch, file);
209 if (ch == '\n')
210 {
211 Set_LineNum(LineNumber - 1);
212 }
213 }
214
215
216 /* this function reads one file entry -- the next -- from a file.
217 * it skips any leading blank lines, ignores comments, and returns
218 * NULL if for any reason the entry can't be read and parsed.
219 */
220
load_entry(FILE * file)221 char *load_entry(FILE *file)
222 {
223 int ch;
224 static char cmd[MAX_COMMAND];
225
226 skip_comments(file);
227
228 ch = get_string(cmd, MAX_COMMAND, file, "\n");
229
230 if (ch == EOF)
231 {
232 return NULL;
233 }
234
235 return cmd;
236 }
237
238
239
240
241
ParseLine(char * line)242 EnviromentPair *ParseLine(char *line)
243 {
244 char *tmpPtr;
245 static EnviromentPair *Env;
246 unsigned short length = strlen(line);
247
248 Env->key = "";
249 Env->value = "";
250
251 for (tmpPtr = line; *tmpPtr; tmpPtr++)
252 {
253 if (*tmpPtr == '=')
254 {
255 *tmpPtr = 0;
256 Env->key = line;
257 if (strlen(Env->key) < length)
258 {
259 Env->value = ++tmpPtr;
260 }
261 return Env;
262 }
263 }
264 return Env;
265 }
266
267
268
269
270
getenv(const char * name)271 char *getenv(const char *name)
272 {
273 FILE *fp;
274 char *LineStr = NULL;
275 EnviromentPair *Env1;
276 FSSpec spec;
277 OSErr err;
278
279 if (IgnoreEnvironment)
280 return NULL; /* user wants to ignore the environment vars */
281
282 if (name == NULL)
283 return NULL;
284
285 GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
286
287 /* try open the file in the current folder */
288 fp = FSp_fopen(&spec,"r");
289 if (fp == NULL)
290 { /* Okey, lets try open the file in the preference folder */
291 FSpFindFolder_Name(
292 kOnSystemDisk,
293 kPreferencesFolderType,
294 kDontCreateFolder,
295 &spec,
296 "\pMacZip.Env");
297 fp = FSp_fopen(&spec,"r");
298 if (fp == NULL)
299 {
300 return NULL; /* there is no enviroment-file */
301 }
302 }
303
304 LineStr = load_entry(fp);
305 while (LineStr != NULL)
306 { /* parse the file line by line */
307 Env1 = ParseLine(LineStr);
308 if (strlen(Env1->value) > 0)
309 { /* we found a key/value pair */
310 if (ListAllKeyValues)
311 printf("\n Line:%3d [%s] = [%s]",LineNumber,Env1->key,Env1->value);
312 if (stricmp(name,Env1->key) == 0)
313 { /* we found the value of a given key */
314 return Env1->value;
315 }
316 }
317 LineStr = load_entry(fp); /* read next line */
318 }
319 fclose(fp);
320
321 return NULL;
322 }
323
324
325
326
327
FSpFindFolder_Name(short vRefNum,OSType folderType,Boolean createFolder,FSSpec * spec,unsigned char * name)328 OSErr FSpFindFolder_Name(
329 short vRefNum, /* Volume reference number. */
330 OSType folderType, /* Folder type taken by FindFolder. */
331 Boolean createFolder, /* Should we create it if non-existant. */
332 FSSpec *spec, /* Pointer to resulting directory. */
333 unsigned char *name) /* Name of the file in the folder */
334 {
335 short foundVRefNum;
336 long foundDirID;
337 OSErr err;
338
339 err = FindFolder(vRefNum, folderType, createFolder,
340 &foundVRefNum, &foundDirID);
341 if (err != noErr)
342 {
343 return err;
344 }
345
346 err = FSMakeFSSpec(foundVRefNum, foundDirID, name, spec);
347 return err;
348 }
349
350
351
352
ShowAllKeyValues(void)353 void ShowAllKeyValues(void)
354 {
355 OSErr err;
356 FSSpec spec;
357 Boolean tmpIgnoreEnvironment = IgnoreEnvironment;
358
359 ListAllKeyValues = 1;
360 IgnoreEnvironment = false;
361
362 GetCompletePath(CompletePath,"MacZip.Env",&spec,&err);
363 if (err != 0)
364 { /* Okey, lets try open the file in the preference folder */
365 FSpFindFolder_Name(
366 kOnSystemDisk,
367 kPreferencesFolderType,
368 kDontCreateFolder,
369 &spec,
370 "\pMacZip.Env");
371 GetFullPathFromSpec(CompletePath,&spec, &err);
372 if (err != 0)
373 {
374 return; /* there is no enviroment-file */
375 }
376 }
377
378 printf("\nLocation of the current \"MacZip.Env\" file:\n [%s]",CompletePath);
379
380 printf("\n\nList of all environment variables\n");
381 getenv(" ");
382 printf("\n\nEnd\n\n");
383
384 /* restore used variables */
385 ListAllKeyValues = 0;
386 LineNumber = 0;
387 IgnoreEnvironment = tmpIgnoreEnvironment;
388 }
389
390
391
392
393
394
395
396
397
398
399