254 lines
5.6 KiB
C
254 lines
5.6 KiB
C
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include "readwrite.h"
|
|
#include "sig.h"
|
|
#include "exit.h"
|
|
#include "open.h"
|
|
#include "seek.h"
|
|
#include "fmt.h"
|
|
#include "alloc.h"
|
|
#include "substdio.h"
|
|
#include "datetime.h"
|
|
#include "now.h"
|
|
#include "triggerpull.h"
|
|
#include "extra.h"
|
|
#include "auto_qmail.h"
|
|
#include "auto_uids.h"
|
|
#include "date822fmt.h"
|
|
#include "fmtqfn.h"
|
|
|
|
#define DEATH 86400 /* 24 hours; _must_ be below q-s's OSSIFIED (36 hours) */
|
|
#define ADDR 1003
|
|
|
|
char inbuf[2048];
|
|
struct substdio ssin;
|
|
char outbuf[256];
|
|
struct substdio ssout;
|
|
|
|
datetime_sec starttime;
|
|
struct datetime dt;
|
|
unsigned long mypid;
|
|
unsigned long uid;
|
|
char *pidfn;
|
|
struct stat pidst;
|
|
unsigned long messnum;
|
|
char *messfn;
|
|
char *todofn;
|
|
char *intdfn;
|
|
int messfd;
|
|
int intdfd;
|
|
int flagmademess = 0;
|
|
int flagmadeintd = 0;
|
|
|
|
void cleanup()
|
|
{
|
|
if (flagmadeintd)
|
|
{
|
|
seek_trunc(intdfd,0);
|
|
if (unlink(intdfn) == -1) return;
|
|
}
|
|
if (flagmademess)
|
|
{
|
|
seek_trunc(messfd,0);
|
|
if (unlink(messfn) == -1) return;
|
|
}
|
|
}
|
|
|
|
void die(e) int e; { _exit(e); }
|
|
void die_write() { cleanup(); die(122); }
|
|
void die_read() { cleanup(); die(121); }
|
|
void sigalrm() { /* thou shalt not clean up here */ die(124); }
|
|
void sigbug() { die(101); }
|
|
|
|
unsigned int receivedlen;
|
|
char *received;
|
|
/* "Received: (qmail-queue invoked by alias); 26 Sep 1995 04:46:54 -0000\n" */
|
|
|
|
static unsigned int receivedfmt(s)
|
|
char *s;
|
|
{
|
|
unsigned int i;
|
|
unsigned int len;
|
|
len = 0;
|
|
i = fmt_str(s,"Received: (qmail "); len += i; if (s) s += i;
|
|
i = fmt_ulong(s,mypid); len += i; if (s) s += i;
|
|
i = fmt_str(s," invoked "); len += i; if (s) s += i;
|
|
if (uid == auto_uida)
|
|
{ i = fmt_str(s,"by alias"); len += i; if (s) s += i; }
|
|
else if (uid == auto_uidd)
|
|
{ i = fmt_str(s,"from network"); len += i; if (s) s += i; }
|
|
else if (uid == auto_uids)
|
|
{ i = fmt_str(s,"for bounce"); len += i; if (s) s += i; }
|
|
else
|
|
{
|
|
i = fmt_str(s,"by uid "); len += i; if (s) s += i;
|
|
i = fmt_ulong(s,uid); len += i; if (s) s += i;
|
|
}
|
|
i = fmt_str(s,"); "); len += i; if (s) s += i;
|
|
i = date822fmt(s,&dt); len += i; if (s) s += i;
|
|
return len;
|
|
}
|
|
|
|
void received_setup()
|
|
{
|
|
receivedlen = receivedfmt((char *) 0);
|
|
received = alloc(receivedlen + 1);
|
|
if (!received) die(123);
|
|
receivedfmt(received);
|
|
}
|
|
|
|
unsigned int pidfmt(s,seq)
|
|
char *s;
|
|
unsigned long seq;
|
|
{
|
|
unsigned int i;
|
|
unsigned int len;
|
|
|
|
len = 0;
|
|
i = fmt_str(s,"pid/"); len += i; if (s) s += i;
|
|
i = fmt_ulong(s,mypid); len += i; if (s) s += i;
|
|
i = fmt_str(s,"."); len += i; if (s) s += i;
|
|
i = fmt_ulong(s,starttime); len += i; if (s) s += i;
|
|
i = fmt_str(s,"."); len += i; if (s) s += i;
|
|
i = fmt_ulong(s,seq); len += i; if (s) s += i;
|
|
++len; if (s) *s++ = 0;
|
|
|
|
return len;
|
|
}
|
|
|
|
char *fnnum(dirslash,flagsplit)
|
|
char *dirslash;
|
|
int flagsplit;
|
|
{
|
|
char *s;
|
|
|
|
s = alloc(fmtqfn((char *) 0,dirslash,messnum,flagsplit));
|
|
if (!s) die(123);
|
|
fmtqfn(s,dirslash,messnum,flagsplit);
|
|
return s;
|
|
}
|
|
|
|
void pidopen()
|
|
{
|
|
unsigned int len;
|
|
unsigned long seq;
|
|
|
|
seq = 1;
|
|
len = pidfmt((char *) 0,seq);
|
|
pidfn = alloc(len);
|
|
if (!pidfn) die(123);
|
|
|
|
for (seq = 1;seq < 10;++seq)
|
|
{
|
|
if (pidfmt((char *) 0,seq) > len) die(101); /* paranoia */
|
|
pidfmt(pidfn,seq);
|
|
messfd = open_excl(pidfn);
|
|
if (messfd != -1) return;
|
|
}
|
|
|
|
die(103);
|
|
}
|
|
|
|
char tmp[FMT_ULONG];
|
|
|
|
void main()
|
|
{
|
|
unsigned int len;
|
|
char ch;
|
|
|
|
sig_blocknone();
|
|
umask(033);
|
|
if (chdir(auto_qmail) == -1) die(102);
|
|
if (chdir("queue") == -1) die(102);
|
|
|
|
mypid = getpid();
|
|
uid = getuid();
|
|
starttime = now();
|
|
datetime_tai(&dt,starttime);
|
|
|
|
received_setup();
|
|
|
|
sig_pipeignore();
|
|
sig_miscignore();
|
|
sig_alarmcatch(sigalrm);
|
|
sig_bugcatch(sigbug);
|
|
|
|
alarm(DEATH);
|
|
|
|
pidopen();
|
|
if (fstat(messfd,&pidst) == -1) die(104);
|
|
|
|
messnum = pidst.st_ino;
|
|
messfn = fnnum("mess/",1);
|
|
todofn = fnnum("todo/",0);
|
|
intdfn = fnnum("intd/",0);
|
|
|
|
if (link(pidfn,messfn) == -1) die(105);
|
|
if (unlink(pidfn) == -1) die(105);
|
|
flagmademess = 1;
|
|
|
|
substdio_fdbuf(&ssout,write,messfd,outbuf,sizeof(outbuf));
|
|
substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf));
|
|
|
|
if (substdio_bput(&ssout,received,receivedlen) == -1) die_write();
|
|
|
|
switch(substdio_copy(&ssout,&ssin))
|
|
{
|
|
case -2: die_read();
|
|
case -3: die_write();
|
|
}
|
|
|
|
if (substdio_flush(&ssout) == -1) die_write();
|
|
if (fsync(messfd) == -1) die_write();
|
|
|
|
intdfd = open_excl(intdfn);
|
|
if (intdfd == -1) die(108);
|
|
flagmadeintd = 1;
|
|
|
|
substdio_fdbuf(&ssout,write,intdfd,outbuf,sizeof(outbuf));
|
|
substdio_fdbuf(&ssin,read,1,inbuf,sizeof(inbuf));
|
|
|
|
if (substdio_bput(&ssout,"u",1) == -1) die_write();
|
|
if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,uid)) == -1) die_write();
|
|
if (substdio_bput(&ssout,"",1) == -1) die_write();
|
|
|
|
if (substdio_bput(&ssout,"p",1) == -1) die_write();
|
|
if (substdio_bput(&ssout,tmp,fmt_ulong(tmp,mypid)) == -1) die_write();
|
|
if (substdio_bput(&ssout,"",1) == -1) die_write();
|
|
|
|
if (substdio_get(&ssin,&ch,1) < 1) die_read();
|
|
if (ch != 'F') die(112);
|
|
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
|
|
for (len = 0;len < ADDR;++len)
|
|
{
|
|
if (substdio_get(&ssin,&ch,1) < 1) die_read();
|
|
if (substdio_put(&ssout,&ch,1) == -1) die_write();
|
|
if (!ch) break;
|
|
}
|
|
if (len >= ADDR) die(115);
|
|
|
|
if (substdio_bput(&ssout,QUEUE_EXTRA,QUEUE_EXTRALEN) == -1) die_write();
|
|
|
|
for (;;)
|
|
{
|
|
if (substdio_get(&ssin,&ch,1) < 1) die_read();
|
|
if (!ch) break;
|
|
if (ch != 'T') die(112);
|
|
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
|
|
for (len = 0;len < ADDR;++len)
|
|
{
|
|
if (substdio_get(&ssin,&ch,1) < 1) die_read();
|
|
if (substdio_bput(&ssout,&ch,1) == -1) die_write();
|
|
if (!ch) break;
|
|
}
|
|
if (len >= ADDR) die(115);
|
|
}
|
|
|
|
if (substdio_flush(&ssout) == -1) die_write();
|
|
if (fsync(intdfd) == -1) die_write();
|
|
|
|
if (link(intdfn,todofn) == -1) die(106);
|
|
|
|
triggerpull();
|
|
die(0);
|
|
}
|