commit 1ede09688b828dbc43da975d948f0fefc63d7493
parent bfeb1f9e864b4e5b64623f26288c148136f9d694
Author: Ellenor Bjornsdottir <ellenor@umbrellix.net>
Date: Sat, 24 Dec 2022 07:43:46 +0000
We still have not tested this code. It's still not ready for that.
Diffstat:
8 files changed, 216 insertions(+), 56 deletions(-)
diff --git a/src/mxf-send/cleanup.c b/src/mxf-send/cleanup.c
@@ -45,24 +45,24 @@ cleanup_do()
return;
}
- fnmake_mess(id);
+ fnmake_mess(id, &fn);
if (stat(fn.s, &st) == -1)
return; /* probably qmail-queue deleted it */
if (recent <= st.st_atime + OSSIFIED)
return;
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (stat(fn.s, &st) == 0)
return;
if (errno != error_noent)
return;
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
if (stat(fn.s, &st) == 0)
return;
if (errno != error_noent)
return;
- fnmake_foop(id);
+ fnmake_foop(id, &fn);
if (substdio_putflush(&sstoqc, fn.s, fn.len) == -1) {
cleandied();
return;
diff --git a/src/mxf-send/comm.c b/src/mxf-send/comm.c
@@ -48,7 +48,7 @@ comm_write(int c, int delnum, unsigned long id, char *sender, char *recip)
ch = delnum;
while (!stralloc_append(&comm_buf[c], &ch))
nomem();
- fnmake_split(id);
+ fnmake_split(id, &fn);
while (!stralloc_cats(&comm_buf[c], fn.s))
nomem();
while (!stralloc_0(&comm_buf[c]))
diff --git a/src/mxf-send/deliveries.c b/src/mxf-send/deliveries.c
@@ -121,7 +121,7 @@ markdone(int c, unsigned long id, seek_pos pos)
{
struct stat st;
int fd;
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
for (;;) {
fd = open_write(fn.s);
if (fd == -1)
diff --git a/src/mxf-send/fnmake.c b/src/mxf-send/fnmake.c
@@ -24,28 +24,41 @@ fnmake_init()
nomem();
}
-void fnmake_info(unsigned long id){
- fn.len = fmtqfn(fn.s, "info/", id, 1);
+/* fnmake_*() family of functions.
+ * All of these functions have a right to expect to be passed ptrs to
+ * the global fn variables, or to appropriate local ones.
+ */
+
+void fnmake_info(unsigned long id, stralloc *fn)
+{
+ fn->len = fmtqfn(fn->s, "info/", id, 1);
}
-void fnmake_todo(unsigned long id){
- fn.len = fmtqfn(fn.s, "todo/", id, 0);
+void fnmake_todo(unsigned long id, stralloc *fn)
+{
+ fn->len = fmtqfn(fn->s, "todo/", id, 0);
}
-void fnmake_mess(unsigned long id){
- fn.len = fmtqfn(fn.s, "mess/", id, 1);
+void fnmake_mess(unsigned long id, stralloc *fn)
+{
+ fn->len = fmtqfn(fn->s, "mess/", id, 1);
}
-void fnmake_foop(unsigned long id){
- fn.len = fmtqfn(fn.s, "foop/", id, 0);
+void fnmake_foop(unsigned long id, stralloc *fn)
+{
+ fn->len = fmtqfn(fn->s, "foop/", id, 0);
}
-void fnmake_split(unsigned long id){
- fn.len = fmtqfn(fn.s, "", id, 1);
+void fnmake_split(unsigned long id, stralloc *fn)
+{
+ fn->len = fmtqfn(fn->s, "", id, 1);
}
+/* fnmake_bounce should generally be passed
+ * fn2, although if you need it in fn, go ahead.
+ */
void
-fnmake2_bounce(unsigned long id)
+fnmake_bounce(unsigned long id, stralloc *fn)
{
- fn2.len = fmtqfn(fn2.s, "bounce/", id, 0);
+ fn->len = fmtqfn(fn->s, "bounce/", id, 0);
}
void
-fnmake_chanaddr(unsigned long id, int c)
+fnmake_chanaddr(unsigned long id, int c, stralloc *fn)
{
- fn.len = fmtqfn(fn.s, chanaddr[c], id, 1);
+ fn->len = fmtqfn(fn->s, chanaddr[c], id, 1);
}
diff --git a/src/mxf-send/mxf-send.c b/src/mxf-send/mxf-send.c
@@ -101,13 +101,13 @@ sighup()
}
void cleandied() {
- log1("alert: oh no! lost qmail-clean connection! dying...\n");
+ log1("alert: the clean channel driver exited. to ensure that it is restarted, I will too.\n");
flagexitasap = 1;
}
int flagspawnalive[CHANNELS];
void spawndied(int c){
- log1("alert: oh no! lost spawn connection! dying...\n");
+ log1("alert: one or more delivery channel drivers exited. to ensure that it is restarted, I will too.\n");
flagspawnalive[c] = 0;
flagexitasap = 1;
}
@@ -176,7 +176,7 @@ getinfo(stralloc * sa, datetime_sec * dt, unsigned long id)
substdio ss;
char buf[128];
- fnmake_info(id);
+ fnmake_info(id, &fn);
fdinfo = open_read(fn.s);
if (fdinfo == -1)
return 0;
@@ -223,19 +223,19 @@ pqadd(unsigned long id)
#define CHECKSTAT if (errno != error_noent) goto fail;
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (stat(fn.s, &st) == -1) {
CHECKSTAT
return; /* someone yanking our chain */
}
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
if (stat(fn.s, &st) != -1)
return; /* look, ma, dad crashed writing info! */
CHECKSTAT
for (c = 0; c < CHANNELS; ++c) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
if (stat(fn.s, &st) == -1) {
flagchan[c] = 0;
CHECKSTAT
@@ -295,7 +295,7 @@ pqfinish()
for (c = 0; c < CHANNELS; ++c)
while (prioq_min(&pqchan[c], &pe)) {
prioq_delmin(&pqchan[c]);
- fnmake_chanaddr(pe.id, c);
+ fnmake_chanaddr(pe.id, c, &fn);
ut[0].tv_sec = ut[1].tv_sec = pe.dt;
if (utimes(fn.s, ut) == -1)
log3("warning: unable to utime ", fn.s, "; message will be retried too soon\n");
@@ -383,7 +383,7 @@ job_close(int j)
pe.id = jo[j].id;
pe.dt = jo[j].retry;
if (jo[j].flaghiteof && !jo[j].numtodo) {
- fnmake_chanaddr(jo[j].id, jo[j].channel);
+ fnmake_chanaddr(jo[j].id, jo[j].channel, &fn);
if (unlink(fn.s) == -1) {
log3("warning: unable to unlink ", fn.s, "; will try again later\n");
pe.dt = now() + SLEEP_SYSFAIL;
@@ -391,7 +391,7 @@ job_close(int j)
int c;
for (c = 0; c < CHANNELS; ++c)
if (c != jo[j].channel) {
- fnmake_chanaddr(jo[j].id, c);
+ fnmake_chanaddr(jo[j].id, c, &fn);
if (stat(fn.s, &st) == 0)
return; /* more channels going */
if (errno != error_noent) {
@@ -472,7 +472,7 @@ addbounce(unsigned long id, char *recip, char *report)
bouncetext.s[pos] = '/';
while (!stralloc_cats(&bouncetext, "\n"))
nomem();
- fnmake2_bounce(id);
+ fnmake_bounce(id, &fn2);
for (;;) {
fd = open_append(fn2.s);
if (fd != -1)
@@ -523,8 +523,8 @@ injectbounce(unsigned long id)
sender.s[sender.len - 1] = 0;
}
- fnmake2_bounce(id);
- fnmake_mess(id);
+ fnmake_bounce(id, &fn2);
+ fnmake_mess(id, &fn);
if (stat(fn2.s, &st) == -1) {
if (errno == error_noent)
return 1;
diff --git a/src/mxf-send/pass.c b/src/mxf-send/pass.c
@@ -100,7 +100,7 @@ pass_dochan(int c)
return;
if (pe.dt > recent)
return;
- fnmake_chanaddr(pe.id, c);
+ fnmake_chanaddr(pe.id, c, &fn);
prioq_delmin(&pqchan[c]);
pass[c].mpos = 0;
@@ -124,7 +124,7 @@ pass_dochan(int c)
return;
if (getln(&pass[c].ss, &line, &match, '\0') == -1) {
- fnmake_chanaddr(pass[c].id, c);
+ fnmake_chanaddr(pass[c].id, c, &fn);
log3("warning: trouble reading ", fn.s, "; will try again later\n");
close(pass[c].fd);
job_close(pass[c].j);
@@ -146,7 +146,7 @@ pass_dochan(int c)
case 'D':
break;
default:
- fnmake_chanaddr(pass[c].id, c);
+ fnmake_chanaddr(pass[c].id, c, &fn);
log3("warning: unknown record type in ", fn.s, "!\n");
close(pass[c].fd);
job_close(pass[c].j);
@@ -173,7 +173,7 @@ messdone(unsigned long id)
struct stat st;
for (c = 0; c < CHANNELS; ++c) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
if (stat(fn.s, &st) == 0)
return; /* false alarm; consequence of HOPEFULLY */
if (errno != error_noent) {
@@ -182,7 +182,7 @@ messdone(unsigned long id)
}
}
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
if (stat(fn.s, &st) == 0)
return;
if (errno != error_noent) {
@@ -190,7 +190,7 @@ messdone(unsigned long id)
goto fail;
}
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (stat(fn.s, &st) == -1) {
if (errno == error_noent)
return;
@@ -206,14 +206,14 @@ messdone(unsigned long id)
log3("end msg ", strnum3, "\n");
/* -todo +info -local -remote -bounce */
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (unlink(fn.s) == -1) {
log3("warning: unable to unlink ", fn.s, "; will try again later\n");
goto fail;
}
/* -todo -info -local -remote -bounce; we can relax */
- fnmake_foop(id);
+ fnmake_foop(id, &fn);
if (substdio_putflush(&sstoqc, fn.s, fn.len) == -1) {
cleandied();
return;
diff --git a/src/mxf-send/rewrite.c b/src/mxf-send/rewrite.c
@@ -97,6 +97,147 @@ rewrite(char *recip)
return 1;
}
+/* may trash recip. must set up rwline, between a T and a \0.
+ * masks the global rwline. */
+int
+rewrite_r(char *recip, stralloc *rwline, stralloc *addr)
+{
+ unsigned int i;
+ char *x;
+ unsigned int at;
+
+ if (!stralloc_copys(rwline, "T"))
+ return AMNESIAC;
+ if (!stralloc_copys(addr, recip))
+ return AMNESIAC;
+
+ i = byte_rchr(addr.s, addr.len, '@');
+ if (i == addr.len) {
+ if (!stralloc_cats(addr, "@"))
+ return AMNESIAC;
+ if (!stralloc_cat(addr, &envnoathost))
+ return AMNESIAC;
+ }
+
+ /* MXF NOTE: Double tap now if you'd scrunkly the when!
+ * This makes no sense. This is a crock. Nobody actually uses the
+ * percent hack.
+ * A respectable site with UUCP source routing allows local parts
+ * to contain exclamatories.
+ * I don't know if constmap is threadsafe. I have to assume that it is not.
+ */
+ while (constmap(&mappercenthack, addr->s + i + 1, addr->len - i - 1)) {
+ unsigned int j = byte_rchr(addr->s, i, '%');
+ if (j == i)
+ break;
+ addr->len = i;
+ i = j;
+ addr->s[i] = '@';
+ }
+
+ /* MXF NOTE: This value is obscurely named.
+ * This is the position of the at in addr->s.
+ */
+ at = byte_rchr(addr->s, addr->len, '@');
+
+ /* MXF NOTE: so what's happening here is that addr, our static,
+ * the value to the right of @ is being checked against
+ * constmap maplocals. Return 0 if "by land" (local).
+ * Same TS note as above.
+ */
+ if (constmap(&maplocals, addr->s + at + 1, addr->len - at - 1)) {
+ if (!stralloc_cat(rwline, addr)) {
+ return AMNESIAC;
+ }
+ if (!stralloc_0(rwline)) {
+ return AMNESIAC;
+ }
+ /* Memory has been malloc'd in addr.s. If we don't free
+ * it now, that's a memory leak. */
+ return 0;
+ }
+
+ /* MXF NOTE: so what's happening here is that addr, our static,
+ * if start of addrlen, or if one after the @, or if at end,
+ * or if cursor>at and addr->s[cursor] is an ascii dot,
+ * then if constmap returns anything useful,
+ * prepend the virtual prepend (XXX uses "-" even if different
+ * dash is used), and return 1 since by land (local).
+ * TODO: turn to different channel idea
+ */
+ for (i = 0; i <= addr->len; ++i)
+ if (!i || (i == at + 1) || (i == addr->len) || ((i > at) && (addr->s[i] == '.')))
+ if ((x = constmap(&mapvdoms, addr->s + i, addr->len - i))) {
+ if (!*x)
+ break;
+ if (!stralloc_cats(rwline, x)) {
+ return AMNESIAC;
+ }
+ if (!stralloc_cats(rwline, "-")) {
+ return AMNESIAC;
+ }
+ if (!stralloc_cat(rwline, addr)) {
+ return AMNESIAC;
+ }
+ if (!stralloc_0(rwline)) {
+ return AMNESIAC;
+ }
+ return 0;
+ }
+
+ if (!stralloc_cat(&rwline, addr)) {
+ return AMNESIAC;
+ }
+ if (!stralloc_0(&rwline)) {
+ return AMNESIAC;
+ }
+ /* MXF NOTE: it isn't going down channel 0, so it's going down channel 1.
+ */
+ return 1;
+}
+
+int rewrite_staticaddr(char *recip, stralloc *rwline)
+{
+ static stralloc addr = TA_ZERO; /* reusable */
+ int r = -1;
+ r = rewrite_r(recip, rwline, &addr);
+ return r;
+}
+
+int rewrite_staticaddr_staticrwline(char *recip)
+{
+ static stralloc addr = TA_ZERO; /* reusable */
+ int r = -1;
+ r = rewrite_r(recip, &rwline, &addr); /* There's already a global rwline, remember? */
+ return r;
+}
+
+int rewrite_aaddr(char *recip, stralloc *rwline)
+{
+ stralloc addr = TA_ZERO; /* disposable */
+ int r = -1;
+ if (!stralloc_readyplus(addr, 257)) return AMNESIAC; /* It'll be overwritten anyway. This is just to create a block of memory for it. With some luck, more won't be needed */
+ r = rewrite_r(recip, rwline, &addr);
+ free(addr.s);
+ return r;
+}
+
+/* 'a' means automatic; i.e. procedure-local. that should be tsafe, but inefficient.
+ * I (Amelia) expect that a serious MT use of rewrite would have a thread-local pool of strallocs
+ * for rewrite. */
+int rewrite_aaddr_arwline(char *recip)
+{
+ stralloc addr = TA_ZERO; /* disposable */
+ stralloc rwline = TA_ZERO; /* disposable */
+ int r = -1;
+ if (!stralloc_readyplus(addr, 257)) return AMNESIAC; /* It'll be overwritten anyway. This is just to create a block of memory for it. With some luck, more won't be needed */
+ if (!stralloc_readyplus(rwline, 257)) return AMNESIAC; /* It'll be overwritten anyway. This is just to create a block of memory for it. With some luck, more won't be needed */
+ r = rewrite_r(recip, &rwline, &addr);
+ free(addr.s);
+ free(rwline.s);
+ return r;
+}
+
// QUERY should return AMNESIAC?
void
senderadd(stralloc * sa, char *sender, char *recip)
diff --git a/src/mxf-send/todo.c b/src/mxf-send/todo.c
@@ -85,15 +85,15 @@ todo_do(fd_set * rfds)
if (!len || dent->d_name[len])
return;
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
- fd = open_read(fn.s);
+ fd = open_read(fn.s); /* fn just comes out of nowhere. */
if (fd == -1) {
log3("warning: unable to open ", fn.s, "\n");
return;
}
- fnmake_mess(id);
+ fnmake_mess(id, &fn);
/* just for the statistics */
if (stat(fn.s, &st) == -1) {
log3("warning: unable to stat ", fn.s, "\n");
@@ -101,7 +101,7 @@ todo_do(fd_set * rfds)
}
for (c = 0; c < CHANNELS; ++c) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
if (unlink(fn.s) == -1)
if (errno != error_noent) {
log3("warning: unable to unlink ", fn.s, "\n");
@@ -109,7 +109,7 @@ todo_do(fd_set * rfds)
}
}
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (unlink(fn.s) == -1)
if (errno != error_noent) {
log3("warning: unable to unlink ", fn.s, "\n");
@@ -137,7 +137,7 @@ todo_do(fd_set * rfds)
for (;;) {
if (getln(&ss, &todoline, &match, '\0') == -1) {
/* perhaps we're out of memory, perhaps an I/O error */
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
log3("warning: trouble reading ", fn.s, "\n");
goto fail;
}
@@ -153,7 +153,7 @@ todo_do(fd_set * rfds)
break;
case 'F':
if (substdio_putflush(&ssinfo, todoline.s, todoline.len) == -1) {
- fnmake_info(id);
+ fnmake_info(id, &fn);
log3("warning: trouble writing to ", fn.s, "\n");
goto fail;
}
@@ -178,7 +178,7 @@ todo_do(fd_set * rfds)
break;
}
if (fdchan[c] == -1) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
fdchan[c] = open_excl(fn.s);
if (fdchan[c] == -1) {
log3("warning: unable to create ", fn.s, "\n");
@@ -189,13 +189,13 @@ todo_do(fd_set * rfds)
flagchan[c] = 1;
}
if (substdio_bput(&sschan[c], rwline.s, rwline.len) == -1) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
log3("warning: trouble writing to ", fn.s, "\n");
goto fail;
}
break;
default:
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
log3("warning: unknown record type in ", fn.s, "\n");
goto fail;
}
@@ -204,7 +204,7 @@ todo_do(fd_set * rfds)
close(fd);
fd = -1;
- fnmake_info(id);
+ fnmake_info(id, &fn);
if (substdio_flush(&ssinfo) == -1) {
log3("warning: trouble writing to ", fn.s, "\n");
goto fail;
@@ -218,10 +218,10 @@ todo_do(fd_set * rfds)
for (c = 0; c < CHANNELS; ++c)
if (fdchan[c] != -1) {
- fnmake_chanaddr(id, c);
+ fnmake_chanaddr(id, c, &fn);
if (substdio_flush(&sschan[c]) == -1) {
log3("warning: trouble writing to ", fn.s, "\n");
- goto fail;
+ goto fail; /* jump... */
}
if (fsync(fdchan[c]) == -1) {
log3("warning: trouble fsyncing ", fn.s, "\n");
@@ -231,13 +231,13 @@ todo_do(fd_set * rfds)
fdchan[c] = -1;
}
- fnmake_todo(id);
+ fnmake_todo(id, &fn);
if (substdio_putflush(&sstoqc, fn.s, fn.len) == -1) {
- cleandied();
+ cleandied(); /* the clean pipe is no longer writable. flag that up, and exit ASAP. ~Mel */
return;
}
if (substdio_get(&ssfromqc, &ch, 1) != 1) {
- cleandied();
+ cleandied(); /* ^ */
return;
}
if (ch != '+') {
@@ -262,6 +262,8 @@ todo_do(fd_set * rfds)
return;
fail:
+ /* this little number is called under exception. It cleans up
+ * the state of the message. */
if (fd != -1)
close(fd);
if (fdinfo != -1)
@@ -270,3 +272,7 @@ fail:
if (fdchan[c] != -1)
close(fdchan[c]);
}
+
+int todo_do_onemsg(unsigned long msgid)
+{
+}