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