X-Git-Url: https://code.citadel.org/?p=citadel.git;a=blobdiff_plain;f=citadel%2Fnetconfig.c;h=1b2e974aa6b42ad137397438dec0c7f620fbf27d;hp=3aac29463e616fc753e7b6d9b0df2dcce54980fc;hb=a5e759daa03e43dfdd940e96c13cded7ba8de39c;hpb=4632e362fbc73c9abce30f0bcf4d0023144937a8 diff --git a/citadel/netconfig.c b/citadel/netconfig.c index 3aac29463..1b2e974aa 100644 --- a/citadel/netconfig.c +++ b/citadel/netconfig.c @@ -29,6 +29,11 @@ #include #include "include/ctdl_module.h" +#include "serv_extensions.h" + +void vFreeRoomNetworkStruct(void *vOneRoomNetCfg); +void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg); + HashList *CfgTypeHash = NULL; HashList *RoomConfigs = NULL; /*-----------------------------------------------------------------------------* @@ -41,6 +46,7 @@ void RegisterRoomCfgType(const char* Name, long len, RoomNetCfg eCfg, CfgLinePar pCfg = (CfgLineType*) malloc(sizeof(CfgLineType)); pCfg->Parser = p; pCfg->Serializer = s; + pCfg->DeAllocator = d; pCfg->C = eCfg; pCfg->Str.Key = Name; pCfg->Str.len = len; @@ -82,34 +88,38 @@ const CfgLineType *GetCfgTypeByEnum(RoomNetCfg eCfg, HashPos *It) } return NULL; } -void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCFG) +void ParseGeneric(const CfgLineType *ThisOne, StrBuf *Line, const char *LinePos, OneRoomNetCfg *OneRNCfg) { RoomNetCfgLine *nptr; int i; nptr = (RoomNetCfgLine *) malloc(sizeof(RoomNetCfgLine)); - nptr->next = OneRNCFG->NetConfigs[ThisOne->C]; + nptr->next = OneRNCfg->NetConfigs[ThisOne->C]; nptr->Value = malloc(sizeof(StrBuf*) * ThisOne->nSegments); + nptr->nValues = 0; memset(nptr->Value, 0, sizeof(StrBuf*) * ThisOne->nSegments); if (ThisOne->nSegments == 1) { nptr->Value[0] = NewStrBufPlain(LinePos, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); + nptr->nValues = 1; } else for (i = 0; i < ThisOne->nSegments; i++) { + nptr->nValues++; nptr->Value[i] = NewStrBufPlain(NULL, StrLength(Line) - ( LinePos - ChrPtr(Line)) ); StrBufExtract_NextToken(nptr->Value[i], Line, &LinePos, '|'); } - OneRNCFG->NetConfigs[ThisOne->C] = nptr; + OneRNCfg->NetConfigs[ThisOne->C] = nptr; } -void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCFG, RoomNetCfgLine *data) +void SerializeGeneric(const CfgLineType *ThisOne, StrBuf *OutputBuffer, OneRoomNetCfg *OneRNCfg, RoomNetCfgLine *data) { int i; StrBufAppendBufPlain(OutputBuffer, CKEY(ThisOne->Str), 0); + StrBufAppendBufPlain(OutputBuffer, HKEY("|"), 0); for (i = 0; i < ThisOne->nSegments; i++) { StrBufAppendBuf(OutputBuffer, data->Value[i], 0); @@ -123,7 +133,10 @@ void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) { int i; - for (i = 0; i < ThisOne->nSegments; i++) + if (*data == NULL) + return; + + for (i = 0; i < (*data)->nValues; i++) { FreeStrBuf(&(*data)->Value[i]); } @@ -133,19 +146,22 @@ void DeleteGenericCfgLine(const CfgLineType *ThisOne, RoomNetCfgLine **data) } RoomNetCfgLine *DuplicateOneGenericCfgLine(const RoomNetCfgLine *data) { + int i; RoomNetCfgLine *NewData; NewData = (RoomNetCfgLine*)malloc(sizeof(RoomNetCfgLine)); - int i; + memset(NewData, 0, sizeof(RoomNetCfgLine)); NewData->Value = (StrBuf **)malloc(sizeof(StrBuf*) * data->nValues); + memset(NewData->Value, 0, sizeof(StrBuf*) * data->nValues); for (i = 0; i < data->nValues; i++) { NewData->Value[i] = NewStrBufDup(data->Value[i]); } + NewData->nValues = data->nValues; return NewData; } -int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCFG, char *filename) +int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCfg, char *filename) { int fd; const char *ErrStr = NULL; @@ -153,41 +169,47 @@ int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCFG, char *filename) const CfgLineType *pCfg; StrBuf *Line; StrBuf *InStr; - OneRoomNetCfg *OneRNCFG; + OneRoomNetCfg *OneRNCfg = NULL; fd = open(filename, O_NONBLOCK|O_RDONLY); if (fd == -1) { - *pOneRNCFG = NULL; + *pOneRNCfg = NULL; return 0; } - OneRNCFG = malloc(sizeof(OneRoomNetCfg)); - memset(OneRNCFG, 0, sizeof(OneRoomNetCfg)); - *pOneRNCFG = OneRNCFG; + if (*pOneRNCfg != NULL) + { + OneRNCfg = *pOneRNCfg; + FreeRoomNetworkStructContent (OneRNCfg); + } + else + OneRNCfg = malloc(sizeof(OneRoomNetCfg)); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); + *pOneRNCfg = OneRNCfg; Line = NewStrBuf(); + InStr = NewStrBuf(); while (StrBufTCP_read_line(Line, &fd, 0, &ErrStr) >= 0) { if (StrLength(Line) == 0) continue; Pos = NULL; - InStr = NewStrBufPlain(NULL, StrLength(Line)); StrBufExtract_NextToken(InStr, Line, &Pos, '|'); pCfg = GetCfgTypeByStr(SKEY(InStr)); if (pCfg != NULL) { - pCfg->Parser(pCfg, Line, Pos, OneRNCFG); + pCfg->Parser(pCfg, Line, Pos, OneRNCfg); } else { - if (OneRNCFG->misc == NULL) + if (OneRNCfg->misc == NULL) { - OneRNCFG->misc = NewStrBufDup(Line); + OneRNCfg->misc = NewStrBufDup(Line); } else { - if(StrLength(OneRNCFG->misc) > 0) - StrBufAppendBufPlain(OneRNCFG->misc, HKEY("\n"), 0); - StrBufAppendBuf(OneRNCFG->misc, Line, 0); + if(StrLength(OneRNCfg->misc) > 0) + StrBufAppendBufPlain(OneRNCfg->misc, HKEY("\n"), 0); + StrBufAppendBuf(OneRNCfg->misc, Line, 0); } } } @@ -198,25 +220,25 @@ int ReadRoomNetConfigFile(OneRoomNetCfg **pOneRNCFG, char *filename) return 1; } -int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) +int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCfg, char *filename) { RoomNetCfg eCfg; - StrBuf *Cfg; + StrBuf *Cfg = NULL; + StrBuf *OutBuffer = NULL; char tempfilename[PATH_MAX]; int TmpFD; long len; time_t unixtime; struct timeval tv; long reltid; /* if we don't have SYS_gettid, use "random" value */ - StrBuf *OutBuffer; int rc; HashPos *CfgIt; len = strlen(filename); memcpy(tempfilename, filename, len + 1); -#if defined(HAVE_SYONERNCFGALL_H) && defined (SYS_gettid) - reltid = syOneRNCFGall(SYS_gettid); +#if defined(HAVE_SYSCALL_H) && defined (SYS_gettid) + reltid = syscall(SYS_gettid); #endif gettimeofday(&tv, NULL); /* Promote to time_t; types differ on some OSes (like darwin) */ @@ -230,9 +252,11 @@ int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) syslog(LOG_CRIT, "ERROR: cannot open %s: %s\n", filename, strerror(errno)); unlink(tempfilename); + FreeStrBuf(&Cfg); return 0; } else { + OutBuffer = NewStrBuf(); CfgIt = GetNewHashPos(CfgTypeHash, 1); fchown(TmpFD, config.c_ctdluid, 0); for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) @@ -241,14 +265,14 @@ int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) pCfg = GetCfgTypeByEnum(eCfg, CfgIt); if (pCfg->IsSingleLine) { - pCfg->Serializer(pCfg, OutBuffer, OneRNCFG, NULL); + pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, NULL); } else { - RoomNetCfgLine *pName = OneRNCFG->NetConfigs[pCfg->C]; + RoomNetCfgLine *pName = OneRNCfg->NetConfigs[pCfg->C]; while (pName != NULL) { - pCfg->Serializer(pCfg, OutBuffer, OneRNCFG, pName); + pCfg->Serializer(pCfg, OutBuffer, OneRNCfg, pName); pName = pName->next; } @@ -259,12 +283,12 @@ int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) DeleteHashPos(&CfgIt); - if (OneRNCFG->misc != NULL) { - StrBufAppendBuf(OutBuffer, OneRNCFG->misc, 0); + if (OneRNCfg->misc != NULL) { + StrBufAppendBuf(OutBuffer, OneRNCfg->misc, 0); } rc = write(TmpFD, ChrPtr(OutBuffer), StrLength(OutBuffer)); - if ((rc >=0 ) && (rc == StrLength(Cfg))) + if ((rc >=0 ) && (rc == StrLength(OutBuffer))) { close(TmpFD); rename(tempfilename, filename); @@ -282,17 +306,60 @@ int SaveRoomNetConfigFile(OneRoomNetCfg *OneRNCFG, char *filename) FreeStrBuf(&OutBuffer); } + FreeStrBuf(&Cfg); return rc; } +void SaveModifiedRooms(struct ctdlroom *qrbuf, void *data, OneRoomNetCfg *OneRNCfg) +{ + char filename[PATH_MAX]; -void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) + if (OneRNCfg->changed) + { + assoc_file_name(filename, sizeof filename, qrbuf, ctdl_netcfg_dir); + SaveRoomNetConfigFile(OneRNCfg, filename); + OneRNCfg->changed = 0; + } +} +void SaveChangedConfigs(void) +{ + CtdlForEachNetCfgRoom(SaveModifiedRooms, + NULL, + maxRoomNetCfg); +} + + +void AddRoomCfgLine(OneRoomNetCfg *OneRNCfg, struct ctdlroom *qrbuf, RoomNetCfg LineType, RoomNetCfgLine *Line) +{ + int new = 0; + RoomNetCfgLine **pLine; + char filename[PATH_MAX]; + + if (OneRNCfg == NULL) + { + new = 1; + OneRNCfg = (OneRoomNetCfg*) malloc(sizeof(OneRoomNetCfg)); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); + } + pLine = &OneRNCfg->NetConfigs[LineType]; + + while(*pLine != NULL) pLine = &((*pLine)->next); + *pLine = Line; + + assoc_file_name(filename, sizeof filename, qrbuf, ctdl_netcfg_dir); + SaveRoomNetConfigFile(OneRNCfg, filename); + OneRNCfg->changed = 0; + if (new) + { + Put(RoomConfigs, LKEY(qrbuf->QRnumber), OneRNCfg, vFreeRoomNetworkStruct); + } +} + +void FreeRoomNetworkStructContent(OneRoomNetCfg *OneRNCfg) { RoomNetCfg eCfg; HashPos *CfgIt; - OneRoomNetCfg *OneRNCFG; - OneRNCFG = (OneRoomNetCfg*)vOneRoomNetCfg; CfgIt = GetNewHashPos(CfgTypeHash, 1); for (eCfg = subpending; eCfg < maxRoomNetCfg; eCfg ++) { @@ -300,28 +367,42 @@ void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) RoomNetCfgLine *pNext, *pName; pCfg = GetCfgTypeByEnum(eCfg, CfgIt); - pName= OneRNCFG->NetConfigs[pCfg->C]; + pName= OneRNCfg->NetConfigs[eCfg]; while (pName != NULL) { pNext = pName->next; - pCfg->DeAllocator(pCfg, &pName); + if (pCfg != NULL) + { + pCfg->DeAllocator(pCfg, &pName); + } + else + { + DeleteGenericCfgLine(NULL, &pName); + } pName = pNext; } } DeleteHashPos(&CfgIt); - FreeStrBuf(&OneRNCFG->Sender); - FreeStrBuf(&OneRNCFG->RoomInfo); - FreeStrBuf(&OneRNCFG->misc); - free(OneRNCFG); + FreeStrBuf(&OneRNCfg->Sender); + FreeStrBuf(&OneRNCfg->RoomInfo); + FreeStrBuf(&OneRNCfg->misc); + memset(OneRNCfg, 0, sizeof(OneRoomNetCfg)); } -void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCFG) +void vFreeRoomNetworkStruct(void *vOneRoomNetCfg) +{ + OneRoomNetCfg *OneRNCfg; + OneRNCfg = (OneRoomNetCfg*)vOneRoomNetCfg; + FreeRoomNetworkStructContent(OneRNCfg); + free(OneRNCfg); +} +void FreeRoomNetworkStruct(OneRoomNetCfg **pOneRNCfg) { - vFreeRoomNetworkStruct(*pOneRNCFG); - *pOneRNCFG=NULL; + vFreeRoomNetworkStruct(*pOneRNCfg); + *pOneRNCfg=NULL; } -const OneRoomNetCfg* CtdlGetNetCfgForRoom(long QRNumber) +OneRoomNetCfg* CtdlGetNetCfgForRoom(long QRNumber) { void *pv; GetHash(RoomConfigs, LKEY(QRNumber), &pv); @@ -337,7 +418,7 @@ void LoadAllNetConfigs(void) int d_type = 0; int d_namelen; long RoomNumber; - OneRoomNetCfg *OneRNCFG; + OneRoomNetCfg *OneRNCfg; int IsNumOnly; const char *pch; char path[PATH_MAX]; @@ -418,12 +499,12 @@ void LoadAllNetConfigs(void) } if (IsNumOnly) { + OneRNCfg = NULL; RoomNumber = atol(filedir_entry->d_name); - ReadRoomNetConfigFile(&OneRNCFG, path); + ReadRoomNetConfigFile(&OneRNCfg, path); - if (OneRNCFG != NULL) - Put(RoomConfigs, LKEY(RoomNumber), OneRNCFG, vFreeRoomNetworkStruct); - + if (OneRNCfg != NULL) + Put(RoomConfigs, LKEY(RoomNumber), OneRNCfg, vFreeRoomNetworkStruct); /* syslog(9, "[%s | %s]\n", ChrPtr(OneWebName), ChrPtr(FileName)); */ } break; @@ -495,8 +576,9 @@ const ConstStr ForceAliases[nForceAliases] = { {HKEY("postmaster,")}, {HKEY("abuse,")} }; - -void cmd_snet(char *argbuf) { +void cmd_snet(char *argbuf) +{ + struct CitContext *CCC = CC; char tempfilename[PATH_MAX]; char filename[PATH_MAX]; int TmpFD; @@ -525,19 +607,19 @@ void cmd_snet(char *argbuf) { } else { - if ( (CC->room.QRflags & QR_MAILBOX) && (CC->user.usernum == atol(CC->room.QRname)) ) { + if ( (CCC->room.QRflags & QR_MAILBOX) && (CCC->user.usernum == atol(CCC->room.QRname)) ) { /* users can edit the netconfigs for their own mailbox rooms */ } else if (CtdlAccessCheck(ac_room_aide)) return; - len = assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); + len = assoc_file_name(filename, sizeof filename, &CCC->room, ctdl_netcfg_dir); memcpy(tempfilename, filename, len + 1); } memset(&StatBuf, 0, sizeof(struct stat)); if ((stat(filename, &StatBuf) == -1) || (StatBuf.st_size == 0)) StatBuf.st_size = 80; /* Not there or empty? guess 80 chars line. */ - sprintf(tempfilename + len, ".%d", CC->cs_pid); + sprintf(tempfilename + len, ".%d", CCC->cs_pid); errno = 0; TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); @@ -630,6 +712,22 @@ void cmd_snet(char *argbuf) { */ begin_critical_section(S_NETCONFIGS); rename(tempfilename, filename); + if (!IsMailAlias) + { + OneRoomNetCfg *RNCfg; + RNCfg = CtdlGetNetCfgForRoom(CCC->room.QRnumber); + if (RNCfg != NULL) + { + ReadRoomNetConfigFile(&RNCfg, filename); + } + else + { + ReadRoomNetConfigFile(&RNCfg, filename); + Put(RoomConfigs, LKEY(CCC->room.QRnumber), RNCfg, vFreeRoomNetworkStruct); + } + + PerformRoomHooks(&CCC->room); + } end_critical_section(S_NETCONFIGS); } @@ -753,7 +851,6 @@ int CtdlNetconfigCheckRoomaccess( const char* RemoteIdentifier) { OneRoomNetCfg *RNCfg; - char filename[SIZ]; int found; if (RemoteIdentifier == NULL) @@ -762,18 +859,18 @@ int CtdlNetconfigCheckRoomaccess( return (ERROR + USERNAME_REQUIRED); } - assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir); begin_critical_section(S_NETCONFIGS); - if (!ReadRoomNetConfigFile(&RNCfg, filename)) + RNCfg = CtdlGetNetCfgForRoom (CC->room.QRnumber); + if (RNCfg == NULL) { end_critical_section(S_NETCONFIGS); snprintf(errmsgbuf, n, "This mailing list only accepts posts from subscribers."); return (ERROR + NO_SUCH_USER); } - end_critical_section(S_NETCONFIGS); found = is_recipient (RNCfg, RemoteIdentifier); - vFreeRoomNetworkStruct(&RNCfg); + end_critical_section(S_NETCONFIGS); + if (found) { return (0); } @@ -1066,7 +1163,17 @@ int CtdlIsValidNode(const StrBuf **nexthop, } +void destroy_network_cfgs(void) +{ + HashList *pCfgTypeHash = CfgTypeHash; + HashList *pRoomConfigs = RoomConfigs; + CfgTypeHash = NULL; + RoomConfigs = NULL; + + DeleteHash(&pCfgTypeHash); + DeleteHash(&pRoomConfigs); +} /* * Module entry point @@ -1075,6 +1182,7 @@ CTDL_MODULE_INIT(netconfig) { if (!threading) { + CtdlRegisterCleanupHook(destroy_network_cfgs); LoadAllNetConfigs (); CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config"); CtdlRegisterProtoHook(cmd_snet, "SNET", "Set network config");