+ return 1;
+}
+
+void free_spoolcontrol_struct(SpoolControl **scc)
+{
+ SpoolControl *sc;
+ namelist *nptr = NULL;
+ maplist *mptr = NULL;
+
+ sc = *scc;
+ while (sc->listrecps != NULL) {
+ nptr = sc->listrecps->next;
+ free(sc->listrecps);
+ sc->listrecps = nptr;
+ }
+ /* Do the same for digestrecps */
+ while (sc->digestrecps != NULL) {
+ nptr = sc->digestrecps->next;
+ free(sc->digestrecps);
+ sc->digestrecps = nptr;
+ }
+ /* Do the same for participates */
+ while (sc->participates != NULL) {
+ nptr = sc->participates->next;
+ free(sc->participates);
+ sc->participates = nptr;
+ }
+ while (sc->ignet_push_shares != NULL) {
+ mptr = sc->ignet_push_shares->next;
+ free(sc->ignet_push_shares);
+ sc->ignet_push_shares = mptr;
+ }
+ free(sc->misc);
+ free(sc);
+ *scc=NULL;
+}
+
+int writenfree_spoolcontrol_file(SpoolControl **scc, char *filename)
+{
+ char tempfilename[PATH_MAX];
+ int TmpFD;
+ SpoolControl *sc;
+ namelist *nptr = NULL;
+ maplist *mptr = NULL;
+ long len;
+ time_t unixtime;
+ struct timeval tv;
+ long reltid; /* if we don't have SYS_gettid, use "random" value */
+ StrBuf *Cfg;
+ int rc;
+
+ len = strlen(filename);
+ memcpy(tempfilename, filename, len + 1);
+
+
+#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) */
+ unixtime = tv.tv_sec;
+
+ sprintf(tempfilename + len, ".%ld-%ld", reltid, unixtime);
+ sc = *scc;
+ errno = 0;
+ TmpFD = open(tempfilename, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
+ Cfg = NewStrBuf();
+ if ((TmpFD < 0) || (errno != 0)) {
+ syslog(LOG_CRIT, "ERROR: cannot open %s: %s\n",
+ filename, strerror(errno));
+ free_spoolcontrol_struct(scc);
+ unlink(tempfilename);
+ }
+ else {
+ fchown(TmpFD, config.c_ctdluid, 0);
+ StrBufAppendPrintf(Cfg, "lastsent|%ld\n", sc->lastsent);
+
+ /* Write out the listrecps while freeing from memory at the
+ * same time. Am I clever or what? :)
+ */
+ while (sc->listrecps != NULL) {
+ StrBufAppendPrintf(Cfg, "listrecp|%s\n", sc->listrecps->name);
+ nptr = sc->listrecps->next;
+ free(sc->listrecps);
+ sc->listrecps = nptr;
+ }
+ /* Do the same for digestrecps */
+ while (sc->digestrecps != NULL) {
+ StrBufAppendPrintf(Cfg, "digestrecp|%s\n", sc->digestrecps->name);
+ nptr = sc->digestrecps->next;
+ free(sc->digestrecps);
+ sc->digestrecps = nptr;
+ }
+ /* Do the same for participates */
+ while (sc->participates != NULL) {
+ StrBufAppendPrintf(Cfg, "participate|%s\n", sc->participates->name);
+ nptr = sc->participates->next;
+ free(sc->participates);
+ sc->participates = nptr;
+ }
+ while (sc->ignet_push_shares != NULL) {
+ StrBufAppendPrintf(Cfg, "ignet_push_share|%s", sc->ignet_push_shares->remote_nodename);
+ if (!IsEmptyStr(sc->ignet_push_shares->remote_roomname)) {
+ StrBufAppendPrintf(Cfg, "|%s", sc->ignet_push_shares->remote_roomname);
+ }
+ StrBufAppendPrintf(Cfg, "\n");
+ mptr = sc->ignet_push_shares->next;
+ free(sc->ignet_push_shares);
+ sc->ignet_push_shares = mptr;
+ }
+ if (sc->misc != NULL) {
+ StrBufAppendBufPlain(Cfg, sc->misc, -1, 0);
+ }
+ free(sc->misc);
+
+ rc = write(TmpFD, ChrPtr(Cfg), StrLength(Cfg));
+ if ((rc >=0 ) && (rc == StrLength(Cfg)))
+ {
+ close(TmpFD);
+ rename(tempfilename, filename);
+ }
+ else {
+ syslog(LOG_EMERG,
+ "unable to write %s; [%s]; not enough space on the disk?\n",
+ tempfilename,
+ strerror(errno));
+ close(TmpFD);
+ unlink(tempfilename);
+ }
+ FreeStrBuf(&Cfg);
+ free(sc);
+ *scc=NULL;
+ }
+ return 1;
+}
+int is_recipient(SpoolControl *sc, const char *Name)
+{
+ namelist *nptr;
+ size_t len;
+
+ len = strlen(Name);
+ nptr = sc->listrecps;
+ while (nptr != NULL) {
+ if (strncmp(Name, nptr->name, len)==0)
+ return 1;
+ nptr = nptr->next;
+ }
+ /* Do the same for digestrecps */
+ nptr = sc->digestrecps;
+ while (nptr != NULL) {
+ if (strncmp(Name, nptr->name, len)==0)
+ return 1;
+ nptr = nptr->next;
+ }
+ /* Do the same for participates */
+ nptr = sc->participates;
+ while (nptr != NULL) {
+ if (strncmp(Name, nptr->name, len)==0)
+ return 1;
+ nptr = nptr->next;
+ }
+ return 0;
+}
+
+
+/*
+ * Batch up and send all outbound traffic from the current room
+ */
+void network_spoolout_room(char *room_to_spool) {
+ char buf[SIZ];
+ char filename[PATH_MAX];
+ SpoolControl *sc;
+ int i;
+
+ /*
+ * If the room doesn't exist, don't try to perform its networking tasks.
+ * Normally this should never happen, but once in a while maybe a room gets
+ * queued for networking and then deleted before it can happen.
+ */
+ if (CtdlGetRoom(&CC->room, room_to_spool) != 0) {
+ syslog(LOG_CRIT, "ERROR: cannot load <%s>\n", room_to_spool);
+ return;
+ }
+
+ assoc_file_name(filename, sizeof filename, &CC->room, ctdl_netcfg_dir);
+ begin_critical_section(S_NETCONFIGS);
+
+ /* Only do net processing for rooms that have netconfigs */
+ if (!read_spoolcontrol_file(&sc, filename))
+ {
+ end_critical_section(S_NETCONFIGS);
+ return;
+ }
+ syslog(LOG_INFO, "Networking started for <%s>\n", CC->room.QRname);