28512af707976ccda042f7911917e61ea3cadc1c
[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 static int
180 IsWindowsModule(const char * name)
181 {
182     char * p;
183     int i;
184
185     /* Do not perform searches for probable Windows modules */
186     for (p = name, i=0; *p; p++) {
187         if ( *p == '.' )
188             i++;
189     }
190     p = strrchr(name, '.');
191     if (p) {
192         if (i == 1 && 
193             (!stricmp(p,".dll") ||
194              !stricmp(p,".exe") ||
195              !stricmp(p,".ini") ||
196              !stricmp(p,".db") ||
197              !stricmp(p,".drv")))
198             return 1;
199     }
200     return 0;
201 }
202
203 /* search for a cell, and either return an error code if we don't find it,
204  * or return 0 if we do, in which case we also fill in the addresses in
205  * the cellp field.
206  *
207  * new feature:  we can handle abbreviations and are insensitive to case.
208  * If the caller wants the "real" cell name, it puts a non-null pointer in
209  * newCellNamep.  Anomaly:  if cellNamep is ambiguous, we may modify
210  * newCellNamep but return an error code.
211  */
212 long cm_SearchCellFile(char *cellNamep, char *newCellNamep,
213                        cm_configProc_t *procp, void *rockp)
214 {
215     char wdir[257];
216     FILE *tfilep = NULL, *bestp, *tempp;
217     char *tp;
218     char lineBuffer[257];
219     struct hostent *thp;
220     char *valuep;
221     struct sockaddr_in vlSockAddr;
222     int inRightCell;
223     int foundCell = 0;
224     long code;
225     int tracking = 1, partial = 0;
226 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
227     char *afsconf_path;
228     DWORD dwSize;
229 #endif
230
231     if ( IsWindowsModule(cellNamep) )
232         return -3;
233
234     cm_GetCellServDB(wdir);
235     tfilep = fopen(wdir, "r");
236
237 #if defined(DJGPP) || defined(AFS_WIN95_ENV)
238     if (!tfilep) {
239         /* If we are using DJGPP client, cellservdb will be in afsconf dir. */
240         /* If we are in Win95 here, we are linking with klog etc. and are
241         using DJGPP client even though DJGPP is not defined.  So we still
242         need to check AFSCONF for location. */
243         dwSize = GetEnvironmentVariable("AFSCONF", NULL, 0);
244         afsconf_path = malloc(dwSize);
245         dwSize = GetEnvironmentVariable("AFSCONF", afsconf_path, dwSize);
246         if (!afsconf_path)
247             strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
248         else {
249             strcpy(wdir, afsconf_path);
250             free(afsconf_path);
251         }
252         strcat(wdir, "/");
253         strcat(wdir, AFS_CELLSERVDB);
254         /*fprintf(stderr, "opening cellservdb file %s\n", wdir);*/
255         tfilep = fopen(wdir, "r");
256         if (!tfilep) 
257             return -2;
258     }
259 #else
260     /* If we are NT or higher, we don't do DJGPP, So just fail */
261     if ( !tfilep )
262         return -2;
263 #endif
264
265     bestp = fopen(wdir, "r");
266     
267 #ifdef DEBUG
268     DebugEvent_local("AFS- cm_searchfile fopen", "Handle[%x], wdir[%s]", bestp, wdir);
269 #endif
270
271     /* have we seen the cell line for the guy we're looking for? */
272     inRightCell = 0;
273     while (1) {
274         tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep);
275         if (tracking)
276             (void) fgets(lineBuffer, sizeof(lineBuffer), bestp);
277         if (    tp == NULL) {
278             if (feof(tfilep)) {
279                 /* hit EOF */
280                 if (partial) {
281                     /*
282                      * found partial match earlier;
283                      * now go back to it
284                      */
285                     tempp = bestp;
286                     bestp = tfilep;
287                     tfilep = tempp;
288                     inRightCell = 1;
289                     partial = 0;
290                     continue;
291                 }
292                 else {
293                     fclose(tfilep);
294                     fclose(bestp);
295                     return (foundCell? 0 : -3);
296                 }
297             }
298         }       
299
300         /* turn trailing cr or lf into null */
301         tp = strchr(lineBuffer, '\r');
302         if (tp) *tp = 0;
303         tp = strchr(lineBuffer, '\n');
304         if (tp) *tp = 0;
305
306         /* skip blank lines */
307         if (lineBuffer[0] == 0) continue;
308
309         if (lineBuffer[0] == '>') {
310             /* trim off at white space or '#' chars */
311             tp = strchr(lineBuffer, ' ');
312             if (tp) *tp = 0;
313             tp = strchr(lineBuffer, '\t');
314             if (tp) *tp = 0;
315             tp = strchr(lineBuffer, '#');
316             if (tp) *tp = 0;
317
318             /* now see if this is the right cell */
319             if (stricmp(lineBuffer+1, cellNamep) == 0) {
320                 /* found the cell we're looking for */
321                 if (newCellNamep)
322                     strcpy(newCellNamep, lineBuffer+1);
323                 inRightCell = 1;
324                 tracking = 0;
325 #ifdef DEBUG
326                 DebugEvent_local("AFS- cm_searchfile is cell", "inRightCell[%x], linebuffer[%s]", 
327                                  inRightCell, lineBuffer);
328 #endif
329             }
330             else if (strnicmp(lineBuffer+1, cellNamep,
331                                strlen(cellNamep)) == 0) {
332                 /* partial match */
333                 if (partial) {  /* ambiguous */
334                     fclose(tfilep);
335                     fclose(bestp);
336                     return -5;
337                 }
338                 if (newCellNamep)
339                     strcpy(newCellNamep, lineBuffer+1);
340                 inRightCell = 0;
341                 tracking = 0;
342                 partial = 1;
343             }
344             else inRightCell = 0;
345         }
346         else {
347 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
348             valuep = strchr(lineBuffer, '#');
349             if (valuep == NULL) {
350                 fclose(tfilep);
351                 fclose(bestp);
352                 return -4;
353             }
354             valuep++;   /* skip the "#" */
355
356             valuep += strspn(valuep, " \t"); /* skip SP & TAB */
357             /* strip spaces and tabs in the end. They should not be there according to CellServDB format
358              * so do this just in case                        
359              */
360             while (valuep[strlen(valuep) - 1] == ' ' || valuep[strlen(valuep) - 1] == '\t') 
361                 valuep[strlen(valuep) - 1] = '\0';
362
363 #endif /* !DJGPP */
364             if (inRightCell) {
365 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
366                 /* add the server to the VLDB list */
367                 WSASetLastError(0);
368                 thp = gethostbyname(valuep);
369 #ifdef DEBUG
370                 {
371                     int iErr = WSAGetLastError();
372                     DebugEvent_local("AFS- cm_searchfile inRightCell", 
373                                      "thp[%x], valuep[%s], WSAGetLastError[%d]", 
374                                      thp, valuep, iErr);
375                 }
376 #endif
377                 if (thp) {
378                     memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr,
379                             sizeof(long));
380                     vlSockAddr.sin_family = AF_INET;
381                     /* sin_port supplied by connection code */
382                     if (procp)
383                         (*procp)(rockp, &vlSockAddr, valuep);
384                     foundCell = 1;
385                 }
386 #else
387                 thp = 0;
388 #endif /* !DJGPP */
389                 if (!thp) {
390                     long ip_addr;
391                     int c1, c2, c3, c4;
392                     char aname[241] = "";                    
393                     
394                     /* Since there is no gethostbyname() data 
395                      * available we will read the IP address
396                      * stored in the CellServDB file
397                      */
398                     code = sscanf(lineBuffer, "%d.%d.%d.%d #%s",
399                                    &c1, &c2, &c3, &c4, aname);
400                     tp = (char *) &ip_addr;
401                     *tp++ = c1;
402                     *tp++ = c2;
403                     *tp++ = c3;
404                     *tp++ = c4;
405                     memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr,
406                             sizeof(long));
407                     vlSockAddr.sin_family = AF_INET;
408                     /* sin_port supplied by connection code */
409                     if (procp)
410                         (*procp)(rockp, &vlSockAddr, valuep);
411                     foundCell = 1;
412                 }
413             }
414         }       /* a vldb line */
415     }           /* while loop processing all lines */
416
417     /* if for some unknown reason cell is not found, return negative code (-11) ??? */
418     return (foundCell) ? 0 : -11;
419 }
420
421 long cm_SearchCellByDNS(char *cellNamep, char *newCellNamep, int *ttl,
422                cm_configProc_t *procp, void *rockp)
423 {
424 #ifdef AFS_AFSDB_ENV
425     int rc;
426     int  cellHostAddrs[AFSMAXCELLHOSTS];
427     char cellHostNames[AFSMAXCELLHOSTS][MAXHOSTCHARS];
428     int numServers;
429     int i;
430     struct sockaddr_in vlSockAddr;
431
432 #ifdef DEBUG
433     DebugEvent_local("AFS SearchCellDNS-","Doing search for [%s]", cellNamep);
434 #endif
435
436     if ( IsWindowsModule(cellNamep) )
437         return -1;
438     rc = getAFSServer(cellNamep, cellHostAddrs, cellHostNames, &numServers, ttl);
439     if (rc == 0 && numServers > 0) {     /* found the cell */
440         for (i = 0; i < numServers; i++) {
441             memcpy(&vlSockAddr.sin_addr.s_addr, &cellHostAddrs[i],
442                    sizeof(long));
443            vlSockAddr.sin_family = AF_INET;
444            /* sin_port supplied by connection code */
445            if (procp)
446           (*procp)(rockp, &vlSockAddr, cellHostNames[i]);
447            if(newCellNamep)
448           strcpy(newCellNamep,cellNamep);
449         }
450         return 0;   /* found cell */
451     }
452     else
453        return -1;  /* not found */
454 #else
455     return -1;  /* not found */
456 #endif /* AFS_AFSDB_ENV */
457 }
458
459 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
460 /* look up the CellServDBDir's name in the Registry 
461  * or use the Client Dirpath value to produce a CellServDB 
462  * filename
463  */
464 long cm_GetCellServDB(char *cellNamep)
465 {
466 #if !defined(DJGPP)
467         DWORD code, dummyLen;
468         HKEY parmKey;
469     int tlen;
470
471         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
472                                 0, KEY_QUERY_VALUE, &parmKey);
473         if (code != ERROR_SUCCESS)
474         goto dirpath;
475
476         dummyLen = 256;
477         code = RegQueryValueEx(parmKey, "CellServDBDir", NULL, NULL,
478                                 cellNamep, &dummyLen);
479         RegCloseKey (parmKey);
480
481   dirpath:
482         if (code != ERROR_SUCCESS || cellNamep[0] == 0)
483         strcpy(cellNamep, AFSDIR_CLIENT_ETC_DIRPATH);
484
485     /* add trailing backslash, if required */
486     tlen = (int)strlen(cellNamep);
487     if (cellNamep[tlen-1] != '\\') 
488         strcat(cellNamep, "\\");
489 #else
490     strcpy(cellNamep, cm_confDir);
491     strcat(cellNamep,"/");
492 #endif /* !DJGPP */
493         
494     strcat(cellNamep, AFS_CELLSERVDB);
495         return 0;
496 }
497
498 /* look up the root cell's name in the Registry */
499 long cm_GetRootCellName(char *cellNamep)
500 {
501         DWORD code, dummyLen;
502         HKEY parmKey;
503
504         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
505                                 0, KEY_QUERY_VALUE, &parmKey);
506         if (code != ERROR_SUCCESS)
507                 return -1;
508
509         dummyLen = 256;
510         code = RegQueryValueEx(parmKey, "Cell", NULL, NULL,
511                                 cellNamep, &dummyLen);
512         RegCloseKey (parmKey);
513         if (code != ERROR_SUCCESS || cellNamep[0] == 0)
514                 return -1;
515
516         return 0;
517 }
518 #else
519 /* look up the root cell's name in the THISCELL file */
520 long cm_GetRootCellName(char *cellNamep)
521 {
522         FILE *thisCell;
523         char thisCellPath[256];
524         char *newline;
525         DWORD dwSize;
526
527 #ifdef DJGPP
528         strcpy(thisCellPath, cm_confDir);
529 #else
530         /* Win 95 */
531         char *afsconf_path;
532         dwSize = GetEnvironmentVariable("AFSCONF", NULL, 0);
533         afsconf_path = malloc(dwSize);
534         dwSize = GetEnvironmentVariable("AFSCONF", afsconf_path, dwSize);
535         if (!afsconf_path)
536           strcpy(thisCellPath, AFSDIR_CLIENT_ETC_DIRPATH);
537         else {
538           strcpy(thisCellPath, afsconf_path);
539           free(afsconf_path);
540         }
541 #endif
542         strcat(thisCellPath,"/");
543
544         strcat(thisCellPath, AFS_THISCELL);
545         thisCell = fopen(thisCellPath, "r");
546         if (thisCell == NULL)
547           return -1;
548
549         fgets(cellNamep, 256, thisCell);
550         fclose(thisCell);
551
552         newline = strrchr(cellNamep,'\n');
553         if (newline) *newline = '\0';
554         newline = strrchr(cellNamep,'\r');
555         if (newline) *newline = '\0';
556
557         return 0;
558 }
559 #endif /* !DJGPP */
560
561 cm_configFile_t *cm_CommonOpen(char *namep, char *rwp)
562 {
563     char wdir[256];
564     long tlen;
565     FILE *tfilep;
566
567 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
568     strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
569         
570     /* add trailing backslash, if required */
571     tlen = (long)(strlen(wdir));
572     if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
573 #else
574 #ifdef DJGPP
575     strcpy(wdir,cm_confDir);
576 #else
577     DWORD dwSize;
578     char *afsconf_path;
579     
580     dwSize = GetEnvironmentVariable("AFSCONF", NULL, 0);
581     afsconf_path = malloc(dwSize);
582     dwSize = GetEnvironmentVariable("AFSCONF", afsconf_path, dwSize);
583
584     if (!afsconf_path)
585         strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
586     else {
587         strcpy(wdir, afsconf_path);
588         free(afsconf_path);
589     }
590 #endif /* !DJGPP */
591     strcat(wdir,"/");
592 #endif /* DJGPP || WIN95 */
593
594     strcat(wdir, namep);
595         
596     tfilep = fopen(wdir, rwp);
597
598     return ((cm_configFile_t *) tfilep);        
599 }       
600
601 #ifndef DJGPP
602 long cm_WriteConfigString(char *labelp, char *valuep)
603 {
604     DWORD code, dummyDisp;
605     HKEY parmKey;
606
607     code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
608                            0, "container", 0, KEY_SET_VALUE, NULL,
609                            &parmKey, &dummyDisp);
610     if (code != ERROR_SUCCESS)
611         return -1;
612
613     code = RegSetValueEx(parmKey, labelp, 0, REG_SZ,
614                           valuep, (DWORD)strlen(valuep) + 1);
615     RegCloseKey (parmKey);
616     if (code != ERROR_SUCCESS)
617         return (long)-1;
618
619     return (long)0;
620 }
621 #endif /* !DJGPP */
622
623 #ifndef DJGPP
624 long cm_WriteConfigInt(char *labelp, long value)
625 {
626         DWORD code, dummyDisp;
627         HKEY parmKey;
628
629         code = RegCreateKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_SVC_PARAM_SUBKEY,
630                                 0, "container", 0, KEY_SET_VALUE, NULL,
631                                 &parmKey, &dummyDisp);
632         if (code != ERROR_SUCCESS)
633                 return -1;
634
635         code = RegSetValueEx(parmKey, labelp, 0, REG_DWORD,
636                              (LPBYTE)&value, sizeof(value));
637         RegCloseKey (parmKey);
638         if (code != ERROR_SUCCESS)
639                 return -1;
640
641         return 0;
642 }
643 #endif /* !DJGPP */
644
645 cm_configFile_t *cm_OpenCellFile(void)
646 {
647         cm_configFile_t *cfp;
648
649         cfp = cm_CommonOpen("afsdcel2.ini", "w");
650         return cfp;
651 }
652
653 long cm_AppendPrunedCellList(cm_configFile_t *ofp, char *cellNamep)
654 {
655         cm_configFile_t *tfilep;        /* input file */
656         char *tp;
657         char lineBuffer[256];
658         char *valuep;
659         int inRightCell;
660         int foundCell;
661
662         tfilep = cm_CommonOpen(AFS_CELLSERVDB, "r");
663         if (!tfilep) return -1;
664
665         foundCell = 0;
666
667         /* have we seen the cell line for the guy we're looking for? */
668         inRightCell = 0;
669         while (1) {
670                 tp = fgets(lineBuffer, sizeof(lineBuffer), (FILE *)tfilep);
671                 if (tp == NULL) {
672                         if (feof((FILE *)tfilep)) {
673                                 /* hit EOF */
674                                 fclose((FILE *)tfilep);
675                                 return 0;
676                         }
677                 }
678                 
679                 /* turn trailing cr or lf into null */
680                 tp = strchr(lineBuffer, '\r');
681                 if (tp) *tp = 0;
682                 tp = strchr(lineBuffer, '\n');
683                 if (tp) *tp = 0;
684                 
685                 /* skip blank lines */
686                 if (lineBuffer[0] == 0) {
687                         fprintf((FILE *)ofp, "%s\n", lineBuffer);
688                         continue;
689                 }
690
691                 if (lineBuffer[0] == '>') {
692                         /* trim off at white space or '#' chars */
693                         tp = strchr(lineBuffer, ' ');
694                         if (tp) *tp = 0;
695                         tp = strchr(lineBuffer, '\t');
696                         if (tp) *tp = 0;
697                         tp = strchr(lineBuffer, '#');
698                         if (tp) *tp = 0;
699
700                         /* now see if this is the right cell */
701                         if (strcmp(lineBuffer+1, cellNamep) == 0) {
702                                 /* found the cell we're looking for */
703                                 inRightCell = 1;
704                         }
705                         else {
706                                 inRightCell = 0;
707                                 fprintf((FILE *)ofp, "%s\n", lineBuffer);
708                         }
709                 }
710                 else {
711                         valuep = strchr(lineBuffer, '#');
712                         if (valuep == NULL) return -2;
713                         valuep++;       /* skip the "#" */
714                         if (!inRightCell) {
715                                 fprintf((FILE *)ofp, "%s\n", lineBuffer);
716                         }
717                 }       /* a vldb line */
718         }               /* while loop processing all lines */
719 }
720
721 long cm_AppendNewCell(cm_configFile_t *filep, char *cellNamep)
722 {
723         fprintf((FILE *)filep, ">%s\n", cellNamep);
724         return 0;
725 }
726
727 long cm_AppendNewCellLine(cm_configFile_t *filep, char *linep)
728 {
729         fprintf((FILE *)filep, "%s\n", linep);
730         return 0;
731 }
732
733 long cm_CloseCellFile(cm_configFile_t *filep)
734 {
735     char wdir[256];
736     char sdir[256];
737     long code;
738     long closeCode;
739     int tlen;
740 #ifdef AFS_WIN95_ENV
741     char *afsconf_path;
742     DWORD dwSize;
743 #endif
744         closeCode = fclose((FILE *)filep);
745
746 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
747     strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
748         
749         /* add trailing backslash, if required */
750     tlen = (int)strlen(wdir);
751     if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
752 #else
753 #ifdef DJGPP
754     strcpy(wdir,cm_confDir);
755 #else
756     dwSize = GetEnvironmentVariable("AFSCONF", NULL, 0);
757     afsconf_path = malloc(dwSize);
758     dwSize = GetEnvironmentVariable("AFSCONF", afsconf_path, dwSize);
759     if (!afsconf_path)
760         strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
761     else {
762         strcpy(wdir, afsconf_path);
763         free(afsconf_path);
764     }
765 #endif /* !DJGPP */
766     strcat(wdir,"/");
767 #endif /* DJGPP || WIN95 */
768
769     strcpy(sdir, wdir);
770
771         if (closeCode != 0) {
772                 /* something went wrong, preserve original database */
773         strcat(wdir, "afsdcel2.ini");
774         unlink(wdir);
775         return closeCode;
776     }
777
778     strcat(wdir, AFS_CELLSERVDB);
779     strcat(sdir, "afsdcel2.ini");       /* new file */
780
781     unlink(wdir);                       /* delete old file */
782
783     code = rename(sdir, wdir);  /* do the rename */
784
785     if (code) 
786         code = errno;
787
788     return code;
789 }   
790
791 void cm_GetConfigDir(char *dir)
792 {
793         char wdir[256];
794     int tlen;
795 #ifdef AFS_WIN95_ENV
796     char *afsconf_path;
797     DWORD dwSize;
798 #endif
799
800 #if !defined(DJGPP) && !defined(AFS_WIN95_ENV)
801     strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
802         
803         /* add trailing backslash, if required */
804     tlen = (int)strlen(wdir);
805     if (wdir[tlen-1] != '\\') strcat(wdir, "\\");
806 #else
807 #ifdef DJGPP
808     strcpy(wdir,cm_confDir);
809 #else
810     dwSize = GetEnvironmentVariable("AFSCONF", NULL, 0);
811     afsconf_path = malloc(dwSize);
812     dwSize = GetEnvironmentVariable("AFSCONF", afsconf_path, dwSize);
813     if (!afsconf_path)
814         strcpy(wdir, AFSDIR_CLIENT_ETC_DIRPATH);
815     else {
816         strcpy(wdir, afsconf_path);
817         free(afsconf_path);
818     }
819 #endif /* !DJGPP */
820     strcat(wdir,"\\");
821 #endif /* DJGPP || WIN95 */
822     strcpy(dir, wdir);
823 }