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