1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
|
/*
* Copyright 1988 by Rayan S. Zachariassen, all rights reserved.
* This will be free software, but only when it is finished.
*
*/
/*
* Lots of modifications (new guts, more or less..) by
* Matti Aarnio <mea@nic.funet.fi> (copyright) 1992-1999
*/
#define USE_SIGREAPER /* DO Use SIGCLD-driven reaper.. */
#include "hostenv.h"
#include "zmalloc.h"
#include "splay.h"
#include "shmmib.h"
/* Some "forward declarations" */
struct config_entry;
struct procinfo;
struct web;
struct thread;
struct threadgroup;
struct vertex;
struct config_entry {
struct config_entry *next;
char *channel; /* channel part of pattern */
char *host; /* host part of pattern */
time_t interval; /* how often to start up these things */
time_t expiry; /* bounce the message after this long in q's */
char *expiryform; /* use this form as the error message */
/* Following two need to be SIGNED variables */
int uid; /* what uid to run the transport agent under */
int gid; /* what gid to run the transport agent under */
char *command; /* the command to run */
int flags; /* miscellaneous flags */
/* #define CFG_BYCHANNEL 0x0001 */ /* obsolete thing.. */
#define CFG_WITHHOST 0x0002
#define CFG_AGEORDER 0x0004 /* by ctlfile->ctime -value */
#define CFG_QUEUEONLY 0x0008
#define CFG_WAKEUPRESTARTONLY 0x0010
#if 0
int bychannel; /* indicates $channel occurs in command */
int withhost; /* indicated $host occurs in command */
int ctlageorder; /* run attempts on oldest-first basis */
#endif
int maxkids; /* run command only if # TA's running < this */
int maxkidChannel; /* run only if # TA's running channel < this */
int maxkidThreads; /*run only if # TA's running thread-ring<this*/
int maxkidThread; /*run only if # TA's running thread < this */
int idlemax; /* max time to keep idle ta-procs around */
int skew; /* retry skew parameter */
int mark; /* non-0 if we started a TA the last time */
int priority; /* Scheduling priority */
int overfeed; /* How much overfeeding instead of
sync processing ? */
char **argv; /* execv parameters for the command */
int nretries; /* number of retry factors known */
int *retries; /* list of nretries retry factors */
char *deliveryform; /* name of delivery error form */
int reporttimes[4]; /* Shall match _CFTAG_RCPTDELAYSIZE */
};
#define L_CTLFILE 0
#define L_HOST 1
#define L_CHANNEL 2
#define SIZE_L 3
extern struct sptree *spt_mesh[SIZE_L];
#define V_NONE 0
#define V_ALL 1
#define V_SELECT 2
struct ctlfile {
int fd; /* a file descriptor pointing at the file */
char *vfpfn; /* a filename for verbose logging of mail */
uid_t uid; /* the owner of the control file (= msg file)*/
time_t mtime; /* original msg file's mtime (~ arrival) */
time_t envctime; /* when the transport file was created */
int haderror; /* some errors/diagnostics need processing */
int resynccount; /* How many resync requests ? */
#define MAXRESYNCS 30
struct vertex *head; /* head of the list of groups */
int nlines; /* number of lines/entries in the file */
char *erroraddr; /* error address(es) */
int iserrmesg; /* error channel -- to detect 'MAIL FROM:<>' */
char *contents; /* the control file as copied into memory */
char *logident; /* identification for log entries */
char *deliveryform; /* [mea] Name of delivery error form */
char *envid; /* DSN envid */
char *dsnretmode; /* DSN ret-mode: FULL/HDRS */
u_long id; /* identification # (inode# of control file) */
char *mid; /* msg identification (name of message file) */
int dirind; /* -1, if no hashed dir, >= 0, if subdired */
int rcpnts_total; /* how many recipients all in all ? */
int rcpnts_failed; /* .. failed ones of them ? */
int rcpnts_work; /* .. yet to deliver ? */
int mark; /* flag used by selector() to pass filenames */
int msgbodyoffset; /* size of original headers to skip on errrpt*/
int format; /* Message format version -- _CF_FORMAT data */
int offset[1]; /* array of nlines byte offsets into the file*/
};
struct threadgroup {
int groupid; /* Unique id */
int threads; /* Number of threads in the group */
int transporters; /* Number of transporters running */
int idlecnt; /* Number of idle transporters */
struct procinfo *idleproc; /* Idle procs in this group */
struct web *wchan; /* Channel identity web */
struct web *whost; /* Host identity web */
char *hostpatt;
int withhost; /* When set, wchan matters. */
struct thread *thread; /* First of the thread in the group */
struct thread *thrtail; /* Last of the threads in the group */
struct threadgroup *nextthg; /* Ring of thread groups */
struct threadgroup *prevthg;
struct config_entry *cep; /* Pointer to a config database */
struct config_entry ce; /* consed scheduler config file entry*/
};
struct thread {
long threadid; /* Unique id */
time_t wakeup; /* When to wake up ? */
int attempts; /* How many times activated ? */
int retryindex; /* when, what ? */
char *channel, *host; /* documenting */
char *pending; /* reason for pending */
struct web *wchan; /* Web of CHANNELs */
struct web *whost; /* Web of HOSTs */
struct thread *nexttr; /* Next one in threads queue */
struct thread *prevtr; /* previous one ... */
struct thread *nextthg; /* Next one in thread GROUP */
struct thread *prevthg; /* previous one.. */
struct threadgroup *thgrp; /* our group-leader */
struct vertex *thvertices; /* First one of the thread vertices */
struct vertex *lastthvertex; /* Last one of the thread vertices */
struct procinfo *proc; /* NULL or ptr to xport proc */
int thrkids; /* Number of procs at this thread */
int jobs; /* How many items in this thread */
int unfed; /* How many not yet fed to TAs */
struct vertex *nextfeed; /* vertex within that thread */
/* feed_child() forwards nextfeed */
};
struct web {
char *name; /* name of the L_? thingy */
int linkcnt; /* How many usage instances */
int kids; /* how many transport agents running for me */
struct vertex *link; /* points at group of addresses */
struct vertex *lastlink; /* for efficiency at link_in() */
};
typedef enum {
CFSTATE_LARVA = 1, /* The first feed of the thread */
CFSTATE_STUFFING = 2, /* More feeds for the thread */
CFSTATE_FINISHING = 3, /* end of thread, waiting reports */
CFSTATE_IDLE = 4, /* Idle state */
CFSTATE_ERROR = 0 /* Error encountered */
} TASTATE;
/* State changes: fork() -> (1) --> (2) -+-> (3) -+-> (4) -+-> death
^ ^ | | |
| |-<-| v v
|---<------------<---|--<-----|
*/
struct procinfo {
pid_t pid; /* Process-id */
int reaped;
int tofd; /* tell transporter job data thru this */
int waitstat; /* What previously called WAIT told.. */
TASTATE state; /* Child-Feed State Machine state */
time_t hungertime; /* .. when last state change */
int overfed; /* Now many jobs fed to it over the normal 1?*/
time_t feedtime; /* .. when fed */
struct web *ch; /* Web of CHANNELs */
struct web *ho; /* Web of HOSTs */
/* Set at channel creation, removed at
reclaim(), modified at thread_start()
when using IDLE queue. */
struct threadgroup *thg; /* The thread-ring we are in */
struct thread *pthread; /* The thread we are processing */
/* ta_hungry() forwards pthread */
struct procinfo *pnext; /* next one of procs in idle/thread */
struct procinfo *pprev; /* prev one of procs in idle/thread */
char *carryover; /* Long responces.. */
int cmdlen; /* buffer content size */
int cmdspc; /* buffer size */
char *cmdbuf; /* outgoing pipe leftovers.. */
char *cmdline; /* Approximation of the execl() params */
int cmdlspc; /* cmdline buffer size */
};
/* Stores the offset indices of all addresses that have same channel and host*/
struct vertex {
struct ctlfile *cfp; /* control file containing this group*/
int qid; /* mailq report id - filled at qprint*/
struct web *orig[SIZE_L]; /* original names (channel,host,etc) */
struct vertex *next[SIZE_L]; /* next group with same L_? */
struct vertex *prev[SIZE_L]; /* previous group with same L_? */
struct thread *thread; /* the thread we are in */
struct threadgroup *thgrp; /* the group we are in */
struct vertex *nextitem; /* next in list of scheduled vertices*/
struct vertex *previtem; /* prev in list of scheduled vertices*/
char *message; /* some text associated with node */
int headeroffset; /* Message headers for this rcpt */
int drptoffset; /* IETF-NOTARY DRPT data */
char *notary; /* IETF Notary report data */
int notaryflg; /* IETF DSN notary control flags */
#define NOT_NEVER 001
#define NOT_DELAY 002
#define NOT_SUCCESS 004
#define NOT_FAILURE 010
#define NOT_TRACE 020 /* RFC 2852 */
int ce_pending; /* pending on what ? */
time_t ce_expiry; /* when this vertex expires ? */
int attempts; /* count of number of TA invocations */
int retryindex; /* cur index into ce->retries array */
time_t wakeup; /* time to wake up and run this */
time_t lastfeed; /* When the last feed was ? */
time_t nextrprttime; /* next time after which collected
reports of this message will be
produced. */
time_t nextdlyrprttime;
char *sender; /* Message Sender/error recipient */
int ngroup; /* number of addresses in group */
int index[1]; /* index of cfp->offset for group */
};
#ifdef HAVE_SELECT
#if defined(BSD4_3) || defined(sun)
#include <sys/file.h>
#endif
#include <errno.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifndef __Usockaddr__ /* Match the same one in smtpserver.h */
typedef union {
struct sockaddr_in v4;
#ifdef INET6
struct sockaddr_in6 v6;
#endif
} Usockaddr;
#define __Usockaddr__
#endif
#endif /* HAVE_SOCKET */
/* mailq iterator state -- non-forking reporter mode */
struct mailq; /* forward declarator */
struct mailq {
struct mailq *nextmailq;
int auth; /* what can do */
int fd; /* FD for I/O (nonblocking-IO) */
#ifdef HAVE_SELECT
Usockaddr qaddr;
#endif /* HAVE_SOCKET */
time_t apopteosis;
char *challenge;
int inbufspace; /* Raw input buffer stuff */
int inbufsize;
int inbufcount;
char *inbuf;
int inplinespace; /* Split into lines */
int inplinesize;
char *inpline;
int outbufspace; /* Output buffer */
int outbufsize;
int outbufcount;
int outcol;
char *outbuf;
};
#define MQ2MODE_SNMP 0x0001
#define MQ2MODE_QQ 0x0002
#define MQ2MODE_FULL 0x0004
#define MQ2MODE_FULL2 0x0008
#define MQ2MODE_ETRN 0x0010
#define MQ2MODE_KILL 0x0020
|