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