#include #include #include #include #include #include #include "cellservdb.h" #ifdef AFS_NT40_ENV #include #include #else #include #endif /* * PROTOTYPES _________________________________________________________________ * */ #define new(_t) (_t*)malloc(sizeof(_t)) #define delete(_p) free((void*)(_p)) #ifndef iswhite #define iswhite(_ch) (((_ch)==' ') || ((_ch)=='\t')) #endif #ifndef iseol #define iseol(_ch) (((_ch)=='\r') || ((_ch)=='\n')) #endif #ifndef iswhiteeol #define iswhiteeol(_ch) (iswhite(_ch) || iseol(_ch)) #endif #ifndef min #define min(_a,_b) ((_a) < (_b) ? (_a) : (_b)) #endif /* * STATICS ____________________________________________________________________ * */ static void strzcpy (char *pszTarget, const char *pszSource, size_t cch) { cch = min(cch, (size_t)(1+strlen(pszSource))); strncpy (pszTarget, pszSource, cch-1); pszTarget[ cch-1 ] = '\0'; } /* * ROUTINES ___________________________________________________________________ * */ void CSDB_GetFileName (char *pszFilename) { #ifdef AFS_NT40_ENV /* Find the appropriate AFSDCELL.INI */ GetWindowsDirectory (pszFilename, MAX_CSDB_PATH); if (pszFilename[ strlen(pszFilename)-1 ] != '\\') strcat (pszFilename, "\\"); strcat (pszFilename, "AFSDCELL.INI"); #else strcpy (pszFilename, "/usr/vice/etc/CellServDB"); #endif } BOOL CSDB_ReadFile (PCELLSERVDB pCellServDB, const char *pszFilename) { BOOL rc = FALSE; FILE *pFile; size_t cbLength; size_t cbRead; char *pszBuffer; char *pszStart; char *pszEnd; PCELLDBLINE pLine; memset (pCellServDB, 0x00, sizeof(CELLSERVDB)); /* Open AFSDCELL.INI and read it into memory. */ if (pszFilename) strcpy (pCellServDB->szFilename, pszFilename); else CSDB_GetFileName (pCellServDB->szFilename); if ((pFile = fopen (pCellServDB->szFilename, "r")) != NULL) { fseek (pFile, 0, 2); cbLength = ftell (pFile); fseek (pFile, 0, 0); pszBuffer = (char*)malloc (sizeof(char) * (cbLength +2)); if ((cbRead = fread (pszBuffer, 1, cbLength, pFile)) != 0) { pszBuffer[ cbRead ] = '\0'; pszBuffer[ cbRead+1 ] = '\0'; /* Scan the file line-by-line... */ for (pszStart = pszBuffer; pszStart && *pszStart; ) { while (iswhiteeol(*pszStart)) ++pszStart; if (!*pszStart) break; for (pszEnd = pszStart; *pszEnd && !iseol(*pszEnd); ++pszEnd) ; *pszEnd++ = '\0'; /* Add this line to our chain */ pLine = new(CELLDBLINE); memset (pLine, 0x00, sizeof(CELLDBLINE)); strzcpy (pLine->szLine, pszStart, cchCELLDBLINE-1); pLine->szLine[ cchCELLDBLINE-1 ] = '\0'; if ((pLine->pPrev = pCellServDB->pLast) != NULL) pLine->pPrev->pNext = pLine; if ((pCellServDB->pLast = pLine)->pPrev == NULL) pCellServDB->pFirst = pLine; /* Process the next line in the file */ pszStart = pszEnd; } rc = TRUE; } free (pszBuffer); fclose (pFile); } return rc; } BOOL CSDB_WriteFile (PCELLSERVDB pCellServDB) { BOOL rc = TRUE; FILE *pFile; char szLine[ cchCELLDBLINE ]; PCELLDBLINE pLine; if (pCellServDB->fChanged) { if ((pFile = fopen (pCellServDB->szFilename, "w")) == NULL) { rc = FALSE; } else { for (pLine = pCellServDB->pFirst; pLine; pLine = pLine->pNext) { #ifdef AFS_NT40_ENV sprintf (szLine, "%s\r\n", pLine->szLine); #else sprintf (szLine, "%s\n", pLine->szLine); #endif fwrite (szLine, 1, strlen(szLine), pFile); } fclose (pFile); } pCellServDB->fChanged = FALSE; } return rc; } void CSDB_FreeFile (PCELLSERVDB pCellServDB) { PCELLDBLINE pNext; PCELLDBLINE pLine; for (pLine = pCellServDB->pFirst; pLine; pLine = pNext) { pNext = pLine->pNext; delete(pLine); } memset (pCellServDB, 0x00, sizeof(CELLSERVDB)); } BOOL CSDB_CrackLine (PCELLDBLINEINFO pInfo, const char *pszLine) { char *pszOut; BOOL fIsCell = TRUE; BOOL fSawHash = FALSE; memset (pInfo, 0x00, sizeof(CELLDBLINEINFO)); if (!pszLine || !*pszLine) return FALSE; while (iswhite(*pszLine)) ++pszLine; if (*pszLine == '>') ++pszLine; else if (!isdigit (*pszLine)) return FALSE; else /* (isdigit (*pszLine)) */ fIsCell = FALSE; for (pszOut = pInfo->szCell; *pszLine && (!iswhite(*pszLine)) && (*pszLine != '#'); ) *pszOut++ = *pszLine++; *pszOut = '\0'; while (iswhite(*pszLine) || (*pszLine == '#')) { fSawHash = fSawHash || (*pszLine == '#'); ++pszLine; } if (fIsCell && *pszLine && !fSawHash) { for (pszOut = pInfo->szLinkedCell; *pszLine && (!iswhite(*pszLine)) && (*pszLine != '#'); ) *pszOut++ = *pszLine++; *pszOut = '\0'; while (iswhite(*pszLine) || (*pszLine == '#')) ++pszLine; } for (pszOut = pInfo->szComment; *pszLine; ) *pszOut++ = *pszLine++; *pszOut = '\0'; if (!pInfo->szCell[0]) return FALSE; if (!fIsCell) { if ((pInfo->ipServer = inet_addr (pInfo->szCell)) == 0xffffffff) return FALSE; pInfo->szCell[0] = '\0'; } return TRUE; } BOOL CSDB_FormatLine (char *pszLine, const char *pszCell, const char *pszLinkedCell, const char *pszComment, BOOL fIsCell) { if (fIsCell) sprintf (pszLine, ">%s", pszCell); else strcpy (pszLine, pszCell); if (fIsCell && pszLinkedCell && *pszLinkedCell) sprintf (&pszLine[ strlen(pszLine) ], " %s", pszLinkedCell); if (pszComment) { size_t cchSpacing = (fIsCell) ? 28 : 33; strcat (pszLine, " "); if ((size_t)strlen(pszLine) < cchSpacing) { strcat (pszLine, " "); pszLine[cchSpacing] = '\0'; } sprintf (&pszLine[ strlen(pszLine) ], ((fIsCell) ? "# %s" : "#%s"), pszComment); } return TRUE; } PCELLDBLINE CSDB_FindCell (PCELLSERVDB pCellServDB, const char *pszCell) { PCELLDBLINE pLine; for (pLine = pCellServDB->pFirst; pLine; pLine = pLine->pNext) { CELLDBLINEINFO Info; if (!CSDB_CrackLine (&Info, pLine->szLine)) continue; if (!strcmpi (Info.szCell, pszCell)) return pLine; } return NULL; } BOOL CSDB_OnRemove (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine, BOOL fRemoveCellLineToo) { CELLDBLINEINFO Info; PCELLDBLINE pNext; PCELLDBLINE pLine; /* Quick validation: make sure the caller specified a Cell line */ if (!pCellLine) return FALSE; if (!CSDB_CrackLine (&Info, pCellLine->szLine)) return FALSE; if (!Info.szCell[0]) return FALSE; /* Remove everything about this cell (except maybe the cell line) */ pLine = (fRemoveCellLineToo) ? pCellLine : pCellLine->pNext; for ( ; pLine; pLine = pNext) { if ((pNext = CSDB_RemoveLine (pCellServDB, pLine)) != NULL) { if (!CSDB_CrackLine (&Info, pNext->szLine)) break; if (Info.szCell[0]) /* Hit the next cell? We're done! */ break; } } pCellServDB->fChanged = TRUE; return TRUE; } BOOL CSDB_RemoveCell (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine) { return CSDB_OnRemove (pCellServDB, pCellLine, TRUE); } BOOL CSDB_RemoveCellServers (PCELLSERVDB pCellServDB, PCELLDBLINE pCellLine) { return CSDB_OnRemove (pCellServDB, pCellLine, FALSE); } PCELLDBLINE CSDB_AddCell (PCELLSERVDB pCellServDB, const char *pszCell, const char *pszLinkedCell, const char *pszComment) { PCELLDBLINE pCellLine; /* Find out if there's already an entry in CellServDB for this cell; */ /* add one if necessary. */ if ((pCellLine = CSDB_FindCell (pCellServDB, pszCell)) == NULL) { pCellLine = new(CELLDBLINE); memset (pCellLine, 0x00, sizeof(CELLDBLINE)); if ((pCellLine->pPrev = pCellServDB->pLast) != NULL) pCellLine->pPrev->pNext = pCellLine; if ((pCellServDB->pLast = pCellLine)->pPrev == NULL) pCellServDB->pFirst = pCellLine; } CSDB_FormatLine (pCellLine->szLine, pszCell, pszLinkedCell, pszComment, TRUE); pCellServDB->fChanged = TRUE; return pCellLine; } PCELLDBLINE CSDB_AddCellServer (PCELLSERVDB pCellServDB, PCELLDBLINE pAddAfter, const char *pszAddress, const char *pszComment) { char szLine[ cchCELLDBLINE ]; CSDB_FormatLine (szLine, pszAddress, NULL, pszComment, FALSE); return CSDB_AddLine (pCellServDB, pAddAfter, szLine); } PCELLDBLINE CSDB_AddLine (PCELLSERVDB pCellServDB, PCELLDBLINE pAddAfter, const char *pszLine) { PCELLDBLINE pNew = new(CELLDBLINE); memset (pNew, 0x00, sizeof(CELLDBLINE)); strcpy (pNew->szLine, pszLine); if (pAddAfter == NULL) { if ((pNew->pNext = pCellServDB->pFirst) != NULL) pNew->pNext->pPrev = pNew; pNew->pPrev = NULL; pCellServDB->pFirst = pNew; if (pCellServDB->pLast == NULL) pCellServDB->pLast = pNew; } else /* (pAddAfter != NULL) */ { if ((pNew->pNext = pAddAfter->pNext) != NULL) pNew->pNext->pPrev = pNew->pPrev; pNew->pPrev = pAddAfter; pAddAfter->pNext = pNew; if (pCellServDB->pLast == pAddAfter) pCellServDB->pLast = pNew; } pCellServDB->fChanged = TRUE; return pNew; } PCELLDBLINE CSDB_RemoveLine (PCELLSERVDB pCellServDB, PCELLDBLINE pRemove) { PCELLDBLINE pNext; if (!pRemove) return NULL; pNext = pRemove->pNext; if (pRemove->pPrev) pRemove->pPrev->pNext = pRemove->pNext; if (pRemove->pNext) pRemove->pNext->pPrev = pRemove->pPrev; if (pCellServDB->pFirst == pRemove) pCellServDB->pFirst = pRemove->pNext; if (pCellServDB->pLast == pRemove) pCellServDB->pLast = pRemove->pPrev; delete(pRemove); pCellServDB->fChanged = TRUE; return pNext; }