72 log1s(
"alert: lost connection to qmail-clean ... exiting\n");
80 log1s(
"alert: oh no! lost spawn connection! dying...\n");
85#define REPORTMAX 10000
121 if (str_equal(
sender + i - 4,
"-@[]")) {
122 j = byte_rchr(
sender,i - 4,
'@');
124 if (
recip[
k] && (
j + 5 <= i)) {
128 while (!stralloc_cats(
sa,
"="))
nomem();
130 while (!stralloc_cats(
sa,
"@"))
nomem();
145 static stralloc
line = {0};
151 fdnumber = open_read(
fn.s);
152 if (fdnumber == -1)
return 0;
153 if (fstat(fdnumber,&st) == -1) { close(fdnumber);
return 0; }
154 buffer_init(&
b,read,fdnumber,
buf,
sizeof(
buf));
155 if (getln(&
b,&
line,&
match,
'\0') == -1) { close(fdnumber);
return 0; }
157 if (!
match)
return 0;
158 if (
line.s[0] !=
'F')
return 0;
162 while (!stralloc_0(
sa))
nomem();
238 if ((w == -1) && (errno == EPIPE))
288 if (stat(
fn.s,&st) == -1)
return;
292 if (stat(
fn.s,&st) == 0)
return;
293 if (errno != ENOENT)
return;
296 if (stat(
fn.s,&st) == 0)
return;
297 if (errno != ENOENT)
return;
303 log3s(
"warning: qmail-clean unable to clean up ",
fn.s,
"\n");
323#define CHECKSTAT if (errno != ENOENT) goto FAIL;
326 if (stat(
fn.s,&st) == -1) {
332 if (stat(
fn.s,&st) != -1)
return;
337 if (stat(
fn.s,&st) == -1) { flagchan[
c] = 0;
CHECKSTAT }
338 else { flagchan[
c] = 1; pechan[
c].
id =
id; pechan[
c].
dt = st.st_mtime; }
346 if (flagchan[
c])
break;
356 log3s(
"warning: unable to stat ",
fn.s,
"; will try again later\n");
370 if (x > 0)
pqadd(
id);
384 if (utime(
fn.s,
ut) == -1)
385 log3s(
"warning: unable to utime ",
fn.s,
"; message will be retried too soon\n");
397 for (i = 0; i <
pqchan[
c].len; ++i)
460 if (0 < --
jo[
j].refs)
return;
465 if (
jo[
j].flaghiteof && !
jo[
j].numtodo) {
467 if (unlink(
fn.s) == -1) {
468 log3s(
"warning: unable to unlink ",
fn.s,
"; will try again later\n");
473 if (stat(
fn.s,&st) == 0)
return;
474 if (errno != ENOENT) {
475 log3s(
"warning: unable to stat ",
fn.s,
"\n");
498 i = str_rchr(
recip,
'@');
501 domainlen = str_len(
domain);
503 for (i = 0; i <= domainlen; ++i)
504 if ((i == 0) || (i == domainlen) || (
domain[i] ==
'.'))
506 if (!*prepend)
break;
507 i = str_len(prepend);
508 if (str_diffn(
recip,prepend,i))
break;
509 if (
recip[i] !=
'-')
break;
510 return recip + i + 1;
538 for (pos =
bouncetext.len - 2; pos > 0; --pos)
547 fd = open_append(
fn2.s);
549 log1s(
"alert: unable to append to bounce message; HELP! sleeping...\n");
558 log1s(
"alert: unable to append to bounce message; HELP! sleeping...\n");
578 static stralloc
sender = {0};
579 static stralloc
quoted = {0};
597 if (stat(
fn2.s,&st) == -1) {
598 if (errno == ENOENT)
return 1;
599 log3s(
"warning: unable to stat ",
fn2.s,
"\n");
603 if (str_equal(
sender.s,
"#@[]"))
604 log3s(
"triple bounce: discarding ",
fn2.s,
"\n");
606 log3s(
"double bounce: discarding ",
fn2.s,
"\n");
609 {
log1s(
"warning: unable to start qmail-queue, will try later\n");
return 0; }
612 if (*
sender.s) { bouncesender =
""; bouncerecip =
sender.s; }
626Subject: failure notice\n\
628Hi. This is the qmail-send program at ");
631I'm afraid I wasn't able to deliver your message to the following addresses.\n\
632This is a permanent error; I've given up. Sorry it didn't work out.\n\
635I tried to deliver a bounce message to this address, but the bounce bounced!\n\
639 fd = open_read(
fn2.s);
644 while ((r = buffer_get(&
bi,
buf,
sizeof(
buf))) > 0)
651 qmail_puts(&
qqt,*
sender.s ?
"--- Below this line is a copy of the message.\n\n" :
"--- Below this line is the original bounce.\n\n");
657 fd = open_read(
fn.s);
663 bytestoget = (bytestogo <
sizeof(
buf)) ? bytestogo :
sizeof(
buf);
667 while (bytestoget > 0 && (r = buffer_get(&
bi,
buf,bytestoget)) > 0) {
669 bytestogo -= bytestoget;
670 bytestoget = (bytestogo <
sizeof(
buf)) ? bytestogo :
sizeof(
buf);
677 while ((r = buffer_get(&
bi,
buf,
sizeof(
buf))) > 0)
688 log1s(
"warning: trouble injecting bounce message, will try later\n");
698 if (unlink(
fn2.s) != 0) {
699 log3s(
"warning: unable to unlink ",
fn2.s,
"\n");
811 fd = open_write(
fn.s);
813 if (fstat(
fd,&st) == -1) { close(
fd);
break; }
814 if (seek_set(
fd,pos) == -1) { close(
fd);
break; }
815 if (
write(
fd,
"D",1) != 1) { close(
fd);
break; }
820 log3s(
"warning: trouble marking ",
fn.s,
"; message will be delivered twice!\n");
834 for (i = 0; i < r; ++i) {
843 if (!ch && (
dline[
c].len > 1)) {
846 log1s(
"warning: internal error: delivery report out of range\n");
853 while (!stralloc_cats(&
dline[
c],
"I'm not going to try again; this message has been in the queue too long.\n"))
nomem();
879 log3s(
"delivery ",
strnum3,
": report mangled, will defer\n");
944 { *wakeup = 0;
return; }
950 if (*wakeup > pe.
dt) *wakeup = pe.
dt;
957 if (*wakeup > pe.
dt)*wakeup = pe.
dt;
968 for (
j = 15;
j >= 0; --
j) {
969 y21 = (y << (
j + 1)) + (1 << (
j +
j));
970 if (y21 <= x - yy) { y += (1 <<
j); yy += y21; }
983 return birth + n * n;
990 static stralloc
line = {0};
1004 if (
pass[
c].
fd == -1)
goto trouble;
1018 log3s(
"warning: trouble reading ",
fn.s,
"; will try again later\n");
1033 switch (
line.s[0]) {
1042 log3s(
"warning: unknown record type in ",
fn.s,
"!\n");
1053 log3s(
"warning: trouble opening ",
fn.s,
"; will try again later\n");
1067 if (stat(
fn.s,&st) == 0)
return;
1068 if (errno != ENOENT) {
1069 log3s(
"warning: unable to stat ",
fn.s,
"; will try again later\n");
1075 if (stat(
fn.s,&st) == 0)
return;
1076 if (errno != ENOENT) {
1077 log3s(
"warning: unable to stat ",
fn.s,
"; will try again later\n");
1082 if (stat(
fn.s,&st) == -1) {
1083 if (errno == ENOENT)
return;
1084 log3s(
"warning: unable to stat ",
fn.s,
"; will try again later\n");
1097 if (unlink(
fn.s) == -1) {
1098 log3s(
"warning: unable to unlink ",
fn.s,
"; will try again later\n");
1106 if (ch !=
'+')
log3s(
"warning: qmail-clean unable to clean up ",
fn.s,
"\n");
1146 log1s(
"alert: lost connection to qmail-todo ... exiting\n");
1201 log1s(
"warning: qmail-send unable to understand qmail-todo\n");
1205 len = scan_ulong(s,&
id);
1206 if (!len || s[len]) {
1207 log1s(
"warning: qmail-send unable to understand qmail-todo\n");
1217 if (flagchan[
c])
break;
1232 if (!FD_ISSET(
todofdin,rfds))
return;
1235 if (r == -1)
return;
1244 for (i = 0; i < r; ++i) {
1266 log1s(
"warning: qmail-send unable to understand qmail-todo: report mangled\n");
1319 if (r == -1) {
log1s(
"alert: unable to reread control/virtualdomains\n");
return; }
1337 log1s(
"alert: unable to reread controls: unable to switch to home directory\n");
1343 while (chdir(
"queue") == -1) {
1344 log1s(
"alert: unable to switch back to queue directory; HELP! sleeping...\n");
1362 if (chdir(
auto_qmail) == -1) {
log1s(
"alert: cannot start: unable to switch to home directory\n");
_exit(110); }
1364 if (chdir(
"queue") == -1) {
log1s(
"alert: cannot start: unable to switch to queue directory\n");
_exit(110); }
1372 fd = open_write(
"lock/sendmutex");
1373 if (
fd == -1) {
log1s(
"alert: cannot start: unable to open mutex\n");
_exit(111); }
1374 if (lock_exnb(
fd) == -1) {
log1s(
"alert: cannot start: qmail-send is already running\n");
_exit(111); }
1381 while ((r == -1) && (errno == EINTR));
1382 if (r < 1) {
log1s(
"alert: cannot start: hath the daemon spawn no fire?\n");
_exit(111); }
1384 u = (
unsigned int) (
unsigned char) ch;
1417 if (wakeup <=
recent) tv.tv_sec = 0;
1421 if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) == -1)
1425 log1s(
"warning: trouble in select\n");
1438 log1s(
"status: exiting\n");
int constmap_init(struct constmap *cm, char *s, int len, int flagcolon)
int control_readint(int *i, char *fn)
int control_rldef(stralloc *sa, char *fn, int flagme, char *def)
int control_readfile(stralloc *sa, char *fn, int flagme)
int stralloc_copys(stralloc *, char const *)
unsigned int fmtqfn(char *s, char *dirslash, unsigned long id, int flagsplit)
void c(char *, char *, char *, int, int, int)
void p(char *, char *, int, int, int)
char fnmake_strnum[FMT_ULONG]
void pqadd(unsigned long id)
void fnmake_todo(unsigned long id)
void fnmake_foop(unsigned long id)
void messdone(unsigned long id)
void fnmake_info(unsigned long id)
int job_open(unsigned long id, int channel)
unsigned int concurrency[CHANNELS]
int getinfo(stralloc *sa, datetime_sec *dt, unsigned long id)
void markdone(int c, unsigned long id, seek_pos pos)
stralloc doublebouncehost
char * chanaddr[CHANNELS]
void fnmake_split(unsigned long id)
void cleanup_selprep(datetime_sec *wakeup)
int injectbounce(unsigned long id)
void addbounce(unsigned long id, char *recip, char *report)
struct constmap mappercenthack
void del_do(fd_set *rfds)
void comm_write(int c, int delnum, unsigned long id, char *sender, char *recip)
void fnmake_mess(unsigned long id)
void todo_do(fd_set *rfds)
void pass_selprep(datetime_sec *wakeup)
int flagspawnalive[CHANNELS]
void comm_do(fd_set *wfds)
void comm_selprep(int *nfds, fd_set *wfds)
void todo_selprep(int *nfds, fd_set *rfds, datetime_sec *wakeup)
void senderadd(stralloc *sa, char *sender, char *recip)
char * stripvdomprepend(char *recip)
unsigned long masterdelid
void del_start(int j, seek_pos mpos, char *recip)
char * chanstatusmsg[CHANNELS]
datetime_sec nextretry(datetime_sec birth, int c)
struct constmap maplocals
unsigned int concurrencyused[CHANNELS]
stralloc comm_buf[CHANNELS]
void fnmake_chanaddr(unsigned long id, int c)
void del_selprep(int *nfds, fd_set *rfds)
void fnmake2_bounce(unsigned long id)
void qmail_to(struct qmail *, char *)
void qmail_from(struct qmail *, char *)
void qmail_put(struct qmail *, char *, int)
char * qmail_close(struct qmail *)
unsigned long qmail_qp(struct qmail *)
void qmail_puts(struct qmail *, char *)
int qmail_open(struct qmail *)
void qmail_fail(struct qmail *)
void log2s(char *, char *)
void log3s(char *, char *, char *)
int quote(stralloc *, stralloc *)
int quote2(stralloc *, char *)