* Copyright (C) 2000-2002 by Art Cancro and others.
* This code is released under the terms of the GNU General Public License.
*
+ * ** NOTE ** A word on the S_NETCONFIGS semaphore:
+ * This is a fairly high-level type of critical section. It ensures that no
+ * two threads work on the netconfigs files at the same time. Since we do
+ * so many things inside these, here are the rules:
+ * 1. begin_critical_section(S_NETCONFIGS) *before* begin_ any others.
+ * 2. Do *not* perform any I/O with the client during these sections.
+ *
*/
/*
* Don't allow polls during network processing
*/
+/*
+ * Duration of time (in seconds) after which pending list subscribe/unsubscribe
+ * requests that have not been confirmed will be deleted.
+ */
+#define EXP 259200 /* three days */
+
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
*/
unlink(filename);
snprintf(buf, sizeof buf, "/bin/mv %s %s", tempfilename, filename);
+ begin_critical_section(S_NETCONFIGS);
system(buf);
+ end_critical_section(S_NETCONFIGS);
}
if ((sc->digestrecps != NULL) && (sc->digestfp != NULL)) {
fprintf(sc->digestfp, " -----------------------------------"
"------------------------------------"
- "-------\r\n");
+ "-------\n");
CtdlRedirectOutput(sc->digestfp, -1);
- CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 1);
+ CtdlOutputMsg(msgnum, MT_RFC822, HEADERS_ALL, 0, 0);
CtdlRedirectOutput(NULL, -1);
sc->num_msgs_spooled += 1;
}
sprintf(buf, "%ld", time(NULL));
msg->cm_fields['T'] = strdoop(buf);
-
+ msg->cm_fields['A'] = strdoop(CC->quickroom.QRname);
+ msg->cm_fields['U'] = strdoop(CC->quickroom.QRname);
sprintf(buf, "room_%s@%s", CC->quickroom.QRname, config.c_fqdn);
for (i=0; i<strlen(buf); ++i) {
if (isspace(buf[i])) buf[i]='_';
}
msg->cm_fields['F'] = strdoop(buf);
- msg->cm_fields['A'] = strdoop(CC->quickroom.QRname);
-
fseek(sc->digestfp, 0L, SEEK_END);
msglen = ftell(sc->digestfp);
FILE *fp;
struct SpoolControl sc;
struct namelist *nptr;
+ size_t miscsize = 0;
+ size_t linesize = 0;
+ int skipthisline = 0;
+ int i;
lprintf(7, "Spooling <%s>\n", room_to_spool);
if (getroom(&CC->quickroom, room_to_spool) != 0) {
memset(&sc, 0, sizeof(struct SpoolControl));
assoc_file_name(filename, sizeof filename, &CC->quickroom, "netconfigs");
+ begin_critical_section(S_NETCONFIGS);
+ end_critical_section(S_NETCONFIGS);
+
fp = fopen(filename, "r");
if (fp == NULL) {
lprintf(7, "Outbound batch processing skipped for <%s>\n",
CC->quickroom.QRname);
+ end_critical_section(S_NETCONFIGS);
return;
}
extract(nptr->name, buf, 1);
sc.ignet_push_shares = nptr;
}
+ else {
+ /* Preserve 'other' lines ... *unless* they happen to
+ * be subscribe/unsubscribe pendings with expired
+ * timestamps.
+ */
+ skipthisline = 0;
+ if (!strncasecmp(buf, "subpending|", 11)) {
+ if (time(NULL) - extract_long(buf, 4) > EXP) {
+ skipthisline = 1;
+ }
+ }
+ if (!strncasecmp(buf, "unsubpending|", 13)) {
+ if (time(NULL) - extract_long(buf, 3) > EXP) {
+ skipthisline = 1;
+ }
+ }
+
+ if (skipthisline == 0) {
+ linesize = strlen(buf);
+ sc.misc = realloc(sc.misc,
+ (miscsize + linesize + 2) );
+ sprintf(&sc.misc[miscsize], "%s\n", buf);
+ miscsize = miscsize + linesize + 1;
+ }
+ }
}
/* If there are digest recipients, we have to build a digest */
if (sc.digestrecps != NULL) {
sc.digestfp = tmpfile();
- fprintf(sc.digestfp, "Content-type: text/plain\r\n\r\n");
+ fprintf(sc.digestfp, "Content-type: text/plain\n\n");
}
/* Do something useful */
network_spool_msg, &sc);
/* If we wrote a digest, deliver it and then close it */
+ snprintf(buf, sizeof buf, "room_%s@%s",
+ CC->quickroom.QRname, config.c_fqdn);
+ for (i=0; i<strlen(buf); ++i) {
+ buf[i] = tolower(buf[i]);
+ if (isspace(buf[i])) buf[i] = '_';
+ }
if (sc.digestfp != NULL) {
fprintf(sc.digestfp, " -----------------------------------"
"------------------------------------"
- "-------\r\n"
+ "-------\n"
"You are subscribed to the '%s' "
- "list.\r\nTo unsubscribe, blah blah "
- "blah FIXME.\r\n",
- CC->quickroom.QRname
+ "list.\n"
+ "To post to the list: %s\n",
+ CC->quickroom.QRname, buf
);
network_deliver_digest(&sc); /* deliver and close */
}
phree(sc.ignet_push_shares);
sc.ignet_push_shares = nptr;
}
+ if (sc.misc != NULL) {
+ fwrite(sc.misc, strlen(sc.misc), 1, fp);
+ }
+ phree(sc.misc);
fclose(fp);
}
+ end_critical_section(S_NETCONFIGS);
lprintf(5, "Outbound batch processing finished for <%s>\n",
CC->quickroom.QRname);