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