batch-commits-windows-20040529
[openafs.git] / src / WINNT / afsd / cm_config.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afs/param.h>
11 #include <afs/stds.h>
12 #include <afs/cellconfig.h>
13
14 #ifndef DJGPP
15 #include <windows.h>
16 #include <winsock2.h>
17 #else
18 #include <sys/socket.h>
19 #include <netdb.h>
20 #endif /* !DJGPP */
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24
25 #include "cm_config.h"
26 #ifdef AFS_AFSDB_ENV
27 #include "cm_dns.h"
28 #include <afs/afsint.h>
29 #endif
30
31 char AFSConfigKeyName[] =
32         "SYSTEM\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters";
33
34 /* TODO: these should be pulled in from dirpath.h */
35 #define AFS_THISCELL "ThisCell"
36 #define AFS_CELLSERVDB_UNIX "CellServDB"
37 #define AFS_CELLSERVDB_NT "afsdcell.ini"
38 #ifndef AFSDIR_CLIENT_ETC_DIRPATH
39 #define AFSDIR_CLIENT_ETC_DIRPATH "c:/afs"
40 #endif
41 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
42 #define AFS_CELLSERVDB AFS_CELLSERVDB_UNIX
43 #ifdef DJGPP
44 extern char cm_confDir[];
45 extern int errno;
46 #endif /* DJGPP */
47 #else
48 #define AFS_CELLSERVDB AFS_CELLSERVDB_NT
49 #endif /* DJGPP || WIN95 */
50
51 #ifdef DEBUG
52 DWORD TraceOption=1;
53
54 #define TRACE_OPTION_EVENT 1
55 #define ISLOGONTRACE(v) ( ((v) & TRACE_OPTION_EVENT)==TRACE_OPTION_EVENT)
56
57 void DebugEvent0_local(char *a) 
58 {
59         HANDLE h; char *ptbuf[1];
60         if (!ISLOGONTRACE(TraceOption))
61                 return;
62         h = RegisterEventSource(NULL, a);
63         ptbuf[0] = a;
64         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);
65         DeregisterEventSource(h);
66 }
67
68 #define MAXBUF_ 512
69
70 void DebugEvent_local(char *a,char *b,...) 
71 {
72         HANDLE h; char *ptbuf[1],buf[MAXBUF_+1];
73         va_list marker;
74         if (!ISLOGONTRACE(TraceOption))
75                 return;
76         h = RegisterEventSource(NULL, a);
77         va_start(marker,b);
78         _vsnprintf(buf,MAXBUF_,b,marker);
79         ptbuf[0] = buf;
80         ReportEvent(h, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (const char **)ptbuf, NULL);\
81         DeregisterEventSource(h);
82         va_end(marker);
83 }
84 #endif /* DEBUG */
85
86 static long cm_ParsePair(char *lineBufferp, char *leftp, char *rightp)
87 {
88         char *tp;
89     char tc;
90     int sawEquals;
91         int sawBracket;
92         
93     sawEquals = 0;
94         sawBracket = 0;
95     for(tp = lineBufferp; *tp; tp++) {
96         tc = *tp;
97
98                 if (sawBracket) {
99                         if (tc == ']')
100                                 sawBracket = 0;
101                         continue;
102                 }
103
104                 /* comment or line end */
105         if (tc == '#' || tc == '\r' || tc == '\n') 
106             break;
107
108                 /* square bracket comment -- look for closing delim */
109                 if (tc == '[') {
110             sawBracket = 1; 
111             continue;
112         }
113
114                 /* space or tab */
115         if (tc == ' ' || tc == '\t') 
116             continue;
117
118         if (tc == '=') {
119             sawEquals = 1;
120             continue;
121                 }
122                 
123         /* now we have a real character, put it in the appropriate bucket */
124         if (sawEquals == 0) {
125                         *leftp++ = tc;
126         }
127         else {
128                         *rightp++ = tc;
129         }
130     }
131
132         /* null terminate the strings */
133         *leftp = 0;
134     *rightp = 0;
135
136     return 0;   /* and return success */
137 }
138
139 /* search for a cell, and either return an error code if we don't find it,
140  * or return 0 if we do, in which case we also fill in the addresses in
141  * the cellp field.
142  *
143  * new feature:  we can handle abbreviations and are insensitive to case.
144  * If the caller wants the "real" cell name, it puts a non-null pointer in
145  * newCellNamep.  Anomaly:  if cellNamep is ambiguous, we may modify
146  * newCellNamep but return an error code.
147  */
148 long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
149         cm_configProc_t *procp, void *rockp)
150 {
151         char wdir[257];
152     int tlen;
153     FILE *tfilep, *bestp, *tempp;
154     char *tp;
155     char lineBuffer[257];
156     struct hostent *thp;
157     char *valuep;
158     struct sockaddr_in vlSockAddr;
159     int inRightCell;
160     int foundCell;
161     long code;
162         int tracking = 1, partial = 0;
163 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
164     char *afsconf_path;
165 #endif
166
167         foundCell = 0;
168
169 #if !defined(DJGPP)
170         code = GetWindowsDirectory(wdir, sizeof(wdir));
171     if (code == 0 || code > sizeof(wdir))
172         return -1;
173
174         /* add trailing backslash, if required */
175     tlen = strlen(wdir);
176     if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
177 #else
178     strcpy(wdir, cm_confDir);
179     strcat(wdir,"/");
180 #endif /* !DJGPP */
181         
182     strcat(wdir, AFS_CELLSERVDB);
183
184     tfilep = fopen(wdir, "r");
185
186 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
187     if (!tfilep) {
188         /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
189         /* If we are in Win95 here, we are linking with klog etc. and are
190         using DJGPP client even though DJGPP is not defined.  So we still
191         need to check AFSCONF for location. */
192         afsconf_path = getenv("AFSCONF");
193         if (!afsconf_path)
194             strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
195         else
196             strcpy(wdir, afsconf_path);
197         strcat(wdir, "/");
198         strcat(wdir, AFS_CELLSERVDB_UNIX);
199         /*fprintf(stderr, "opening cellservdb file %s\n", wdir);*/
200         tfilep = fopen(wdir, "r");
201         if (!tfilep) return -2;
202     }
203 #else
204     /* If we are NT or higher, we don't do DJGPP, So just fail */
205     if ( !tfilep )
206         return -2;
207 #endif
208
209         bestp = fopen(wdir, "r");
210     
211 #ifdef DEBUG
212     DebugEvent_local("AFS- cm_searchfile fopen", "Handle[%x], wdir[%s]", bestp, wdir);
213 #endif
214
215         /* have we seen the cell line for the guy we're looking for? */
216         inRightCell = 0;
217         while (1) {
218         tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
219         if (tracking)
220                         (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
221         if (tp == NULL) {
222                         if (feof(tfilep)) {
223                                 /* hit EOF */
224                                 if (partial) {
225                                         /*
226                                          * found partial match earlier;
227                                          * now go back to it
228                                          */
229                                         tempp = bestp;
230                                         bestp = tfilep;
231                                         tfilep = tempp;
232                                         inRightCell = 1;
233                                         partial = 0;
234                                         continue;
235                                 }
236                                 else {
237                                         fclose(tfilep);
238                                         fclose(bestp);
239                                         return (foundCell? 0 : -3);
240                                 }
241                         }
242         }
243
244         /* turn trailing cr or lf into null */
245         tp = strchr(lineBuffer, '\r');
246         if (tp) *tp = 0;
247         tp = strchr(lineBuffer, '\n');
248         if (tp) *tp = 0;
249
250                 /* skip blank lines */
251         if (lineBuffer[0] == 0) continue;
252
253         if (lineBuffer[0] == '>') {
254                         /* trim off at white space or '#' chars */
255             tp = strchr(lineBuffer, ' ');
256             if (tp) *tp = 0;
257             tp = strchr(lineBuffer, '\t');
258             if (tp) *tp = 0;
259             tp = strchr(lineBuffer, '#');
260             if (tp) *tp = 0;
261
262                         /* now see if this is the right cell */
263             if (stricmp(lineBuffer+1, cellNamep) == 0) {
264                                 /* found the cell we're looking for */
265                                 if (newCellNamep)
266                                         strcpy(newCellNamep, lineBuffer+1);
267                 inRightCell = 1;
268                                 tracking = 0;
269 #ifdef DEBUG
270                 DebugEvent_local("AFS- cm_searchfile is cell", "inRightCell[%x], linebuffer[%s]", 
271                                  inRightCell, lineBuffer);
272 #endif
273                         }
274                         else if (strnicmp(lineBuffer+1, cellNamep,
275                                strlen(cellNamep)) == 0) {
276                                 /* partial match */
277                                 if (partial) {  /* ambiguous */
278                                         fclose(tfilep);
279                                         fclose(bestp);
280                                         return -5;
281                                 }
282                                 if (newCellNamep)
283                                         strcpy(newCellNamep, lineBuffer+1);
284                                 inRightCell = 0;
285                                 tracking = 0;
286                                 partial = 1;
287                         }
288             else inRightCell = 0;
289         }
290         else {
291 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
292             valuep = strchr(lineBuffer, '#');
293                         if (valuep == NULL) {
294                                 fclose(tfilep);
295                                 fclose(bestp);
296                                 return -4;
297                         }
298             valuep++;   /* skip the "#" */
299
300             valuep += strspn(valuep, " \t"); /* skip SP & TAB */
301             /* strip spaces and tabs in the end. They should not be there according to CellServDB format
302             so do this just in case                        */
303             while (valuep[strlen(valuep) - 1] == ' ' || valuep[strlen(valuep) - 1] == '\t') 
304                 valuep[strlen(valuep) - 1] = '\0';
305
306 #endif /* !DJGPP */
307                         if (inRightCell) {
308 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
309                                 /* add the server to the VLDB list */
310                 WSASetLastError(0);
311                 thp = gethostbyname(valuep);
312 #ifdef DEBUG
313                 {
314                     int iErr = WSAGetLastError();
315                     DebugEvent_local("AFS- cm_searchfile inRightCell", 
316                                      "thp[%x], valuep[%s], WSAGetLastError[%d]", 
317                                      thp, valuep, iErr);
318                 }
319 #endif
320                 if (thp) {
321                                         memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
322                             sizeof(long));
323                     vlSockAddr.sin_family = AF_INET;
324                     /* sin_port supplied by connection code */
325                                         if (procp)
326                                                 (*procp)(rockp, &vlSockAddr, valuep);
327                     foundCell = 1;
328                                 }
329 #else
330                 thp = 0;
331 #endif /* !DJGPP */
332                 if (!thp) {
333                     long ip_addr;
334                                         int c1, c2, c3, c4;
335                                         char aname[241] = "";                    
336                     
337                     /* Since there is no gethostbyname() data 
338                      * available we will read the IP address
339                      * stored in the CellServDB file
340                      */
341                     code = sscanf(lineBuffer, "%d.%d.%d.%d #%s",
342                                    &c1, &c2, &c3, &c4, aname);
343                     tp = (char *) &ip_addr;
344                     *tp++ = c1;
345                     *tp++ = c2;
346                     *tp++ = c3;
347                     *tp++ = c4;
348                     memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
349                             sizeof(long));
350                     vlSockAddr.sin_family = AF_INET;
351                     /* sin_port supplied by connection code */
352                     if (procp)
353                         (*procp)(rockp, &vlSockAddr, valuep);
354                     foundCell = 1;
355                 }
356             }
357         }       /* a vldb line */
358     }           /* while loop processing all lines */
359
360     /* if for some unknown reason cell is not found, return negative code (-11) ??? */
361     return (foundCell) ? 0 : -11;
362 }
363
364 long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
365                cm_configProc_t *procp, void *rockp)
366 {
367 #ifdef AFS_AFSDB_ENV
368     int rc;
369     int  cellHostAddrs[AFSMAXCELLHOSTS];
370     char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
371     int numServers;
372     int i;
373     struct sockaddr_in vlSockAddr;
374
375 #ifdef DEBUG
376     DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
377 #endif
378     rc = getAFSServer(cellNamep, cellHostAddrs, cellHostNames, &numServers, ttl);
379     if (rc == 0 && numServers > 0) {     /* found the cell */
380         for (i = 0; i < numServers; i++) {
381             memcpy(&vlSockAddr.sin_addr.s_addr, &cellHostAddrs[i],
382                    sizeof(long));
383            vlSockAddr.sin_family = AF_INET;
384            /* sin_port supplied by connection code */
385            if (procp)
386           (*procp)(rockp, &vlSockAddr, cellHostNames[i]);
387            if(newCellNamep)
388           strcpy(newCellNamep,cellNamep);
389         }
390         return 0;   /* found cell */
391     }
392     else
393        return -1;  /* not found */
394 #else
395         return -1;  /* not found */
396 #endif /* AFS_AFSDB_ENV */
397 }
398
399 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
400 /* look up the root cell's name in the Registry */
401 long cm_GetRootCellName(char *cellNamep)
402 {
403         DWORD code, dummyLen;
404         HKEY parmKey;
405
406         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
407                                 0, KEY_QUERY_VALUE, &parmKey);
408         if (code != ERROR_SUCCESS)
409                 return -1;
410
411         dummyLen = 256;
412         code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
413                                 cellNamep, &dummyLen);
414         RegCloseKey (parmKey);
415         if (code != ERROR_SUCCESS || cellNamep[0] == 0)
416                 return -1;
417
418         return 0;
419 }
420 #else
421 /* look up the root cell's name in the THISCELL file */
422 long cm_GetRootCellName(char *cellNamep)
423 {
424         FILE *thisCell;
425         char thisCellPath[256];
426         char *newline;
427
428 #ifdef DJGPP
429         strcpy(thisCellPath, cm_confDir);
430 #else
431         /* Win 95 */
432         char *afsconf_path;
433         afsconf_path = getenv("AFSCONF");
434         if (!afsconf_path)
435           strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
436         else
437           strcpy(thisCellPath, afsconf_path);
438 #endif
439         strcat(thisCellPath,"/");
440
441         strcat(thisCellPath, AFS_THISCELL);
442         thisCell = fopen(thisCellPath, "r");
443         if (thisCell == NULL)
444           return -1;
445
446         fgets(cellNamep, 256, thisCell);
447         fclose(thisCell);
448
449         newline = strrchr(cellNamep,'\n');
450         if (newline) *newline = '\0';
451         newline = strrchr(cellNamep,'\r');
452         if (newline) *newline = '\0';
453
454         return 0;
455 }
456 #endif /* !DJGPP */
457
458 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
459 {
460         char wdir[256];
461     long code;
462     long tlen;
463     FILE *tfilep;
464
465 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
466         code = GetWindowsDirectory(wdir, sizeof(wdir));
467         if (code == 0 || code > sizeof(wdir)) 
468             return 0;
469         
470         /* add trailing backslash, if required */
471         tlen = strlen(wdir);
472         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
473 #else
474 #ifdef DJGPP
475         strcpy(wdir,cm_confDir);
476 #else
477         char *afsconf_path = getenv("AFSCONF");
478         if (!afsconf_path)
479           strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
480         else
481           strcpy(wdir, afsconf_path);
482 #endif /* !DJGPP */
483         strcat(wdir,"/");
484 #endif /* DJGPP || WIN95 */
485
486         strcat(wdir, namep);
487         
488         tfilep = fopen(wdir, rwp);
489
490         return ((cm_configFile_t *) tfilep);        
491 }
492
493 #ifndef DJGPP
494 long cm_WriteConfigString(char *labelp, char *valuep)
495 {
496         DWORD code, dummyDisp;
497         HKEY parmKey;
498
499         code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
500                                 0, "container", 0, KEY_SET_VALUE, NULL,
501                                 &parmKey, &dummyDisp);
502         if (code != ERROR_SUCCESS)
503                 return -1;
504
505         code = RegSetValueEx(parmKey, labelp, 0, REG_SZ,
506                              valuep, strlen(valuep) + 1);
507         RegCloseKey (parmKey);
508         if (code != ERROR_SUCCESS)
509                 return -1;
510
511         return 0;
512 }
513 #endif /* !DJGPP */
514
515 #ifndef DJGPP
516 long cm_WriteConfigInt(char *labelp, long value)
517 {
518         DWORD code, dummyDisp;
519         HKEY parmKey;
520
521         code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSConfigKeyName,
522                                 0, "container", 0, KEY_SET_VALUE, NULL,
523                                 &parmKey, &dummyDisp);
524         if (code != ERROR_SUCCESS)
525                 return -1;
526
527         code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
528                              (LPBYTE)&value, sizeof(value));
529         RegCloseKey (parmKey);
530         if (code != ERROR_SUCCESS)
531                 return -1;
532
533         return 0;
534 }
535 #endif /* !DJGPP */
536
537 cm_configFile_t *cm_OpenCellFile(void)
538 {
539         cm_configFile_t *cfp;
540
541         cfp = cm_CommonOpen("afsdcel2.ini", "w");
542         return cfp;
543 }
544
545 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
546 {
547         cm_configFile_t *tfilep;        /* input file */
548         char *tp;
549         char lineBuffer[256];
550         char *valuep;
551         int inRightCell;
552         int foundCell;
553
554         tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
555         if (!tfilep) return -1;
556
557         foundCell = 0;
558
559         /* have we seen the cell line for the guy we're looking for? */
560         inRightCell = 0;
561         while (1) {
562                 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
563                 if (tp == NULL) {
564                         if (feof((FILE *)tfilep)) {
565                                 /* hit EOF */
566                                 fclose((FILE *)tfilep);
567                                 return 0;
568                         }
569                 }
570                 
571                 /* turn trailing cr or lf into null */
572                 tp = strchr(lineBuffer, '\r');
573                 if (tp) *tp = 0;
574                 tp = strchr(lineBuffer, '\n');
575                 if (tp) *tp = 0;
576                 
577                 /* skip blank lines */
578                 if (lineBuffer[0] == 0) {
579                         fprintf((FILE *)ofp, "%s\n", lineBuffer);
580                         continue;
581                 }
582
583                 if (lineBuffer[0] == '>') {
584                         /* trim off at white space or '#' chars */
585                         tp = strchr(lineBuffer, ' ');
586                         if (tp) *tp = 0;
587                         tp = strchr(lineBuffer, '\t');
588                         if (tp) *tp = 0;
589                         tp = strchr(lineBuffer, '#');
590                         if (tp) *tp = 0;
591
592                         /* now see if this is the right cell */
593                         if (strcmp(lineBuffer+1, cellNamep) == 0) {
594                                 /* found the cell we're looking for */
595                                 inRightCell = 1;
596                         }
597                         else {
598                                 inRightCell = 0;
599                                 fprintf((FILE *)ofp, "%s\n", lineBuffer);
600                         }
601                 }
602                 else {
603                         valuep = strchr(lineBuffer, '#');
604                         if (valuep == NULL) return -2;
605                         valuep++;       /* skip the "#" */
606                         if (!inRightCell) {
607                                 fprintf((FILE *)ofp, "%s\n", lineBuffer);
608                         }
609                 }       /* a vldb line */
610         }               /* while loop processing all lines */
611 }
612
613 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
614 {
615         fprintf((FILE *)filep, ">%s\n", cellNamep);
616         return 0;
617 }
618
619 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
620 {
621         fprintf((FILE *)filep, "%s\n", linep);
622         return 0;
623 }
624
625 long cm_CloseCellFile(cm_configFile_t *filep)
626 {
627         char wdir[256];
628     char sdir[256];
629     long code;
630     long closeCode;
631     int tlen;
632 #ifdef AFS_WIN95_ENV
633     char *afsconf_path;
634 #endif
635         closeCode = fclose((FILE *)filep);
636
637 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
638         code = GetWindowsDirectory(wdir, sizeof(wdir));
639         if (code == 0 || code > sizeof(wdir)) 
640             return closeCode;
641         
642         /* add trailing backslash, if required */
643         tlen = strlen(wdir);
644         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
645 #else
646 #ifdef DJGPP
647         strcpy(wdir,cm_confDir);
648 #else
649         afsconf_path = getenv("AFSCONF");
650         if (!afsconf_path)
651           strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
652         else
653           strcpy(wdir, afsconf_path);
654 #endif /* !DJGPP */
655         strcat(wdir,"/");
656 #endif /* DJGPP || WIN95 */
657
658         strcpy(sdir, wdir);
659
660         if (closeCode != 0) {
661                 /* something went wrong, preserve original database */
662                 strcat(wdir, "afsdcel2.ini");
663                 unlink(wdir);
664                 return closeCode;
665         }
666
667         strcat(wdir, AFS_CELLSERVDB);
668         strcat(sdir, "afsdcel2.ini");   /* new file */
669         
670         unlink(wdir);                   /* delete old file */
671         
672         code = rename(sdir, wdir);      /* do the rename */
673         
674         if (code) 
675           code = errno;
676         
677         return code;
678 }
679
680 void cm_GetConfigDir(char *dir)
681 {
682         char wdir[256];
683     int code;
684     int tlen;
685 #ifdef AFS_WIN95_ENV
686     char *afsconf_path;
687 #endif
688
689 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
690         code = GetWindowsDirectory(wdir, sizeof(wdir));
691       if (code == 0 || code > sizeof(wdir)) wdir[0] = 0;
692         
693         /* add trailing backslash, if required */
694         tlen = strlen(wdir);
695         if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
696 #else
697 #ifdef DJGPP
698         strcpy(wdir,cm_confDir);
699 #else
700         afsconf_path = getenv("AFSCONF");
701         if (!afsconf_path)
702           strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
703         else
704           strcpy(wdir, afsconf_path);
705 #endif /* !DJGPP */
706         strcat(wdir,"\\");
707 #endif /* DJGPP || WIN95 */
708         strcpy(dir, wdir);
709 }