/*
* $Id$
*
- * This module will eventually replace netproc and some of its utilities.
- * Copyright (C) 2000 by Art Cancro and others.
+ * This module will eventually replace netproc and some of its utilities. In
+ * the meantime, it serves as a mailing list manager.
+ *
+ * Copyright (C) 2000-2001 by Art Cancro and others.
* This code is released under the terms of the GNU General Public License.
*
*/
-
-/* FIXME
-
-there's stuff in here that makes the assumption that /tmp is on the same
-filesystem as Citadel, and makes calls to link() on that basis. fix this.
-
-*/
-
#include "sysdep.h"
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <errno.h>
#include <sys/types.h>
-#include <sys/time.h>
+
+#if TIME_WITH_SYS_TIME
+# include <sys/time.h>
+# include <time.h>
+#else
+# if HAVE_SYS_TIME_H
+# include <sys/time.h>
+# else
+# include <time.h>
+# endif
+#endif
+
#include <sys/wait.h>
#include <string.h>
#include <limits.h>
#include "citadel.h"
#include "server.h"
-#include <time.h>
#include "sysdep_decls.h"
#include "citserver.h"
#include "support.h"
void cmd_gnet(char *argbuf) {
- char filename[256];
- char buf[256];
+ char filename[SIZ];
+ char buf[SIZ];
FILE *fp;
if (CtdlAccessCheck(ac_room_aide)) return;
void cmd_snet(char *argbuf) {
- char tempfilename[256];
- char filename[256];
- char buf[256];
+ char tempfilename[SIZ];
+ char filename[SIZ];
+ char buf[SIZ];
FILE *fp;
if (CtdlAccessCheck(ac_room_aide)) return;
}
fclose(fp);
- /* Now that we've got the whole file, put it in place */
+ /* Now copy the temp file to its permanent location
+ * (We use /bin/mv instead of link() because they may be on
+ * different filesystems)
+ */
unlink(filename);
- link(tempfilename, filename);
- unlink(tempfilename);
+ snprintf(buf, sizeof buf, "/bin/mv %s %s", tempfilename, filename);
+ system(buf);
}
struct namelist *nptr;
int err;
char *instr = NULL;
- int instr_len = 0;
+ size_t instr_len = SIZ;
struct CtdlMessage *imsg;
sc = (struct SpoolControl *)userdata;
err = CtdlSaveMsgPointerInRoom(SMTP_SPOOLOUT_ROOM, msgnum, 0);
if (err != 0) return;
+ /*
+ * Figure out how big a buffer we need to allocate
+ */
+ for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
+ instr_len = instr_len + strlen(nptr->name);
+ }
+
+ /*
+ * allocate...
+ */
lprintf(9, "Generating delivery instructions\n");
- instr_len = 4096;
instr = mallok(instr_len);
+ if (instr == NULL) {
+ lprintf(1, "Cannot allocate %d bytes for instr...\n",
+ instr_len);
+ abort();
+ }
sprintf(instr,
"Content-type: %s\n\nmsgid|%ld\nsubmitted|%ld\n"
"bounceto|postmaster@%s\n" ,
SPOOLMIME, msgnum, time(NULL), config.c_fqdn );
+ /* Generate delivery instructions for each recipient */
+ for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
+ sprintf(&instr[strlen(instr)], "remote|%s|0||\n",
+ nptr->name);
+ }
+
+ /*
+ * Generate a message from the instructions
+ */
imsg = mallok(sizeof(struct CtdlMessage));
memset(imsg, 0, sizeof(struct CtdlMessage));
imsg->cm_magic = CTDLMESSAGE_MAGIC;
imsg->cm_fields['A'] = strdoop("Citadel");
imsg->cm_fields['M'] = instr;
- /* Generate delivery instructions for each recipient */
- for (nptr = sc->listrecps; nptr != NULL; nptr = nptr->next) {
- if (instr_len - strlen(instr) < 256) {
- instr_len = instr_len * 2;
- instr = reallok(instr, instr_len);
- }
- sprintf(&instr[strlen(instr)], "remote|%s|0||\n",
- nptr->name);
- }
-
/* Save delivery instructions in spoolout room */
CtdlSaveMsg(imsg, "", SMTP_SPOOLOUT_ROOM, MES_LOCAL);
CtdlFreeMessage(imsg);
/*
* Batch up and send all outbound traffic from the current room
*/
-void network_spoolout_current_room(void) {
- char filename[256];
- char buf[256];
- char instr[256];
+void network_spoolout_room(struct quickroom *qrbuf, void *data) {
+ char filename[SIZ];
+ char buf[SIZ];
+ char instr[SIZ];
FILE *fp;
struct SpoolControl sc;
/* struct namelist *digestrecps = NULL; */
struct namelist *nptr;
+ memcpy(&CC->quickroom, qrbuf, sizeof(struct quickroom));
+
memset(&sc, 0, sizeof(struct SpoolControl));
assoc_file_name(filename, &CC->quickroom, "netconfigs");
/* Do something useful */
- CtdlForEachMessage(MSGS_ALL, 0L, (-63), NULL, NULL,
+ CtdlForEachMessage(MSGS_GT, sc.lastsent, (-63), NULL, NULL,
network_spool_msg, &sc);
}
+/*
+ * network_do_queue()
+ *
+ * Run through the rooms doing various types of network stuff.
+ */
+void network_do_queue(void) {
+ static int doing_queue = 0;
+ static time_t last_run = 0L;
-/* FIXME temporary server command for batch send */
-void cmd_batc(char *argbuf) {
- if (CtdlAccessCheck(ac_aide)) return;
+#define NETWORK_QUEUE_FREQUENCY 3600 /* one hour ... FIXME put in config */
+ /*
+ * Run no more frequently than once every n seconds
+ */
+ if ( (time(NULL) - last_run) < NETWORK_QUEUE_FREQUENCY ) return;
- network_spoolout_current_room();
+ /*
+ * This is a simple concurrency check to make sure only one queue run
+ * is done at a time. We could do this with a mutex, but since we
+ * don't really require extremely fine granularity here, we'll do it
+ * with a static variable instead.
+ */
+ if (doing_queue) return;
+ doing_queue = 1;
+ last_run = time(NULL);
- cprintf("%d FIXME cmd_batc() ok\n", OK);
+ /*
+ * Go ahead and run the queue
+ */
+ lprintf(7, "network: processing outbound queue\n");
+ ForEachRoom(network_spoolout_room, NULL);
+ lprintf(7, "network: queue run completed\n");
+ doing_queue = 0;
}
-
char *Dynamic_Module_Init(void)
{
CtdlRegisterProtoHook(cmd_gnet, "GNET", "Get network config");
CtdlRegisterProtoHook(cmd_snet, "SNET", "Get network config");
-
- /* FIXME
- temporary server command for batch send
- */
- CtdlRegisterProtoHook(cmd_batc, "BATC", "send out batch (temp)");
-
+ CtdlRegisterSessionHook(network_do_queue, EVT_TIMER);
return "$Id$";
}