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