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