nightmaremail

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

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:
Msrc/mxf-send/cleanup.c | 8++++----
Msrc/mxf-send/comm.c | 2+-
Msrc/mxf-send/deliveries.c | 2+-
Msrc/mxf-send/fnmake.c | 41+++++++++++++++++++++++++++--------------
Msrc/mxf-send/mxf-send.c | 24++++++++++++------------
Msrc/mxf-send/pass.c | 16++++++++--------
Msrc/mxf-send/rewrite.c | 141+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/mxf-send/todo.c | 38++++++++++++++++++++++----------------
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) +{ +}