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