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