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