windows-pcache-20050310
[openafs.git] / src / WINNT / client_config / cellservdb.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 #include <stdio.h>
14 #include <string.h>
15 #include <memory.h>
16 #include <malloc.h>
17 #include "cellservdb.h"
18
19 #ifdef AFS_NT40_ENV
20 #include <windows.h>
21 #include <winsock2.h>
22 #else
23 #include <sys/socket.h>
24 #endif
25 #include <WINNT\afsreg.h>
26
27 /*
28  * PROTOTYPES _________________________________________________________________
29  *
30  */
31
32 #define new(_t)     (_t*)malloc(sizeof(_t))
33 #define delete(_p)  free((void*)(_p))
34
35 #ifndef iswhite
36 #define iswhite(_ch) (((_ch)==' ') || ((_ch)=='\t'))
37 #endif
38 #ifndef iseol
39 #define iseol(_ch) (((_ch)=='\r') || ((_ch)=='\n'))
40 #endif
41 #ifndef iswhiteeol
42 #define iswhiteeol(_ch) (iswhite(_ch) || iseol(_ch))
43 #endif
44 #ifndef min
45 #define min(_a,_b) ((_a) < (_b) ? (_a) : (_b))
46 #endif
47
48
49 /*
50  * STATICS ____________________________________________________________________
51  *
52  */
53
54 static void strzcpy (char *pszTarget, const char *pszSource, size_t cch)
55 {
56    cch = min(cch, (size_t)(1+strlen(pszSource)));
57    strncpy (pszTarget, pszSource, cch-1);
58    pszTarget[ cch-1 ] = '\0';
59 }
60
61
62 /*
63  * ROUTINES ___________________________________________________________________
64  *
65  */
66
67 void CSDB_GetFileName (char *pszFilename)
68 {
69 #ifdef AFS_NT40_ENV
70    /* Find the appropriate CellServDB */
71     char * clientdir = 0;
72         DWORD code, dummyLen;
73         HKEY parmKey;
74     int tlen;
75
76         code = RegOpenKeyEx(HKEY_LOCAL_MACHINE, AFSREG_CLT_OPENAFS_SUBKEY,
77                                 0, KEY_QUERY_VALUE, &parmKey);
78         if (code != ERROR_SUCCESS)
79         goto dirpath;
80
81         dummyLen = MAX_CSDB_PATH;
82         code = RegQueryValueEx(parmKey, "CellServDBDir", NULL, NULL,
83                                 pszFilename, &dummyLen);
84         RegCloseKey (parmKey);
85
86   dirpath:
87         if (code != ERROR_SUCCESS || pszFilename[0] == 0) {
88         afssw_GetClientInstallDir(&clientdir);
89         if (clientdir) {
90             strncpy(pszFilename, clientdir, MAX_CSDB_PATH);
91             pszFilename[MAX_CSDB_PATH - 1] = '\0';
92         }
93     }
94     if (pszFilename[ strlen(pszFilename)-1 ] != '\\')
95       strcat (pszFilename, "\\");
96
97    strcat (pszFilename, "CellServDB");
98 #else
99    strcpy (pszFilename, "/usr/vice/etc/CellServDB");
100 #endif
101 }
102
103
104 BOOL CSDB_ReadFile (PCELLSERVDB pCellServDB, const char *pszFilename)
105 {
106    BOOL rc = FALSE;
107    FILE *pFile;
108    size_t cbLength;
109    size_t cbRead;
110    char *pszBuffer;
111    char *pszStart;
112    char *pszEnd;
113    PCELLDBLINE pLine;
114
115    memset (pCellServDB, 0x00, sizeof(CELLSERVDB));
116
117    /* Open AFSDCELL.INI and read it into memory. */
118
119    if (pszFilename)
120       strcpy (pCellServDB->szFilename, pszFilename);
121    else
122       CSDB_GetFileName (pCellServDB->szFilename);
123
124    if ((pFile = fopen (pCellServDB->szFilename, "r")) != NULL)
125       {
126       fseek (pFile, 0, 2);
127       cbLength = ftell (pFile);
128       fseek (pFile, 0, 0);
129
130       pszBuffer = (char*)malloc (sizeof(char) * (cbLength +2));
131
132       if ((cbRead = fread (pszBuffer, 1, cbLength, pFile)) != 0)
133          {
134          pszBuffer[ cbRead ] = '\0';
135          pszBuffer[ cbRead+1 ] = '\0';
136
137          /* Scan the file line-by-line... */
138
139          for (pszStart = pszBuffer; pszStart && *pszStart; )
140             {
141             while (iswhiteeol(*pszStart))
142                ++pszStart;
143             if (!*pszStart)
144                break;
145
146             for (pszEnd = pszStart; *pszEnd && !iseol(*pszEnd); ++pszEnd)
147                ;
148             *pszEnd++ = '\0';
149
150             /* Add this line to our chain */
151
152             pLine = new(CELLDBLINE);
153             memset (pLine, 0x00, sizeof(CELLDBLINE));
154             strzcpy (pLine->szLine, pszStart, cchCELLDBLINE-1);
155             pLine->szLine[ cchCELLDBLINE-1 ] = '\0';
156             if ((pLine->pPrev = pCellServDB->pLast) != NULL)
157                pLine->pPrev->pNext = pLine;
158             if ((pCellServDB->pLast = pLine)->pPrev == NULL)
159                pCellServDB->pFirst = pLine;
160
161             /* Process the next line in the file */
162
163             pszStart = pszEnd;
164             }
165
166          rc = TRUE;
167          }
168
169       free (pszBuffer);
170       fclose (pFile);
171       }
172
173    return rc;
174 }
175
176
177 BOOL CSDB_WriteFile (PCELLSERVDB pCellServDB)
178 {
179    BOOL rc = TRUE;
180    FILE *pFile;
181    char szLine[ cchCELLDBLINE ];
182    PCELLDBLINE pLine;
183
184    if (pCellServDB->fChanged)
185       {
186       if ((pFile = fopen (pCellServDB->szFilename, "w")) == NULL)
187          {
188          rc = FALSE;
189          }
190       else
191          {
192          for (pLine = pCellServDB->pFirst; pLine; pLine = pLine->pNext)
193             {
194 #ifdef AFS_NT40_ENV
195             sprintf (szLine, "%s\r\n", pLine->szLine);
196 #else
197             sprintf (szLine, "%s\n", pLine->szLine);
198 #endif
199             fwrite (szLine, 1, strlen(szLine), pFile);
200             }
201
202          fclose (pFile);
203          }
204
205       pCellServDB->fChanged = FALSE;
206       }
207
208    return rc;
209 }
210
211
212 void CSDB_FreeFile (PCELLSERVDB pCellServDB)
213 {
214    PCELLDBLINE pNext;
215    PCELLDBLINE pLine;
216    for (pLine = pCellServDB->pFirst; pLine; pLine = pNext)
217       {
218       pNext = pLine->pNext;
219       delete(pLine);
220       }
221    memset (pCellServDB, 0x00, sizeof(CELLSERVDB));
222 }
223
224
225 BOOL CSDB_CrackLine (PCELLDBLINEINFO pInfo, const char *pszLine)
226 {
227    char *pszOut;
228    BOOL fIsCell = TRUE;
229    BOOL fSawHash = FALSE;
230
231    memset (pInfo, 0x00, sizeof(CELLDBLINEINFO));
232
233    if (!pszLine || !*pszLine)
234       return FALSE;
235
236    while (iswhite(*pszLine))
237       ++pszLine;
238
239    if (*pszLine == '>')
240       ++pszLine;
241    else if (!isdigit (*pszLine))
242       return FALSE;
243    else /* (isdigit (*pszLine)) */
244       fIsCell = FALSE;
245
246    for (pszOut = pInfo->szCell; *pszLine && (!iswhite(*pszLine)) && (*pszLine != '#'); )
247       *pszOut++ = *pszLine++;
248    *pszOut = '\0';
249
250    while (iswhite(*pszLine) || (*pszLine == '#'))
251       {
252       fSawHash = fSawHash || (*pszLine == '#');
253       ++pszLine;
254       }
255
256    if (fIsCell && *pszLine && !fSawHash)
257       {
258       for (pszOut = pInfo->szLinkedCell; *pszLine && (!iswhite(*pszLine)) && (*pszLine != '#'); )
259          *pszOut++ = *pszLine++;
260       *pszOut = '\0';
261
262       while (iswhite(*pszLine) || (*pszLine == '#'))
263          ++pszLine;
264       }
265
266    for (pszOut = pInfo->szComment; *pszLine; )
267       *pszOut++ = *pszLine++;
268    *pszOut = '\0';
269
270    if (!pInfo->szCell[0])
271       return FALSE;
272
273    if (!fIsCell)
274       {
275       if ((pInfo->ipServer = inet_addr (pInfo->szCell)) == 0xffffffff)
276          return FALSE;
277       pInfo->szCell[0] = '\0';
278       }
279
280    return TRUE;
281 }
282
283
284 BOOL CSDB_FormatLine (char *pszLine, const char *pszCell, const char *pszLinkedCell, const char *pszComment, BOOL fIsCell)
285 {
286    if (fIsCell)
287       sprintf (pszLine, ">%s", pszCell);
288    else
289       strcpy (pszLine, pszCell);
290
291    if (fIsCell && pszLinkedCell && *pszLinkedCell)
292       sprintf (&pszLine[ strlen(pszLine) ], " %s", pszLinkedCell);
293
294    if (pszComment)
295       {
296       size_t cchSpacing = (fIsCell) ? 28 : 33;
297       strcat (pszLine, " ");
298       if ((size_t)strlen(pszLine) < cchSpacing)
299          {
300          strcat (pszLine, "                                 ");
301          pszLine[cchSpacing] = '\0';
302          }
303
304       sprintf (&pszLine[ strlen(pszLine) ], ((fIsCell) ? "# %s" : "#%s"), pszComment);
305       }
306
307    return TRUE;
308 }
309
310
311 PCELLDBLINE CSDB_FindCell (PCELLSERVDB pCellServDB, const char *pszCell)
312 {
313    PCELLDBLINE pLine;
314    for (pLine = pCellServDB->pFirst; pLine; pLine = pLine->pNext)
315       {
316       CELLDBLINEINFO Info;
317       if (!CSDB_CrackLine (&Info, pLine->szLine))
318          continue;
319       if (!strcmpi (Info.szCell, pszCell))
320          return pLine;
321       }
322    return NULL;
323 }
324
325
326 BOOL CSDB_OnRemove (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine, BOOL fRemoveCellLineToo)
327 {
328    CELLDBLINEINFO Info;
329    PCELLDBLINE pNext;
330    PCELLDBLINE pLine;
331
332    /* Quick validation: make sure the caller specified a Cell line */
333
334    if (!pCellLine)
335       return FALSE;
336    if (!CSDB_CrackLine (&Info, pCellLine->szLine))
337       return FALSE;
338    if (!Info.szCell[0])
339       return FALSE;
340
341    /* Remove everything about this cell (except maybe the cell line) */
342
343    pLine = (fRemoveCellLineToo) ? pCellLine : pCellLine->pNext;
344    for ( ; pLine; pLine = pNext)
345       {
346       if ((pNext = CSDB_RemoveLine (pCellServDB, pLine)) != NULL)
347          {
348          if (!CSDB_CrackLine (&Info, pNext->szLine))
349             break;
350          if (Info.szCell[0]) /* Hit the next cell? We're done! */
351             break;
352          }
353       }
354
355    pCellServDB->fChanged = TRUE;
356    return TRUE;
357 }
358
359 BOOL CSDB_RemoveCell (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine)
360 {
361    return CSDB_OnRemove (pCellServDB, pCellLine, TRUE);
362 }
363    
364 BOOL CSDB_RemoveCellServers (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine)
365 {
366    return CSDB_OnRemove (pCellServDB, pCellLine, FALSE);
367 }
368
369
370 PCELLDBLINE CSDB_AddCell (PCELLSERVDB pCellServDB, const char *pszCell, const char *pszLinkedCell, const char *pszComment)
371 {
372    PCELLDBLINE pCellLine;
373
374    /* Find out if there's already an entry in CellServDB for this cell; */
375    /* add one if necessary. */
376
377    if ((pCellLine = CSDB_FindCell (pCellServDB, pszCell)) == NULL)
378       {
379       pCellLine = new(CELLDBLINE);
380       memset (pCellLine, 0x00, sizeof(CELLDBLINE));
381       if ((pCellLine->pPrev = pCellServDB->pLast) != NULL)
382          pCellLine->pPrev->pNext = pCellLine;
383       if ((pCellServDB->pLast = pCellLine)->pPrev == NULL)
384          pCellServDB->pFirst = pCellLine;
385       }
386
387    CSDB_FormatLine (pCellLine->szLine, pszCell, pszLinkedCell, pszComment, TRUE);
388    pCellServDB->fChanged = TRUE;
389    return pCellLine;
390 }
391
392
393 PCELLDBLINE CSDB_AddCellServer (PCELLSERVDB pCellServDB, PCELLDBLINE pAddAfter, const char *pszAddress, const char *pszComment)
394 {
395    char szLine[ cchCELLDBLINE ];
396    CSDB_FormatLine (szLine, pszAddress, NULL, pszComment, FALSE);
397    return CSDB_AddLine (pCellServDB, pAddAfter, szLine);
398 }
399
400
401 PCELLDBLINE CSDB_AddLine (PCELLSERVDB pCellServDB, PCELLDBLINE pAddAfter, const char *pszLine)
402 {
403    PCELLDBLINE pNew = new(CELLDBLINE);
404    memset (pNew, 0x00, sizeof(CELLDBLINE));
405    strcpy (pNew->szLine, pszLine);
406
407    if (pAddAfter == NULL)
408       {
409       if ((pNew->pNext = pCellServDB->pFirst) != NULL)
410          pNew->pNext->pPrev = pNew;
411       pNew->pPrev = NULL;
412       pCellServDB->pFirst = pNew;
413       if (pCellServDB->pLast == NULL)
414          pCellServDB->pLast = pNew;
415       }
416    else /* (pAddAfter != NULL) */
417       {
418       if ((pNew->pNext = pAddAfter->pNext) != NULL)
419          pNew->pNext->pPrev = pNew->pPrev;
420       pNew->pPrev = pAddAfter;
421       pAddAfter->pNext = pNew;
422       if (pCellServDB->pLast == pAddAfter)
423          pCellServDB->pLast = pNew;
424       }
425
426    pCellServDB->fChanged = TRUE;
427    return pNew;
428 }
429
430
431 PCELLDBLINE CSDB_RemoveLine (PCELLSERVDB pCellServDB, PCELLDBLINE pRemove)
432 {
433    PCELLDBLINE pNext;
434
435    if (!pRemove)
436       return NULL;
437
438    pNext = pRemove->pNext;
439
440    if (pRemove->pPrev)
441       pRemove->pPrev->pNext = pRemove->pNext;
442    if (pRemove->pNext)
443       pRemove->pNext->pPrev = pRemove->pPrev;
444    if (pCellServDB->pFirst == pRemove)
445       pCellServDB->pFirst = pRemove->pNext;
446    if (pCellServDB->pLast == pRemove)
447       pCellServDB->pLast = pRemove->pPrev;
448
449    delete(pRemove);
450
451    pCellServDB->fChanged = TRUE;
452    return pNext;
453 }
454