netqmail-1.06/0000755000076400007640000000000010727260204012640 5ustar nelsonnelsonnetqmail-1.06/qmail-header.50000644000076400007640000001263306541176434015276 0ustar nelsonnelson.TH qmail-header 5 .SH NAME qmail-header \- format of a mail message .SH OVERVIEW At the top of every mail message is a highly structured .BR header . Many programs expect the header to carry certain information, as described below. The main function of .B qmail-inject is to make sure that each outgoing message has an appropriate header. For more detailed information, see .BR http://pobox.com/~djb/proto/immhf.html . .SH "MESSAGE STRUCTURE" A message contains a series of .I header fields\fR, a blank line, and a .IR body : .EX Received: (qmail-queue invoked by uid 666); .br 30 Jul 1996 11:54:54 -0000 .br From: djb@silverton.berkeley.edu (D. J. Bernstein) .br To: fred@silverton.berkeley.edu .br Date: 30 Jul 1996 11:54:54 -0000 .br Subject: Go, Bears! .br .br I've got money on this one. How about you? .br .br ---Dan (this is the third line of the body) .EE Each header field has a .IR name , a colon, some .IR contents , and a newline: .EX Subject: Go, Bears! .EE The field contents may be folded across several lines. Each line past the first must begin with a space or tab: .EX Received: (qmail-queue invoked by uid 666); .br 30 Jul 1996 11:54:54 -0000 .EE The field name must not contain spaces, tabs, or colons. Also, an empty field name is illegal. .B qmail-inject does not allow field names with unprintable characters. Case is irrelevant in field names: .B subject and .B SUBJECT and .B SuBjEcT have the same meaning. .SH "ADDRESS LISTS" Certain fields, such as .BR To , contain .I address lists\fR. An address list contains some number of .I addresses or .I address groups\fR, separated by commas: .EX a@b, c@d (Somebody), A Person , .br random group: g@h, i@j;, k@l .EE An .I address group has some text, a colon, a list of addresses, and a semicolon: .EX random group: g@h, i@j; .EE An address can appear in several forms. The most common form is .IR box@host . Every address must include a host name. If .B qmail-inject sees a lone box name it adds the .I default host name\fR. All host names should be fully qualified. .B qmail-inject appends the .I default domain name to any name without dots: .EX djb@silverton -> djb@silverton.berkeley.edu .EE It appends the .I plus domain name to any name that ends with a plus sign: .EX eric@mammoth.cs+ -> eric@mammoth.cs.berkeley.edu .EE A host name may be a dotted-decimal address: .EX djb@[128.32.183.163] .EE RFC 822 allows mailbox names inside angle brackets to include .I source routes\fR, but .B qmail-inject strips all source routes out of addresses. .SH "SENDER ADDRESSES" .B qmail-inject looks for sender address lists in the following fields: .BR Sender , .BR From , .BR Reply-To , .BR Return-Path , .BR Return-Receipt-To , .BR Errors-To , .BR Resent-Sender , .BR Resent-From , .BR Resent-Reply-To . If there is no .B From field, .B qmail-inject adds a new .B From field with the name of the user invoking .B qmail-inject. RFC 822 requires that certain sender fields contain only a single address, but .B qmail-inject does not enforce this restriction. .SH "RECIPIENT ADDRESSES" .B qmail-inject looks for recipient address lists in the following fields: .BR To , .BR Cc , .BR Bcc , .BR Apparently-To , .BR Resent-To , .BR Resent-Cc , .BR Resent-Bcc . Every message must contain at least one .B To or .B Cc or .BR Bcc . .B qmail-inject deletes any .B Bcc field. If there is no .B To or .B Cc field, .B qmail-inject adds a line .EX Cc: recipient list not shown: ; .EE This complies with RFC 822; it also works around some strange .B sendmail behavior, in case the message is passed through .B sendmail on another machine. .SH STAMPS Every message must contain a .B Date field, with the date in a strict format defined by RFC 822. If necessary .B qmail-inject creates a new .B Date field with the current date (in GMT). Every message should contain a .B Message-Id field. The field contents are a unique worldwide identifier for this message. If necessary .B qmail-inject creates a new .B Message-Id field. Another important field is .BR Received . Every time the message is sent from one system to another, a new .B Received field is added to the top of the message. .B qmail-inject does not create any .B Received fields. .SH "RESENT MESSAGES" A message is .I resent if it contains any of the following fields: .BR Resent-Sender , .BR Resent-From , .BR Resent-Reply-To , .BR Resent-To , .BR Resent-Cc , .BR Resent-Bcc , .BR Resent-Date , .BR Resent-Message-ID . If a message is resent, .B qmail-inject changes its behavior as follows. It deletes any .B Resent-Bcc field (as well as any .B Bcc field); if there are no .B Resent-To or .B Resent-Cc fields, .B qmail-inject adds an appropriate .B Resent-Cc line. It does .I not add a .B Cc line, even if neither .B To nor .B Cc is present. If there is no .B Resent-From field, .B qmail-inject adds a new .B Resent-From field. It does .I not add a new .B From field. .B qmail-inject adds .B Resent-Date if one is not already present; same for .BR Resent-Message-Id . It does .I not add new .B Date or .B Message-Id fields. .SH "OTHER FEATURES" Addresses are separated by commas, not spaces. When .B qmail-inject sees an illegal space, it inserts a comma: .EX djb fred -> djb, fred .EE .B qmail-inject removes all .B Return-Path header fields. .B qmail-inject also removes any .B Content-Length fields. .SH "SEE ALSO" addresses(5), envelopes(5), qmail-inject(8) netqmail-1.06/trywaitp.c0000644000076400007640000000012006541176434014672 0ustar nelsonnelson#include #include void main() { waitpid(0,0,0); } netqmail-1.06/timeoutconn.c0000644000076400007640000000240206541176434015360 0ustar nelsonnelson#include #include #include #include #include "ndelay.h" #include "select.h" #include "error.h" #include "readwrite.h" #include "ip.h" #include "byte.h" #include "timeoutconn.h" int timeoutconn(s,ip,port,timeout) int s; struct ip_address *ip; unsigned int port; int timeout; { char ch; struct sockaddr_in sin; char *x; fd_set wfds; struct timeval tv; byte_zero(&sin,sizeof(sin)); byte_copy(&sin.sin_addr,4,ip); x = (char *) &sin.sin_port; x[1] = port; port >>= 8; x[0] = port; sin.sin_family = AF_INET; if (ndelay_on(s) == -1) return -1; /* XXX: could bind s */ if (connect(s,(struct sockaddr *) &sin,sizeof(sin)) == 0) { ndelay_off(s); return 0; } if ((errno != error_inprogress) && (errno != error_wouldblock)) return -1; FD_ZERO(&wfds); FD_SET(s,&wfds); tv.tv_sec = timeout; tv.tv_usec = 0; if (select(s + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(s,&wfds)) { int dummy; dummy = sizeof(sin); if (getpeername(s,(struct sockaddr *) &sin,&dummy) == -1) { read(s,&ch,1); return -1; } ndelay_off(s); return 0; } errno = error_timeout; /* note that connect attempt is continuing */ return -1; } netqmail-1.06/ipme.h0000644000076400007640000000022106541176434013750 0ustar nelsonnelson#ifndef IPME_H #define IPME_H #include "ip.h" #include "ipalloc.h" extern ipalloc ipme; extern int ipme_init(); extern int ipme_is(); #endif netqmail-1.06/make-load.sh0000644000076400007640000000011106541176434015031 0ustar nelsonnelsonecho 'main="$1"; shift' echo exec "$LD" '-o "$main" "$main".o ${1+"$@"}' netqmail-1.06/SENDMAIL0000644000076400007640000000604106541176434013772 0ustar nelsonnelsonThis document explains what you, as a user, will notice when the system switches from sendmail to qmail. This is a global document, part of the qmail package, not reflecting the decisions made by your system administrator. For details on * which local delivery agent qmail is configured to use, * whether qmail is configured to use dot-forward, * whether ezmlm is installed, * whether fastforward is installed, and * all other local configuration features, see your local sendmail-qmail upgrade announcement (which your system administrator may have placed into /var/qmail/doc/ANNOUNCE). --- Mailbox location If your system administrator has configured qmail to use binmail for local deliveries, your mailbox will be in /var/spool/mail/you, just as it was under sendmail. If your system administrator has configured qmail to use qmail-local for local deliveries, your mailbox will be moved to ~you/Mailbox. There is a symbolic link from /var/spool/mail/you to ~you/Mailbox, so your mail reader will find the mailbox at its new location. --- Loop control qmail-local automatically adds a Delivered-To field at the top of every delivered message. It uses Delivered-To to prevent mail forwarding loops, including cross-host mailing-list loops. --- Outgoing messages qmail lets you use environment variables to control the appearance of your outgoing mail, supplementing the features offered by your MUA. For example, qmail-inject will set up Mail-Followup-To for you automatically if you tell it which mailing lists you are subscribed to. See qmail-inject(8) for a complete list of features. If you're at (say) sun.ee.movie.edu, qmail lets you type joe@mac for joe@mac.ee.movie.edu, and joe@mac+ for joe@mac.movie.edu without the ee. sendmail has a different interpretation of hostnames without dots. --- Forwarding and mailing lists qmail gives you the power to set up your own mailing lists without pestering your system administrator. Under qmail, you are in charge of all addresses of the form you-anything. The delivery of you-anything is controlled by ~you/.qmail-anything, a file in your home directory. For example, if you want to set up a bug-of-the-month-club mailing list, you can put a list of addresses into ~you/.qmail-botmc. Any mail to you-botmc will be forwarded to all of those addresses. Mail directly to you is controlled by ~you/.qmail. You can even set up a catch-all, ~you/.qmail-default, to handle unknown you- addresses. See dot-qmail(5) for the complete story. Beware that the syntax of .qmail is different from the syntax of sendmail's .forward file. If your system administrator has configured qmail to use the dot-forward compatibility tool, you can put forwarding addresses (and programs) into .forward the same way you did with sendmail. If your system administrator has installed ezmlm, you can use ezmlm-make to instantly set up a professional-quality mailing list, handling subscriptions and archives automatically. If your system administrator has installed fastforward, you can easily manage a large database of forwarding addresses. netqmail-1.06/dot-qmail.90000644000076400007640000001630610724074016014630 0ustar nelsonnelson.TH dot-qmail 5 .SH NAME dot-qmail \- control the delivery of mail messages .SH DESCRIPTION Normally the .B qmail-local program delivers each incoming message to your system mailbox, .IR homedir\fB/Mailbox , where .I homedir is your home directory. It can instead write the mail to a different file or directory, forward it to another address, distribute it to a mailing list, or even execute programs, all under your control. .SH "THE QMAIL FILE" To change .BR qmail-local 's behavior, set up a .B .qmail file in your home directory. .B .qmail contains one or more lines. Each line is a delivery instruction. .B qmail-local follows each instruction in turn. There are five types of delivery instructions: (1) comment; (2) program; (3) forward; (4) mbox; (5) maildir. .TP 5 (1) A comment line begins with a number sign: .EX # this is a comment .EE .B qmail-local ignores the line. .TP 5 (2) A program line begins with a vertical bar: .EX |preline /usr/ucb/vacation djb .EE .B qmail-local takes the rest of the line as a command to supply to .BR sh . See .B qmail-command(8) for further information. .TP 5 (3) A forward line begins with an ampersand: .EX &me@new.job.com .EE .B qmail-local takes the rest of the line as a mail address; it uses .B qmail-queue to forward the message to that address. The address must contain a fully qualified domain name; it must not contain extra spaces, angle brackets, or comments: .EX # the following examples are WRONG .br &me@new .br & .br & me@new.job.com .br &me@new.job.com (New Address) .EE If the address begins with a letter or number, you may leave out the ampersand: .EX me@new.job.com .EE Note that .B qmail-local omits its new .B Return-Path line when forwarding messages. .TP 5 (4) An .I mbox line begins with a slash or dot, and does not end with a slash: .EX /home/djb/Mailbox.sos .EE .B qmail-local takes the entire line as a filename. It appends the mail message to that file, using .BR flock -style file locking if possible. .B qmail-local stores the mail message in .I mbox format, as described in .BR mbox(5) . .B WARNING: On many systems, anyone who can read a file can .B flock it, and thus hold up .BR qmail-local 's delivery forever. Do not deliver mail to a publicly accessible file! If .B qmail-local is able to lock the file, but has trouble writing to it (because, for example, the disk is full), it will truncate the file back to its original length. However, it cannot prevent mailbox corruption if the system crashes during delivery. .TP 5 (5) A .I maildir line begins with a slash or dot, and ends with a slash: .EX /home/djb/Maildir/ .EE .B qmail-local takes the entire line as the name of a directory in .I maildir format. It reliably stores the incoming message in that directory. See .B maildir(5) for more details. .PP If .B .qmail has the execute bit set, it must not contain any program lines, .I mbox lines, or .I maildir lines. If .B qmail-local sees any such lines, it will stop and indicate a temporary failure. If .B .qmail is completely empty (0 bytes long), or does not exist, .B qmail-local follows the .I defaultdelivery instructions set by your system administrator; normally .I defaultdelivery is .BR ./Mailbox , so .B qmail-local appends the mail message to .B Mailbox in .I mbox format. .B .qmail may contain extra spaces and tabs at the end of a line. Blank lines are allowed, but not for the first line of .BR .qmail . If .B .qmail is world-writable, .B qmail-local stops and indicates a temporary failure. .SH "SAFE QMAIL EDITING" Incoming messages can arrive at any moment. If you want to safely edit your .B .qmail file, first set the sticky bit on your home directory: .EX chmod +t $HOME .EE .B qmail-local will temporarily defer delivery of any message to you if your home directory is sticky (or group-writable or other-writable, which should never happen). Make sure to .EX chmod -t $HOME .EE when you are done! It's a good idea to test your new .B .qmail file as follows: .EX qmail-local -n $USER ~ $USER '' '' '' '' ./Mailbox .EE .SH "EXTENSION ADDRESSES" In the .B qmail system, you control all local addresses of the form .IR user\fBBREAK\fIanything , as well as the address .I user itself, where .I user is your account name. Delivery to .I user\fBBREAK\fIanything is controlled by the file .IR homedir/\fB.qmail\-\fIanything . (These rules may be changed by the system administrator; see .BR qmail-users (5).) The .B alias user controls all other addresses. Delivery to .I local is controlled by the file .IR homedir/\fB.qmail\-\fIlocal , where .I homedir is .BR alias 's home directory. In the following description, .B qmail-local is handling a message addressed to .IR local@domain , where .I local is controlled by .BR .qmail\-\fIext . Here is what it does. If .B .qmail\-\fIext is completely empty, .B qmail-local follows the .I defaultdelivery instructions set by your system administrator. If .B .qmail\-\fIext doesn't exist, .B qmail-local will try some default .B .qmail files. For example, if .I ext is .BR foo-bar , .B qmail-local will try first .BR .qmail-foo-bar , then .BR .qmail-foo-default , and finally .BR .qmail-default . If none of these exist, .B qmail-local will bounce the message. (Exception: for the basic .I user address, .B qmail-local treats a nonexistent .B .qmail the same as an empty .BR .qmail .) .B WARNING: For security, .B qmail-local replaces any dots in .I ext with colons before checking .BR .qmail\-\fIext . For convenience, .B qmail-local converts any uppercase letters in .I ext to lowercase. When .B qmail-local forwards a message as instructed in .B .qmail\-\fIext (or .BR .qmail-default ), it checks whether .B .qmail\-\fIext\fB-owner\fP exists. If so, it uses .I local\fB-owner@\fIdomain as the envelope sender for the forwarded message. Otherwise it retains the envelope sender of the original message. Exception: .B qmail-local always retains the original envelope sender if it is the empty address or .BR #@[] , i.e., if this is a bounce message. .B qmail-local also supports .B variable envelope return paths (VERPs): if .B .qmail\-\fIext\fB-owner\fP and .B .qmail\-\fIext\fB-owner-default\fP both exist, it uses .I local\fB\-owner\-@\fIdomain\fB-@[] as the envelope sender. This will cause a recipient .I recip\fB@\fIreciphost to see an envelope sender of .IR local\fB\-owner\-\fIrecip\fB=\fIreciphost\fB@\fIdomain . .SH "ERROR HANDLING" If a delivery instruction fails, .B qmail-local stops immediately and reports failure. .B qmail-local handles forwarding after all other instructions, so any error in another type of delivery will prevent all forwarding. If a program returns exit code 99, .B qmail-local ignores all succeeding lines in .BR .qmail , but it still pays attention to previous forward lines. To set up independent instructions, where a temporary or permanent failure in one instruction does not affect the others, move each instruction into a separate .B .qmail\-\fIext file, and set up a central .B .qmail file that forwards to all of the .BR .qmail\-\fIext s. Note that .B qmail-local can handle any number of forward lines simultaneously. .SH "SEE ALSO" envelopes(5), maildir(5), mbox(5), qmail-users(5), qmail-local(8), qmail-command(8), qmail-queue(8), qmail-lspawn(8) netqmail-1.06/auto_patrn.h0000644000076400007640000000011206541176434015171 0ustar nelsonnelson#ifndef AUTO_PATRN_H #define AUTO_PATRN_H extern int auto_patrn; #endif netqmail-1.06/alloc.30000644000076400007640000000167606541176434014042 0ustar nelsonnelson.TH alloc 3 .SH NAME alloc \- allocate memory .SH SYNTAX .B #include char *\fBalloc\fP(\fInew\fR); void \fBalloc_free\fP(\fIx\fR); void \fBalloc_re\fP(&\fIx\fR,\fIold\fR,\fInew\fR); char *\fIx\fR; .br unsigned int \fIold\fR; .br unsigned int \fInew\fR; .SH DESCRIPTION .B alloc allocates enough space from the heap for .I new bytes of data, adequately aligned for any data type. .I new may be 0. .B alloc returns a pointer to the space. If space is not available, .B alloc returns 0, setting .B errno appropriately. .B alloc_free returns space to the heap. .B alloc_re expands the space allocated to .I x from .I old bytes to .I new bytes. It allocates new space, copies .I old bytes from the old space to the new space, returns the old space to the heap, and changes .I x to point to the new space. It then returns 1. If space is not available, .B alloc_re returns 0, leaving the old space alone. .SH "SEE ALSO" sbrk(2), malloc(3), error(3) netqmail-1.06/substdo.c0000644000076400007640000000374506541176434014512 0ustar nelsonnelson#include "substdio.h" #include "str.h" #include "byte.h" #include "error.h" static int allwrite(op,fd,buf,len) register int (*op)(); register int fd; register char *buf; register int len; { register int w; while (len) { w = op(fd,buf,len); if (w == -1) { if (errno == error_intr) continue; return -1; /* note that some data may have been written */ } if (w == 0) ; /* luser's fault */ buf += w; len -= w; } return 0; } int substdio_flush(s) register substdio *s; { register int p; p = s->p; if (!p) return 0; s->p = 0; return allwrite(s->op,s->fd,s->x,p); } int substdio_bput(s,buf,len) register substdio *s; register char *buf; register int len; { register int n; while (len > (n = s->n - s->p)) { byte_copy(s->x + s->p,n,buf); s->p += n; buf += n; len -= n; if (substdio_flush(s) == -1) return -1; } /* now len <= s->n - s->p */ byte_copy(s->x + s->p,len,buf); s->p += len; return 0; } int substdio_put(s,buf,len) register substdio *s; register char *buf; register int len; { register int n; n = s->n; if (len > n - s->p) { if (substdio_flush(s) == -1) return -1; /* now s->p == 0 */ if (n < SUBSTDIO_OUTSIZE) n = SUBSTDIO_OUTSIZE; while (len > s->n) { if (n > len) n = len; if (allwrite(s->op,s->fd,buf,n) == -1) return -1; buf += n; len -= n; } } /* now len <= s->n - s->p */ byte_copy(s->x + s->p,len,buf); s->p += len; return 0; } int substdio_putflush(s,buf,len) register substdio *s; register char *buf; register int len; { if (substdio_flush(s) == -1) return -1; return allwrite(s->op,s->fd,buf,len); } int substdio_bputs(s,buf) register substdio *s; register char *buf; { return substdio_bput(s,buf,str_len(buf)); } int substdio_puts(s,buf) register substdio *s; register char *buf; { return substdio_put(s,buf,str_len(buf)); } int substdio_putsflush(s,buf) register substdio *s; register char *buf; { return substdio_putflush(s,buf,str_len(buf)); } netqmail-1.06/binm3+df.sh0000644000076400007640000000061106541176434014601 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using dot-forward to support sendmail-style ~/.forward files. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using V7 binmail interface: /bin/mail -f exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|dot-forward .forward |preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/trysyslog.c0000644000076400007640000000017506541176434015100 0ustar nelsonnelson#include #include #include main() { openlog("foo",0,LOG_MAIL); syslog(0,"foo"); } netqmail-1.06/qmail-qmtpd.c0000644000076400007640000001425606541176434015254 0ustar nelsonnelson#include "stralloc.h" #include "substdio.h" #include "qmail.h" #include "now.h" #include "str.h" #include "fmt.h" #include "env.h" #include "sig.h" #include "rcpthosts.h" #include "auto_qmail.h" #include "readwrite.h" #include "control.h" #include "received.h" void badproto() { _exit(100); } void resources() { _exit(111); } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = write(fd,buf,len); if (r <= 0) _exit(0); return r; } char ssoutbuf[256]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); int saferead(fd,buf,len) int fd; char *buf; int len; { int r; substdio_flush(&ssout); r = read(fd,buf,len); if (r <= 0) _exit(0); return r; } char ssinbuf[512]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); unsigned long getlen() { unsigned long len = 0; char ch; for (;;) { substdio_get(&ssin,&ch,1); if (ch == ':') return len; if (len > 200000000) resources(); len = 10 * len + (ch - '0'); } } void getcomma() { char ch; substdio_get(&ssin,&ch,1); if (ch != ',') badproto(); } unsigned int databytes = 0; unsigned int bytestooverflow = 0; struct qmail qq; char buf[1000]; char buf2[100]; char *remotehost; char *remoteinfo; char *remoteip; char *local; stralloc failure = {0}; char *relayclient; int relayclientlen; main() { char ch; int i; unsigned long biglen; unsigned long len; int flagdos; int flagsenderok; int flagbother; unsigned long qp; char *result; char *x; unsigned long u; sig_pipeignore(); sig_alarmcatch(resources); alarm(3600); if (chdir(auto_qmail) == -1) resources(); if (control_init() == -1) resources(); if (rcpthosts_init() == -1) resources(); relayclient = env_get("RELAYCLIENT"); relayclientlen = relayclient ? str_len(relayclient) : 0; if (control_readint(&databytes,"control/databytes") == -1) resources(); x = env_get("DATABYTES"); if (x) { scan_ulong(x,&u); databytes = u; } if (!(databytes + 1)) --databytes; remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; for (;;) { if (!stralloc_copys(&failure,"")) resources(); flagsenderok = 1; len = getlen(); if (len == 0) badproto(); if (databytes) bytestooverflow = databytes + 1; if (qmail_open(&qq) == -1) resources(); qp = qmail_qp(&qq); substdio_get(&ssin,&ch,1); --len; if (ch == 10) flagdos = 0; else if (ch == 13) flagdos = 1; else badproto(); received(&qq,"QMTP",local,remoteip,remotehost,remoteinfo,(char *) 0); /* XXX: check for loops? only if len is big? */ if (flagdos) while (len > 0) { substdio_get(&ssin,&ch,1); --len; while ((ch == 13) && len) { substdio_get(&ssin,&ch,1); --len; if (ch == 10) break; if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); qmail_put(&qq,"\015",1); } if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qq); qmail_put(&qq,&ch,1); } else { if (databytes) if (len > databytes) { bytestooverflow = 0; qmail_fail(&qq); } while (len > 0) { /* XXX: could speed this up, obviously */ substdio_get(&ssin,&ch,1); --len; qmail_put(&qq,&ch,1); } } getcomma(); len = getlen(); if (len >= 1000) { buf[0] = 0; flagsenderok = 0; for (i = 0;i < len;++i) substdio_get(&ssin,&ch,1); } else { for (i = 0;i < len;++i) { substdio_get(&ssin,buf + i,1); if (!buf[i]) flagsenderok = 0; } buf[len] = 0; } getcomma(); flagbother = 0; qmail_from(&qq,buf); if (!flagsenderok) qmail_fail(&qq); biglen = getlen(); while (biglen > 0) { if (!stralloc_append(&failure,"")) resources(); len = 0; for (;;) { if (!biglen) badproto(); substdio_get(&ssin,&ch,1); --biglen; if (ch == ':') break; if (len > 200000000) resources(); len = 10 * len + (ch - '0'); } if (len >= biglen) badproto(); if (len + relayclientlen >= 1000) { failure.s[failure.len - 1] = 'L'; for (i = 0;i < len;++i) substdio_get(&ssin,&ch,1); } else { for (i = 0;i < len;++i) { substdio_get(&ssin,buf + i,1); if (!buf[i]) failure.s[failure.len - 1] = 'N'; } buf[len] = 0; if (relayclient) str_copy(buf + len,relayclient); else switch(rcpthosts(buf,len)) { case -1: resources(); case 0: failure.s[failure.len - 1] = 'D'; } if (!failure.s[failure.len - 1]) { qmail_to(&qq,buf); flagbother = 1; } } getcomma(); biglen -= (len + 1); } getcomma(); if (!flagbother) qmail_fail(&qq); result = qmail_close(&qq); if (!flagsenderok) result = "Dunacceptable sender (#5.1.7)"; if (databytes) if (!bytestooverflow) result = "Dsorry, that message size exceeds my databytes limit (#5.3.4)"; if (*result) len = str_len(result); else { /* success! */ len = 0; len += fmt_str(buf2 + len,"Kok "); len += fmt_ulong(buf2 + len,(unsigned long) now()); len += fmt_str(buf2 + len," qp "); len += fmt_ulong(buf2 + len,qp); buf2[len] = 0; result = buf2; } len = fmt_ulong(buf,len); buf[len++] = ':'; len += fmt_str(buf + len,result); buf[len++] = ','; for (i = 0;i < failure.len;++i) switch(failure.s[i]) { case 0: substdio_put(&ssout,buf,len); break; case 'D': substdio_puts(&ssout,"66:Dsorry, that domain isn't in my list of allowed rcpthosts (#5.7.1),"); break; default: substdio_puts(&ssout,"46:Dsorry, I can't handle that recipient (#5.1.3),"); break; } /* ssout will be flushed when we read from the network again */ } } netqmail-1.06/home+df.sh0000644000076400007640000000043706541176434014527 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using dot-forward to support sendmail-style ~/.forward files. # Using qmail-local to deliver messages to ~/Mailbox by default. exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|dot-forward .forward ./Mailbox' splogger qmail netqmail-1.06/fifo.c0000644000076400007640000000041506541176434013741 0ustar nelsonnelson#include #include #include "hasmkffo.h" #include "fifo.h" #ifdef HASMKFIFO int fifo_make(fn,mode) char *fn; int mode; { return mkfifo(fn,mode); } #else int fifo_make(fn,mode) char *fn; int mode; { return mknod(fn,S_IFIFO | mode,0); } #endif netqmail-1.06/BLURB20000644000076400007640000000223406541176434013526 0ustar nelsonnelsonMailing list management is one of qmail's strengths. Notable features: * qmail lets each user handle his own mailing lists. The delivery instructions for user-whatever go into ~user/.qmail-whatever. * qmail makes it really easy to set up mailing list owners. If the user touches ~user/.qmail-whatever-owner, all bounces will come back to him. * qmail supports VERPs, which permit completely reliable automated bounce handling for mailing lists of any size. * SPEED---qmail blasts through mailing lists an order of magnitude faster than sendmail. For example, one message was successfully delivered to 150 hosts around the world in just 70 seconds, with qmail's out-of-the-box configuration. * qmail automatically prevents mailing list loops, even across hosts. * qmail allows inconceivably gigantic mailing lists. No random limits. * qmail handles aliasing and forwarding with the same simple mechanism. For example, Postmaster is controlled by ~alias/.qmail-postmaster. This means that cross-host loop detection also applies to aliases. * qmail supports the ezmlm mailing list manager, which easily and automatically handles bounces, subscription requests, and archives. netqmail-1.06/getln2.30000644000076400007640000000166706541176434014143 0ustar nelsonnelson.TH getln2 3 .SH NAME getln2 \- read one line of data .SH SYNTAX .B #include int \fBgetln2\fP(&\fIss\fR,&\fIsa\fR,&\fIcont\fR,&\fIclen\fR,\fIsep\fR); substdio \fIss\fR; .br stralloc \fIsa\fR; .br char *\fIcont\fR; .br unsigned int \fIclen\fR; .br int \fIsep\fR; .SH DESCRIPTION .B getln2 reads a line of characters, terminated by a .I sep character, from .IR ss . The line is returned in two pieces. The first piece is stored in .IR sa . The second piece is .IR cont , a pointer to .I clen characters inside the .I ss buffer. The second piece must be copied somewhere else before .I ss is used again. If .B getln2 sees end-of-input before it sees .IR sep , it sets .I clen to 0 and does not set .IR cont . It puts the partial line into .IR sa . .B getln2 normally returns 0. If it runs out of memory, or encounters an error from .IR ss , it returns -1, setting .B errno appropriately. .SH "SEE ALSO" stralloc(3), substdio(3), getln(3) netqmail-1.06/sendmail.c0000644000076400007640000000740510724070436014611 0ustar nelsonnelson#include "sgetopt.h" #include "substdio.h" #include "subfd.h" #include "alloc.h" #include "auto_qmail.h" #include "exit.h" #include "env.h" #include "str.h" void nomem() { substdio_putsflush(subfderr,"sendmail: fatal: out of memory\n"); _exit(111); } void die_usage() { substdio_putsflush(subfderr,"sendmail: usage: sendmail [ -t ] [ -fsender ] [ -Fname ] [ -bp ] [ -bs ] [ arg ... ]\n"); _exit(100); } char *smtpdarg[] = { "bin/qmail-smtpd", 0 }; void smtpd() { if (!env_get("PROTO")) { if (!env_put("RELAYCLIENT=")) nomem(); if (!env_put("DATABYTES=0")) nomem(); if (!env_put("PROTO=TCP")) nomem(); if (!env_put("TCPLOCALIP=127.0.0.1")) nomem(); if (!env_put("TCPLOCALHOST=localhost")) nomem(); if (!env_put("TCPREMOTEIP=127.0.0.1")) nomem(); if (!env_put("TCPREMOTEHOST=localhost")) nomem(); if (!env_put("TCPREMOTEINFO=sendmail-bs")) nomem(); } execv(*smtpdarg,smtpdarg); substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-smtpd\n"); _exit(111); } char *qreadarg[] = { "bin/qmail-qread", 0 }; void mailq() { execv(*qreadarg,qreadarg); substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-qread\n"); _exit(111); } void do_sender(s) const char *s; { char *x; int n; int a; int i; env_unset("QMAILNAME"); env_unset("MAILNAME"); env_unset("NAME"); env_unset("QMAILHOST"); env_unset("MAILHOST"); n = str_len(s); a = str_rchr(s, '@'); if (a == n) { env_put2("QMAILUSER", s); return; } env_put2("QMAILHOST", s + a + 1); x = (char *) alloc((a + 1) * sizeof(char)); if (!x) nomem(); for (i = 0; i < a; i++) x[i] = s[i]; x[i] = 0; env_put2("QMAILUSER", x); alloc_free(x); } int flagh; char *sender; void main(argc,argv) int argc; char **argv; { int opt; char **qiargv; char **arg; int i; if (chdir(auto_qmail) == -1) { substdio_putsflush(subfderr,"sendmail: fatal: unable to switch to qmail home directory\n"); _exit(111); } flagh = 0; sender = 0; while ((opt = getopt(argc,argv,"vimte:f:p:o:B:F:EJxb:")) != opteof) switch(opt) { case 'B': break; case 't': flagh = 1; break; case 'f': sender = optarg; break; case 'F': if (!env_put2("MAILNAME",optarg)) nomem(); break; case 'p': break; /* could generate a Received line from optarg */ case 'v': break; case 'i': break; /* what an absurd concept */ case 'x': break; /* SVR4 stupidity */ case 'm': break; /* twisted-paper-path blindness, incompetent design */ case 'e': break; /* qmail has only one error mode */ case 'o': switch(optarg[0]) { case 'd': break; /* qmail has only one delivery mode */ case 'e': break; /* see 'e' above */ case 'i': break; /* see 'i' above */ case 'm': break; /* see 'm' above */ } break; case 'E': case 'J': /* Sony NEWS-OS */ while (argv[optind][optpos]) ++optpos; /* skip optional argument */ break; case 'b': switch(optarg[0]) { case 'm': break; case 'p': mailq(); case 's': smtpd(); default: die_usage(); } break; default: die_usage(); } argc -= optind; argv += optind; if (str_equal(optprogname,"mailq")) mailq(); if (str_equal(optprogname,"newaliases")) { substdio_putsflush(subfderr,"sendmail: fatal: please use fastforward/newaliases instead\n"); _exit(100); } qiargv = (char **) alloc((argc + 10) * sizeof(char *)); if (!qiargv) nomem(); arg = qiargv; *arg++ = "bin/qmail-inject"; *arg++ = (flagh ? "-H" : "-a"); if (sender) { *arg++ = "-f"; *arg++ = sender; do_sender(sender); } *arg++ = "--"; for (i = 0;i < argc;++i) *arg++ = argv[i]; *arg = 0; execv(*qiargv,qiargv); substdio_putsflush(subfderr,"sendmail: fatal: unable to run qmail-inject\n"); _exit(111); } netqmail-1.06/str_start.c0000644000076400007640000000052606541176434015046 0ustar nelsonnelson#include "str.h" int str_start(s,t) register char *s; register char *t; { register char x; for (;;) { x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; x = *t++; if (!x) return 1; if (x != *s++) return 0; } } netqmail-1.06/qmail-lspawn.80000644000076400007640000000172506541176434015355 0ustar nelsonnelson.TH qmail-lspawn 8 .SH NAME qmail-lspawn \- schedule local deliveries .SH SYNOPSIS .B qmail-lspawn .I defaultdelivery .SH DESCRIPTION .B qmail-lspawn reads a series of local delivery commands from descriptor 0, invokes .B qmail-local to perform the deliveries, and prints the results to descriptor 1. It passes .I defaultdelivery to .B qmail-local as the default delivery instruction. .B qmail-lspawn invokes .B qmail-local asynchronously, so the results may not be in the same order as the commands. For each recipient address, .B qmail-lspawn finds out which local user controls that address. It first checks the .B qmail-users mechanism; if the address is not listed there, it invokes .BR qmail-getpw . .B qmail-lspawn then runs .B qmail-local under the user's uid and gid. It does not set up any supplementary groups. .B qmail-lspawn treats an empty mailbox name as a trash address. .SH "SEE ALSO" envelopes(5), qmail-users(5), qmail-getpw(8), qmail-send(8), qmail-local(8) netqmail-1.06/sgetopt.30000644000076400007640000000071706541176434014430 0ustar nelsonnelson.TH sgetopt 3 .SH NAME sgetopt \- get option character from command line .SH SYNTAX .B #include .SH DESCRIPTION The .B sgetopt library is just like the .B getopt library, except that it prints errors using .B substdio rather than .BR stdio . See .B getopt(3) for interface details. .SH VERSION sgetopt version 1.9, 931201. .SH AUTHOR Placed into the public domain by Daniel J. Bernstein. .SH "SEE ALSO" getopt(3), subgetopt(3), subfd(3), substdio(3) netqmail-1.06/spawn.c0000644000076400007640000001460010724070436014140 0ustar nelsonnelson#include #include #include "sig.h" #include "wait.h" #include "substdio.h" #include "byte.h" #include "str.h" #include "alloc.h" #include "stralloc.h" #include "select.h" #include "exit.h" #include "coe.h" #include "open.h" #include "error.h" #include "auto_qmail.h" #include "auto_uids.h" #include "auto_spawn.h" extern int truncreport; extern int spawn(); extern void report(); extern void initialize(); struct delivery { int used; int fdin; /* pipe input */ int pid; /* zero if child is dead */ int wstat; /* if !pid: status of child */ int fdout; /* pipe output, -1 if !pid; delays eof until after death */ stralloc output; } ; struct delivery *d; void sigchld() { int wstat; int pid; int i; while ((pid = wait_nohang(&wstat)) > 0) for (i = 0;i < auto_spawn;++i) if (d[i].used) if (d[i].pid == pid) { close(d[i].fdout); d[i].fdout = -1; d[i].wstat = wstat; d[i].pid = 0; } } int flagwriting = 1; int okwrite(fd,buf,n) int fd; char *buf; int n; { int w; if (!flagwriting) return n; w = write(fd,buf,n); if (w != -1) return w; if (errno == error_intr) return -1; flagwriting = 0; close(fd); return n; } int flagreading = 1; char outbuf[1024]; substdio ssout; int stage = 0; /* reading 0:delnum 1:messid 2:sender 3:recip */ int flagabort = 0; /* if 1, everything except delnum is garbage */ int delnum; stralloc messid = {0}; stralloc sender = {0}; stralloc recip = {0}; void err(s) char *s; { char ch; ch = delnum; substdio_put(&ssout,&ch,1); substdio_puts(&ssout,s); substdio_putflush(&ssout,"",1); } void docmd() { int f; int i; int j; int fdmess; int pi[2]; struct stat st; if (flagabort) { err("Zqmail-spawn out of memory. (#4.3.0)\n"); return; } if (delnum < 0) { err("ZInternal error: delnum negative. (#4.3.5)\n"); return; } if (delnum >= auto_spawn) { err("ZInternal error: delnum too big. (#4.3.5)\n"); return; } if (d[delnum].used) { err("ZInternal error: delnum in use. (#4.3.5)\n"); return; } for (i = 0;i < messid.len;++i) if (messid.s[i]) if (!i || (messid.s[i] != '/')) if ((unsigned char) (messid.s[i] - '0') > 9) { err("DInternal error: messid has nonnumerics. (#5.3.5)\n"); return; } if (messid.len > 100) { err("DInternal error: messid too long. (#5.3.5)\n"); return; } if (!messid.s[0]) { err("DInternal error: messid too short. (#5.3.5)\n"); return; } if (!stralloc_copys(&d[delnum].output,"")) { err("Zqmail-spawn out of memory. (#4.3.0)\n"); return; } j = byte_rchr(recip.s,recip.len,'@'); if (j >= recip.len) { err("DSorry, address must include host name. (#5.1.3)\n"); return; } fdmess = open_read(messid.s); if (fdmess == -1) { err("Zqmail-spawn unable to open message. (#4.3.0)\n"); return; } if (fstat(fdmess,&st) == -1) { close(fdmess); err("Zqmail-spawn unable to fstat message. (#4.3.0)\n"); return; } if ((st.st_mode & S_IFMT) != S_IFREG) { close(fdmess); err("ZSorry, message has wrong type. (#4.3.5)\n"); return; } if (st.st_uid != auto_uidq) /* aaack! qmailq has to be trusted! */ /* your security is already toast at this point. damage control... */ { close(fdmess); err("ZSorry, message has wrong owner. (#4.3.5)\n"); return; } if (pipe(pi) == -1) { close(fdmess); err("Zqmail-spawn unable to create pipe. (#4.3.0)\n"); return; } coe(pi[0]); f = spawn(fdmess,pi[1],sender.s,recip.s,j); close(fdmess); if (f == -1) { close(pi[0]); close(pi[1]); err("Zqmail-spawn unable to fork. (#4.3.0)\n"); return; } d[delnum].fdin = pi[0]; d[delnum].fdout = pi[1]; coe(pi[1]); d[delnum].pid = f; d[delnum].used = 1; } char cmdbuf[1024]; void getcmd() { int i; int r; char ch; r = read(0,cmdbuf,sizeof(cmdbuf)); if (r == 0) { flagreading = 0; return; } if (r == -1) { if (errno != error_intr) flagreading = 0; return; } for (i = 0;i < r;++i) { ch = cmdbuf[i]; switch(stage) { case 0: delnum = (unsigned int) (unsigned char) ch; messid.len = 0; stage = 1; break; case 1: if (!stralloc_append(&messid,&ch)) flagabort = 1; if (ch) break; sender.len = 0; stage = 2; break; case 2: if (!stralloc_append(&sender,&ch)) flagabort = 1; if (ch) break; recip.len = 0; stage = 3; break; case 3: if (!stralloc_append(&recip,&ch)) flagabort = 1; if (ch) break; docmd(); flagabort = 0; stage = 0; break; } } } char inbuf[128]; void main(argc,argv) int argc; char **argv; { char ch; int i; int r; fd_set rfds; int nfds; if (chdir(auto_qmail) == -1) _exit(111); if (chdir("queue/mess") == -1) _exit(111); if (!stralloc_copys(&messid,"")) _exit(111); if (!stralloc_copys(&sender,"")) _exit(111); if (!stralloc_copys(&recip,"")) _exit(111); d = (struct delivery *) alloc((auto_spawn + 10) * sizeof(struct delivery)); if (!d) _exit(111); substdio_fdbuf(&ssout,okwrite,1,outbuf,sizeof(outbuf)); sig_pipeignore(); sig_childcatch(sigchld); initialize(argc,argv); ch = auto_spawn; substdio_putflush(&ssout,&ch,1); for (i = 0;i < auto_spawn;++i) { d[i].used = 0; d[i].output.s = 0; } for (;;) { if (!flagreading) { for (i = 0;i < auto_spawn;++i) if (d[i].used) break; if (i >= auto_spawn) _exit(0); } sig_childunblock(); FD_ZERO(&rfds); if (flagreading) FD_SET(0,&rfds); nfds = 1; for (i = 0;i < auto_spawn;++i) if (d[i].used) { FD_SET(d[i].fdin,&rfds); if (d[i].fdin >= nfds) nfds = d[i].fdin + 1; } r = select(nfds,&rfds,(fd_set *) 0,(fd_set *) 0,(struct timeval *) 0); sig_childblock(); if (r != -1) { if (flagreading) if (FD_ISSET(0,&rfds)) getcmd(); for (i = 0;i < auto_spawn;++i) if (d[i].used) if (FD_ISSET(d[i].fdin,&rfds)) { r = read(d[i].fdin,inbuf,128); if (r == -1) continue; /* read error on a readable pipe? be serious */ if (r == 0) { ch = i; substdio_put(&ssout,&ch,1); report(&ssout,d[i].wstat,d[i].output.s,d[i].output.len); substdio_put(&ssout,"",1); substdio_flush(&ssout); close(d[i].fdin); d[i].used = 0; continue; } while (!stralloc_readyplus(&d[i].output,r)) sleep(10); /*XXX*/ byte_copy(d[i].output.s + d[i].output.len,r,inbuf); d[i].output.len += r; if (truncreport > 100) if (d[i].output.len > truncreport) { char *truncmess = "\nError report too long, sorry.\n"; d[i].output.len = truncreport - str_len(truncmess) - 3; stralloc_cats(&d[i].output,truncmess); } } } } } netqmail-1.06/datemail.sh0000644000076400007640000000006406541176434014766 0ustar nelsonnelsonexec QMAIL/bin/predate QMAIL/bin/sendmail ${1+"$@"} netqmail-1.06/case_starts.c0000644000076400007640000000052406541176434015332 0ustar nelsonnelson#include "case.h" int case_starts(s,t) register char *s; register char *t; { register unsigned char x; register unsigned char y; for (;;) { x = *s++ - 'A'; if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; y = *t++ - 'A'; if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; if (!y) return 1; if (x != y) return 0; } } netqmail-1.06/fd.h0000644000076400007640000000011706541176434013413 0ustar nelsonnelson#ifndef FD_H #define FD_H extern int fd_copy(); extern int fd_move(); #endif netqmail-1.06/binm2+df.sh0000644000076400007640000000061306541176434014602 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using dot-forward to support sendmail-style ~/.forward files. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using SVR4 binmail interface: /bin/mail -r exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|dot-forward .forward |preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/qbiff.10000644000076400007640000000074406541176434014030 0ustar nelsonnelson.TH qbiff 1 .SH NAME qbiff \- announce new mail the moment it arrives .SH SYNOPSIS in .BR .qmail : .B |qbiff .SH DESCRIPTION .B qbiff writes a message to your screen whenever a new mail message is delivered, if you ran .B biff y after logging in. .B WARNING: If you create a .B .qmail file to enable .BR qbiff , make sure to also add a line specifying delivery to your normal mailbox. For example: .EX /home/joe/Mailbox .br |qbiff .EE .SH "SEE ALSO" biff(1), dot-qmail(5) netqmail-1.06/auto-gid.c0000644000076400007640000000164406541176434014534 0ustar nelsonnelson#include #include #include "subfd.h" #include "substdio.h" #include "readwrite.h" #include "exit.h" #include "scan.h" #include "fmt.h" char buf1[256]; substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); void outs(s) char *s; { if (substdio_puts(&ss1,s) == -1) _exit(111); } void main(argc,argv) int argc; char **argv; { char *name; char *value; struct group *gr; char strnum[FMT_ULONG]; name = argv[1]; if (!name) _exit(100); value = argv[2]; if (!value) _exit(100); gr = getgrnam(value); if (!gr) { substdio_puts(subfderr,"fatal: unable to find group "); substdio_puts(subfderr,value); substdio_puts(subfderr,"\n"); substdio_flush(subfderr); _exit(111); } strnum[fmt_ulong(strnum,(unsigned long) gr->gr_gid)] = 0; outs("int "); outs(name); outs(" = "); outs(strnum); outs(";\n"); if (substdio_flush(&ss1) == -1) _exit(111); _exit(0); } netqmail-1.06/binm1.sh0000644000076400007640000000052606541176434014217 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r exec env - PATH="QMAIL/bin:$PATH" \ qmail-start \ '|preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/select.h20000644000076400007640000000020506541176434014361 0ustar nelsonnelson#ifndef SELECT_H #define SELECT_H #include #include #include extern int select(); #endif netqmail-1.06/case.h0000644000076400007640000000036406541176434013741 0ustar nelsonnelson#ifndef CASE_H #define CASE_H extern void case_lowers(); extern void case_lowerb(); extern int case_diffs(); extern int case_diffb(); extern int case_starts(); extern int case_startb(); #define case_equals(s,t) (!case_diffs((s),(t))) #endif netqmail-1.06/conf-patrn0000644000076400007640000000027506541176434014650 0ustar nelsonnelson002 These stat bits are not allowed in ~ and ~/.qmail. On most systems, the default umask is 022 or 077, so 022 will work here. Note that ~ftp, ~www, ~uucp, etc. should be owned by root. netqmail-1.06/ndelay_off.c0000644000076400007640000000032306541176434015122 0ustar nelsonnelson#include #include #include "ndelay.h" #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif int ndelay_off(fd) int fd; { return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) & ~O_NONBLOCK); } netqmail-1.06/byte_zero.c0000644000076400007640000000034606541176434015023 0ustar nelsonnelson#include "byte.h" void byte_zero(s,n) char *s; register unsigned int n; { for (;;) { if (!n) break; *s++ = 0; --n; if (!n) break; *s++ = 0; --n; if (!n) break; *s++ = 0; --n; if (!n) break; *s++ = 0; --n; } } netqmail-1.06/received.c0000644000076400007640000000301106541176434014577 0ustar nelsonnelson#include "fmt.h" #include "qmail.h" #include "now.h" #include "datetime.h" #include "date822fmt.h" #include "received.h" static int issafe(ch) char ch; { if (ch == '.') return 1; if (ch == '@') return 1; if (ch == '%') return 1; if (ch == '+') return 1; if (ch == '/') return 1; if (ch == '=') return 1; if (ch == ':') return 1; if (ch == '-') return 1; if ((ch >= 'a') && (ch <= 'z')) return 1; if ((ch >= 'A') && (ch <= 'Z')) return 1; if ((ch >= '0') && (ch <= '9')) return 1; return 0; } void safeput(qqt,s) struct qmail *qqt; char *s; { char ch; while (ch = *s++) { if (!issafe(ch)) ch = '?'; qmail_put(qqt,&ch,1); } } static char buf[DATE822FMT]; /* "Received: from relay1.uu.net (HELO uunet.uu.net) (7@192.48.96.5)\n" */ /* " by silverton.berkeley.edu with SMTP; 26 Sep 1995 04:46:54 -0000\n" */ void received(qqt,protocol,local,remoteip,remotehost,remoteinfo,helo) struct qmail *qqt; char *protocol; char *local; char *remoteip; char *remotehost; char *remoteinfo; char *helo; { struct datetime dt; qmail_puts(qqt,"Received: from "); safeput(qqt,remotehost); if (helo) { qmail_puts(qqt," (HELO "); safeput(qqt,helo); qmail_puts(qqt,")"); } qmail_puts(qqt," ("); if (remoteinfo) { safeput(qqt,remoteinfo); qmail_puts(qqt,"@"); } safeput(qqt,remoteip); qmail_puts(qqt,")\n by "); safeput(qqt,local); qmail_puts(qqt," with "); qmail_puts(qqt,protocol); qmail_puts(qqt,"; "); datetime_tai(&dt,now()); qmail_put(qqt,buf,date822fmt(buf,&dt)); } netqmail-1.06/auto-int8.c0000644000076400007640000000122406541176434014645 0ustar nelsonnelson#include "substdio.h" #include "readwrite.h" #include "exit.h" #include "scan.h" #include "fmt.h" char buf1[256]; substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); void puts(s) char *s; { if (substdio_puts(&ss1,s) == -1) _exit(111); } void main(argc,argv) int argc; char **argv; { char *name; char *value; unsigned long num; char strnum[FMT_ULONG]; name = argv[1]; if (!name) _exit(100); value = argv[2]; if (!value) _exit(100); scan_8long(value,&num); strnum[fmt_ulong(strnum,num)] = 0; puts("int "); puts(name); puts(" = "); puts(strnum); puts(";\n"); if (substdio_flush(&ss1) == -1) _exit(111); _exit(0); } netqmail-1.06/qmail-showctl.80000644000076400007640000000034006541176434015524 0ustar nelsonnelson.TH qmail-showctl 8 .SH NAME qmail-showctl \- analyze the qmail configuration files .SH SYNOPSIS .B qmail-showctl .SH DESCRIPTION .B qmail-showctl explains the current .B qmail configuration. .SH "SEE ALSO" qmail-control(8) netqmail-1.06/timeoutconn.h0000644000076400007640000000011706541176434015366 0ustar nelsonnelson#ifndef TIMEOUTCONN_H #define TIMEOUTCONN_H extern int timeoutconn(); #endif netqmail-1.06/TODO0000644000076400007640000000131106541176434013336 0ustar nelsonnelsonconsider stripping vdoms for VERPs; tnx PJH consider ~ in qmail-local for doing defaultdelivery (not recursively) consider POP bulletins turn qmail-upq into a more serious queue-moving utility consider fast-greeting option in qmail-smtpd build a returnmail package expand strerr coverage redo control interface allow concurrency over 255 allow more channels at compile time test for linux fifo close bug at compile time eliminate qsmhook finish OTBS conversion use mess822 in qmail-inject use mess822 in qreceipt use mess822 in qbiff use mess822 in maildirwatch eliminate token822, headerbody, hfield replace INTERNALS and THOUGHTS with a real paper describing qmail handle IPv6 rewrite everything from scratch netqmail-1.06/fd_move.c0000644000076400007640000000023406541176434014434 0ustar nelsonnelson#include "fd.h" int fd_move(to,from) int to; int from; { if (to == from) return 0; if (fd_copy(to,from) == -1) return -1; close(from); return 0; } netqmail-1.06/tcp-env.c0000644000076400007640000000567206541176434014404 0ustar nelsonnelson#include #include #include #include #include "sig.h" #include "stralloc.h" #include "str.h" #include "env.h" #include "fmt.h" #include "scan.h" #include "subgetopt.h" #include "ip.h" #include "dns.h" #include "byte.h" #include "remoteinfo.h" #include "exit.h" #include "case.h" void die() { _exit(111); } struct sockaddr_in salocal; unsigned long localport; struct ip_address iplocal; stralloc localname = {0}; struct sockaddr_in saremote; unsigned long remoteport; struct ip_address ipremote; stralloc remotename = {0}; char temp[IPFMT + FMT_ULONG]; void main(argc,argv) int argc; char *argv[]; { int dummy; char *proto; int opt; int flagremoteinfo; unsigned long timeout; sig_pipeignore(); flagremoteinfo = 1; timeout = 30; while ((opt = sgopt(argc,argv,"rRt:")) != sgoptdone) switch(opt) { case 'r': flagremoteinfo = 1; break; case 'R': flagremoteinfo = 0; break; case 't': scan_ulong(sgoptarg,&timeout); break; } argv += sgoptind; argc -= sgoptind; if (argc < 1) die(); if (!env_init()) die(); proto = env_get("PROTO"); if (!proto || str_diff(proto,"TCP")) { if (!env_put("PROTO=TCP")) die(); dummy = sizeof(salocal); if (getsockname(0,(struct sockaddr *) &salocal,&dummy) == -1) die(); localport = ntohs(salocal.sin_port); temp[fmt_ulong(temp,localport)] = 0; if (!env_put2("TCPLOCALPORT",temp)) die(); byte_copy(&iplocal,4,&salocal.sin_addr); temp[ip_fmt(temp,&iplocal)] = 0; if (!env_put2("TCPLOCALIP",temp)) die(); switch(dns_ptr(&localname,&iplocal)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&localname,"softdnserror")) die(); case 0: if (!stralloc_0(&localname)) die(); case_lowers(localname.s); if (!env_put2("TCPLOCALHOST",localname.s)) die(); break; default: if (!env_unset("TCPLOCALHOST")) die(); } dummy = sizeof(saremote); if (getpeername(0,(struct sockaddr *) &saremote,&dummy) == -1) die(); remoteport = ntohs(saremote.sin_port); temp[fmt_ulong(temp,remoteport)] = 0; if (!env_put2("TCPREMOTEPORT",temp)) die(); byte_copy(&ipremote,4,&saremote.sin_addr); temp[ip_fmt(temp,&ipremote)] = 0; if (!env_put2("TCPREMOTEIP",temp)) die(); switch(dns_ptr(&remotename,&ipremote)) { case DNS_MEM: die(); case DNS_SOFT: if (!stralloc_copys(&remotename,"softdnserror")) die(); case 0: if (!stralloc_0(&remotename)) die(); case_lowers(remotename.s); if (!env_put2("TCPREMOTEHOST",remotename.s)) die(); break; default: if (!env_unset("TCPREMOTEHOST")) die(); } if (!env_unset("TCPREMOTEINFO")) die(); if (flagremoteinfo) { char *rinfo; rinfo = remoteinfo_get(&ipremote,remoteport,&iplocal,localport,(int) timeout); if (rinfo) if (!env_put2("TCPREMOTEINFO",rinfo)) die(); } } sig_pipedefault(); execvp(*argv,argv); die(); } netqmail-1.06/qmail-log.50000644000076400007640000001353310724070436014620 0ustar nelsonnelson.TH qmail-log 5 .SH NAME qmail-log \- the qmail activity record .SH DESCRIPTION .B qmail-send prints a series of lines describing its activities. Each possible line is described below. .SH "STATUS" .TP .B status: local \fIl\fB/\fIL\fB remote \fIr\fB/\fIR\fB ... .B qmail-send is waiting for .I l local deliveries and .I r remote deliveries. The concurrency limits are .I L and .IR R . .TP .B status: exiting .B qmail-send is done. .SH "FATAL PROBLEMS" .TP .B alert: cannot start: ... .B qmail-send is unable to prepare itself for delivering messages; it is giving up. This normally indicates a serious configuration error, but it can be caused by a temporary lack of resources. .TP .B alert: oh no! lost ... One of the other daemons has died. .B qmail-send will exit as soon as possible. .SH "SERIOUS PROBLEMS" .TP .B alert: unable to append to bounce message... .B qmail-send is unable to record a permanent failure, usually because the disk is full. This is a very serious problem; .B qmail-send cannot proceed without recording the results. It will try again in ten seconds. .TP .B alert: out of memory... .B qmail-send tried to allocate more memory and failed. It will try again in ten seconds. .TP .B alert: unable to opendir... .B qmail-send is having trouble reading a file list from disk, usually because the system's file descriptor table is full, but possibly because permissions are set incorrectly. It will try again in ten seconds. .TP .B alert: unable to switch back... .B qmail-send was sent SIGHUP, and it is unable to reenter the queue directory. This is a very serious problem; .B qmail-send cannot proceed outside the queue directory. It will try again in ten seconds. .TP .B alert: unable to reread... .B qmail-send was sent SIGHUP, but it is unable to read the new controls. It will continue operating with the original controls. .SH "MESSAGES" .TP .B new msg \fIm\fB .B qmail-send is going to preprocess a queued message. The message number, .IR m , is its disk inode number. After a message is removed from the queue, its number can be reused immediately. .TP .B info msg \fIm\fB: bytes \fIb\fB from <\fIs\fB> qp \fIq\fB uid \fIu\fB Message .I m contains .I b bytes; its envelope sender is .IR s ; it was queued by a user with user ID .IR u . .I q is a long-term queue identifier, the process ID of the .B qmail-queue that queued the message. .TP .B bounce msg \fIm\fB qp \fIq\fB Message .I m had some delivery failures. The long-term queue identifier of the bounce (or double-bounce) message is .IR q . .TP .B triple bounce: discarding ... Message .I m had some delivery failures, but it is already a double-bounce message, so it must be thrown away. Triple-bounce messages do not exist. .TP .B end msg \fIm\fB .B qmail-send is about to remove message .I m from the queue. .SH "DELIVERIES" .TP .B starting delivery \fId\fB: msg \fIm\fB to ... .B qmail-send is telling .B qmail-lspawn or .B qmail-rspawn to deliver message .I m to one recipient. The delivery number, .IR d , starts at 1 and increases by 1 for each new delivery. .TP .B delivery \fId\fB: success: ... Delivery .I d was successful. .TP .B delivery \fId\fB: failure: ... Delivery .I d failed permanently. The message will bounce. .TP .B delivery \fId\fB: deferral: ... Delivery .I d failed temporarily. This recipient will be retried later. .TP .B delivery \fId\fB: report mangled, will defer There is a serious bug in .B qmail-lspawn or .BR qmail-rspawn . This recipient will be retried later. .SH "WARNINGS" .TP .B internal error: delivery report out of range .B qmail-lspawn or .B qmail-rspawn has supplied a report on a nonexistent delivery. This is a serious bug. .TP .B qmail-clean unable to clean up ... For some reason .B qmail-clean is unable to remove the indicated file. It will try again later. .TP .B trouble fsyncing ... .B qmail-send was unable to write to disk the results of preprocessing a queued message. It will try again later. .TP .B trouble in select There is an operating system bug. .TP .B trouble injecting bounce message... .B qmail-send was unable to queue a bounce message, usually because the disk is full. It will try again later. .TP .B trouble marking ... .B qmail-send was unable to record the result of a successful or permanently unsuccessful delivery. This means that the delivery will be tried again later. .TP .B trouble opening ... .B qmail-send was unable to open the list of local or remote recipients for a message. It will try again later. .TP .B trouble reading ... Either .B qmail-send is unable to read a recipient list, or it is unable to read the envelope of a queued message, or it is out of memory. Whatever it was doing, it will try again later. .TP .B trouble writing to ... .B qmail-send was unable to preprocess a queued message, usually because the disk is full. It will try again later. .TP .B unable to create ... .B qmail-send was unable to preprocess a queued message, usually because the disk is out of inodes. It will try again later. .TP .B unable to open ... .B qmail-send is unable to read the envelope of a queued message for preprocessing. It will try again later. .TP .B unable to start qmail-queue... .B qmail-send is unable to queue a bounce message, usually because the machine is almost out of memory. It will try again later. This can also be caused by incorrect settings of .B $QMAILQUEUE or errors in a program or script which .B $QMAILQUEUE points to. .TP .B unable to stat ... .B qmail-send is unable to obtain information about a file that should exist. It will try again later. .TP .B unable to unlink ... .B qmail-send is unable to remove a file. It will try again later. .TP .B unable to utime ... .B qmail-send is about to exit, and it is unable to record on disk the next scheduled delivery time for a message. The message will be retried as soon as .B qmail-send is restarted. .TP .B unknown record type in ... There is a serious bug in either .B qmail-queue or .BR qmail-send . .SH "SEE ALSO" qmail-send(8) netqmail-1.06/stralloc_eady.c0000644000076400007640000000031306541176434015640 0ustar nelsonnelson#include "alloc.h" #include "stralloc.h" #include "gen_allocdefs.h" GEN_ALLOC_ready(stralloc,char,s,len,a,i,n,x,30,stralloc_ready) GEN_ALLOC_readyplus(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus) netqmail-1.06/tryflock.c0000644000076400007640000000017106541176434014652 0ustar nelsonnelson#include #include #include void main() { flock(0,LOCK_EX | LOCK_UN | LOCK_NB); } netqmail-1.06/qmail-tcpok.80000644000076400007640000000062306541176434015165 0ustar nelsonnelson.TH qmail-tcpok 8 .SH NAME qmail-tcpok \- clear TCP timeout table .SH SYNOPSIS .B qmail-tcpok .SH DESCRIPTION .B qmail-tcpok erases .BR qmail-remote 's current list of timeouts, so that .B qmail-remote does not make any assumptions about failing addresses. .B qmail-tcpok must be run either as .B root or with user id .B qmailr and group id .BR qmail . .SH "SEE ALSO" qmail-remote(8), qmail-tcpto(8) netqmail-1.06/qmail-qmqpc.80000644000076400007640000000115506541176434015167 0ustar nelsonnelson.TH qmail-qmqpc 8 .SH NAME qmail-qmqpc \- queue a mail message via QMQP .SH SYNOPSIS .B qmail-qmqpc .SH DESCRIPTION .B qmail-qmqpc offers the same interface as .BR qmail-queue , but it gives the message to a QMQP server instead of storing it locally. In a .B mini-qmail installation, .B qmail-queue is replaced with a symbolic link to .BR qmail-qmqpc . .SH "CONTROL FILES" .TP 5 .I qmqpservers IP addresses of QMQP servers, one address per line. .B qmail-qmqpc will try each address in turn until it establishes a QMQP connection or runs out of addresses. .SH "SEE ALSO" qmail-control(5), qmail-queue(8), qmail-qmqpd(8) netqmail-1.06/substdio_copy.c0000644000076400007640000000053306541176434015705 0ustar nelsonnelson#include "substdio.h" int substdio_copy(ssout,ssin) register substdio *ssout; register substdio *ssin; { register int n; register char *x; for (;;) { n = substdio_feed(ssin); if (n < 0) return -2; if (!n) return 0; x = substdio_PEEK(ssin); if (substdio_put(ssout,x,n) == -1) return -3; substdio_SEEK(ssin,n); } } netqmail-1.06/preline.10000644000076400007640000000161306541176434014373 0ustar nelsonnelson.TH preline 1 .SH NAME preline \- prepend lines to message .SH SYNOPSIS in .BR .qmail\fIext : .B | preline \fIcommand .SH DESCRIPTION .B preline feeds each incoming mail message through .IR command . At the top of each message it inserts a UUCP-style .B From_ line, a .B Return-Path line, and a .B Delivered-To line. .B preline is useful for .B procmail and ELM's .BR filter , which do not understand the .B qmail-command environment variables. .SH OPTIONS .TP .B \-d Do not include the .B Delivered-To line. You should use this option when the recipient of the incoming mail message is actually under remote control, but was sent here through .B control/virtualdomains for manual routing. .TP .B \-f Do not include the .B From_ line. You should use this option except for .IR command s that create .I mbox files. .TP .B \-r Do not include the .B Return-Path line. .SH "SEE ALSO" mbox(5), qmail-command(8) netqmail-1.06/lock.h0000644000076400007640000000015306541176434013752 0ustar nelsonnelson#ifndef LOCK_H #define LOCK_H extern int lock_ex(); extern int lock_un(); extern int lock_exnb(); #endif netqmail-1.06/case.30000644000076400007640000000337506541176434013661 0ustar nelsonnelson.TH case 3 .SH NAME case \- convert ASCII uppercase bytes to lowercase .SH SYNTAX .B #include void \fBcase_lowers\fP(\fIs\fR); .br void \fBcase_lowerb\fP(\fIs\fR,\fIlen\fR); int \fBcase_diffs\fP(\fIs\fR,\fIt\fR); .br int \fBcase_equals\fP(\fIs\fR,\fIt\fR); .br int \fBcase_starts\fP(\fIs\fR,\fIt\fR); int \fBcase_diffb\fP(\fIs\fR,\fIlen\fR,\fIt\fR); .br int \fBcase_startb\fP(\fIs\fR,\fIlen\fR,\fIt\fR); char *\fIs\fR; .br char *\fIt\fR; .br unsigned int \fIlen\fR; .SH DESCRIPTION .B case_lowers converts each uppercase byte in the string .I s to lowercase. .I s must be 0-terminated. .B case_lowerb converts each uppercase byte in the buffer .IR s , of length .IR len , to lowercase. .B case_diffs lexicographically compares lowercase versions of the strings .I s and .IR t . It returns something positive, negative, or zero when the first is larger than, smaller than, or equal to the second. .I s and .I t must be 0-terminated. .B case_equals means .BR !case_diffs . .B case_starts returns 1 if a lowercase version of .I s starts with a lowercase version of .IR t . .I s and .I t must be 0-terminated. .B case_diffb lexicographically compares lowercase versions of the buffers .I s and .IR t , each of length .IR len . It returns something positive, negative, or zero when the first is larger than, smaller than, or equal to the second. .B case_startb returns 1 if a lowercase version of the buffer .IR s , of length .IR len , starts with a lowercase version of the string .IR t . .I t must be 0-terminated. The .B case routines are ASCII-specific. They are suitable for programs that handle case-independent networking protocols. All comparisons are performed on unsigned bytes. .SH "SEE ALSO" byte_diff(3), byte_equal(3), str_diff(3), str_equal(3), str_start(3) netqmail-1.06/auto-int.c0000644000076400007640000000122406541176434014555 0ustar nelsonnelson#include "substdio.h" #include "readwrite.h" #include "exit.h" #include "scan.h" #include "fmt.h" char buf1[256]; substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); void puts(s) char *s; { if (substdio_puts(&ss1,s) == -1) _exit(111); } void main(argc,argv) int argc; char **argv; { char *name; char *value; unsigned long num; char strnum[FMT_ULONG]; name = argv[1]; if (!name) _exit(100); value = argv[2]; if (!value) _exit(100); scan_ulong(value,&num); strnum[fmt_ulong(strnum,num)] = 0; puts("int "); puts(name); puts(" = "); puts(strnum); puts(";\n"); if (substdio_flush(&ss1) == -1) _exit(111); _exit(0); } netqmail-1.06/stralloc.h0000644000076400007640000000076006541176434014651 0ustar nelsonnelson#ifndef STRALLOC_H #define STRALLOC_H #include "gen_alloc.h" GEN_ALLOC_typedef(stralloc,char,s,len,a) extern int stralloc_ready(); extern int stralloc_readyplus(); extern int stralloc_copy(); extern int stralloc_cat(); extern int stralloc_copys(); extern int stralloc_cats(); extern int stralloc_copyb(); extern int stralloc_catb(); extern int stralloc_append(); /* beware: this takes a pointer to 1 char */ extern int stralloc_starts(); #define stralloc_0(sa) stralloc_append(sa,"") #endif netqmail-1.06/stralloc_catb.c0000644000076400007640000000050006541176434015625 0ustar nelsonnelson#include "stralloc.h" #include "byte.h" int stralloc_catb(sa,s,n) stralloc *sa; char *s; unsigned int n; { if (!sa->s) return stralloc_copyb(sa,s,n); if (!stralloc_readyplus(sa,n + 1)) return 0; byte_copy(sa->s + sa->len,n,s); sa->len += n; sa->s[sa->len] = 'Z'; /* ``offensive programming'' */ return 1; } netqmail-1.06/predate.c0000644000076400007640000000535406541176434014451 0ustar nelsonnelson#include #include #include "datetime.h" #include "fork.h" #include "wait.h" #include "fd.h" #include "fmt.h" #include "strerr.h" #include "substdio.h" #include "subfd.h" #include "readwrite.h" #include "exit.h" #define FATAL "predate: fatal: " static char *montab[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; char num[FMT_ULONG]; char outbuf[1024]; void main(argc,argv) int argc; char **argv; { time_t now; struct tm *tm; struct datetime dt; datetime_sec utc; datetime_sec local; int minutes; int pi[2]; substdio ss; int wstat; int pid; sig_pipeignore(); if (!argv[1]) strerr_die1x(100,"predate: usage: predate child"); if (pipe(pi) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); switch(pid = fork()) { case -1: strerr_die2sys(111,FATAL,"unable to fork: "); case 0: close(pi[1]); if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,FATAL,"unable to set up fds: "); sig_pipedefault(); execvp(argv[1],argv + 1); strerr_die4sys(111,FATAL,"unable to run ",argv[1],": "); } close(pi[0]); substdio_fdbuf(&ss,write,pi[1],outbuf,sizeof(outbuf)); time(&now); tm = gmtime(&now); dt.year = tm->tm_year; dt.mon = tm->tm_mon; dt.mday = tm->tm_mday; dt.hour = tm->tm_hour; dt.min = tm->tm_min; dt.sec = tm->tm_sec; utc = datetime_untai(&dt); /* utc == now, if gmtime ignores leap seconds */ tm = localtime(&now); dt.year = tm->tm_year; dt.mon = tm->tm_mon; dt.mday = tm->tm_mday; dt.hour = tm->tm_hour; dt.min = tm->tm_min; dt.sec = tm->tm_sec; local = datetime_untai(&dt); substdio_puts(&ss,"Date: "); substdio_put(&ss,num,fmt_uint(num,dt.mday)); substdio_puts(&ss," "); substdio_puts(&ss,montab[dt.mon]); substdio_puts(&ss," "); substdio_put(&ss,num,fmt_uint(num,dt.year + 1900)); substdio_puts(&ss," "); substdio_put(&ss,num,fmt_uint0(num,dt.hour,2)); substdio_puts(&ss,":"); substdio_put(&ss,num,fmt_uint0(num,dt.min,2)); substdio_puts(&ss,":"); substdio_put(&ss,num,fmt_uint0(num,dt.sec,2)); if (local < utc) { minutes = (utc - local + 30) / 60; substdio_puts(&ss," -"); substdio_put(&ss,num,fmt_uint0(num,minutes / 60,2)); substdio_put(&ss,num,fmt_uint0(num,minutes % 60,2)); } else { minutes = (local - utc + 30) / 60; substdio_puts(&ss," +"); substdio_put(&ss,num,fmt_uint0(num,minutes / 60,2)); substdio_put(&ss,num,fmt_uint0(num,minutes % 60,2)); } substdio_puts(&ss,"\n"); substdio_copy(&ss,subfdin); substdio_flush(&ss); close(pi[1]); if (wait_pid(&wstat,pid) == -1) strerr_die2sys(111,FATAL,"wait failed: "); if (wait_crashed(wstat)) strerr_die2x(111,FATAL,"child crashed"); _exit(wait_exitcode(wstat)); } netqmail-1.06/stralloc_cats.c0000644000076400007640000000022606541176434015653 0ustar nelsonnelson#include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_cats(sa,s) stralloc *sa; char *s; { return stralloc_catb(sa,s,str_len(s)); } netqmail-1.06/sgetopt.h0000644000076400007640000000064106541176434014511 0ustar nelsonnelson#ifndef SGETOPT_H #define SGETOPT_H #ifndef SGETOPTNOSHORT #define getopt sgetoptmine #define optarg subgetoptarg #define optind subgetoptind #define optpos subgetoptpos #define opterr sgetopterr #define optproblem subgetoptproblem #define optprogname sgetoptprogname #define opteof subgetoptdone #endif #include "subgetopt.h" extern int sgetoptmine(); extern int sgetopterr; extern char *sgetoptprogname; #endif netqmail-1.06/qmail-qmqpc.c0000644000076400007640000000755706541176434015256 0ustar nelsonnelson#include #include #include #include #include "substdio.h" #include "getln.h" #include "readwrite.h" #include "exit.h" #include "stralloc.h" #include "slurpclose.h" #include "error.h" #include "sig.h" #include "ip.h" #include "timeoutconn.h" #include "timeoutread.h" #include "timeoutwrite.h" #include "auto_qmail.h" #include "control.h" #include "fmt.h" #define PORT_QMQP 628 void die_success() { _exit(0); } void die_perm() { _exit(31); } void nomem() { _exit(51); } void die_read() { if (errno == error_nomem) nomem(); _exit(54); } void die_control() { _exit(55); } void die_socket() { _exit(56); } void die_home() { _exit(61); } void die_temp() { _exit(71); } void die_conn() { _exit(74); } void die_format() { _exit(91); } int lasterror = 55; int qmqpfd; int saferead(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutread(60,qmqpfd,buf,len); if (r <= 0) die_conn(); return r; } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(60,qmqpfd,buf,len); if (r <= 0) die_conn(); return r; } char buf[1024]; substdio to = SUBSTDIO_FDBUF(safewrite,-1,buf,sizeof buf); substdio from = SUBSTDIO_FDBUF(saferead,-1,buf,sizeof buf); substdio envelope = SUBSTDIO_FDBUF(read,1,buf,sizeof buf); /* WARNING: can use only one of these at a time! */ stralloc beforemessage = {0}; stralloc message = {0}; stralloc aftermessage = {0}; char strnum[FMT_ULONG]; stralloc line = {0}; void getmess() { int match; if (slurpclose(0,&message,1024) == -1) die_read(); strnum[fmt_ulong(strnum,(unsigned long) message.len)] = 0; if (!stralloc_copys(&beforemessage,strnum)) nomem(); if (!stralloc_cats(&beforemessage,":")) nomem(); if (!stralloc_copys(&aftermessage,",")) nomem(); if (getln(&envelope,&line,&match,'\0') == -1) die_read(); if (!match) die_format(); if (line.len < 2) die_format(); if (line.s[0] != 'F') die_format(); strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; if (!stralloc_cats(&aftermessage,strnum)) nomem(); if (!stralloc_cats(&aftermessage,":")) nomem(); if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); if (!stralloc_cats(&aftermessage,",")) nomem(); for (;;) { if (getln(&envelope,&line,&match,'\0') == -1) die_read(); if (!match) die_format(); if (line.len < 2) break; if (line.s[0] != 'T') die_format(); strnum[fmt_ulong(strnum,(unsigned long) line.len - 2)] = 0; if (!stralloc_cats(&aftermessage,strnum)) nomem(); if (!stralloc_cats(&aftermessage,":")) nomem(); if (!stralloc_catb(&aftermessage,line.s + 1,line.len - 2)) nomem(); if (!stralloc_cats(&aftermessage,",")) nomem(); } } void doit(server) char *server; { struct ip_address ip; char ch; if (!ip_scan(server,&ip)) return; qmqpfd = socket(AF_INET,SOCK_STREAM,0); if (qmqpfd == -1) die_socket(); if (timeoutconn(qmqpfd,&ip,PORT_QMQP,10) != 0) { lasterror = 73; if (errno == error_timeout) lasterror = 72; close(qmqpfd); return; } strnum[fmt_ulong(strnum,(unsigned long) (beforemessage.len + message.len + aftermessage.len))] = 0; substdio_puts(&to,strnum); substdio_puts(&to,":"); substdio_put(&to,beforemessage.s,beforemessage.len); substdio_put(&to,message.s,message.len); substdio_put(&to,aftermessage.s,aftermessage.len); substdio_puts(&to,","); substdio_flush(&to); for (;;) { substdio_get(&from,&ch,1); if (ch == 'K') die_success(); if (ch == 'Z') die_temp(); if (ch == 'D') die_perm(); } } stralloc servers = {0}; main() { int i; int j; sig_pipeignore(); if (chdir(auto_qmail) == -1) die_home(); if (control_init() == -1) die_control(); if (control_readfile(&servers,"control/qmqpservers",0) != 1) die_control(); getmess(); i = 0; for (j = 0;j < servers.len;++j) if (!servers.s[j]) { doit(servers.s + i); i = j + 1; } _exit(lasterror); } netqmail-1.06/PIC.relaybad0000644000076400007640000000045406541176434014775 0ustar nelsonnelsonqmail-smtpd Receive message by SMTP from another host: MAIL FROM: RCPT TO: Is $RELAYCLIENT set? No. Is irs.gov in rcpthosts? No. Reject RCPT. netqmail-1.06/constmap.c0000644000076400007640000000451506541176434014647 0ustar nelsonnelson#include "constmap.h" #include "alloc.h" #include "case.h" static constmap_hash hash(s,len) char *s; int len; { unsigned char ch; constmap_hash h; h = 5381; while (len > 0) { ch = *s++ - 'A'; if (ch <= 'Z' - 'A') ch += 'a' - 'A'; h = ((h << 5) + h) ^ ch; --len; } return h; } char *constmap(cm,s,len) struct constmap *cm; char *s; int len; { constmap_hash h; int pos; h = hash(s,len); pos = cm->first[h & cm->mask]; while (pos != -1) { if (h == cm->hash[pos]) if (len == cm->inputlen[pos]) if (!case_diffb(cm->input[pos],len,s)) return cm->input[pos] + cm->inputlen[pos] + 1; pos = cm->next[pos]; } return 0; } int constmap_init(cm,s,len,flagcolon) struct constmap *cm; char *s; int len; int flagcolon; { int i; int j; int k; int pos; constmap_hash h; cm->num = 0; for (j = 0;j < len;++j) if (!s[j]) ++cm->num; h = 64; while (h && (h < cm->num)) h += h; cm->mask = h - 1; cm->first = (int *) alloc(sizeof(int) * h); if (cm->first) { cm->input = (char **) alloc(sizeof(char *) * cm->num); if (cm->input) { cm->inputlen = (int *) alloc(sizeof(int) * cm->num); if (cm->inputlen) { cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num); if (cm->hash) { cm->next = (int *) alloc(sizeof(int) * cm->num); if (cm->next) { for (h = 0;h <= cm->mask;++h) cm->first[h] = -1; pos = 0; i = 0; for (j = 0;j < len;++j) if (!s[j]) { k = j - i; if (flagcolon) { for (k = i;k < j;++k) if (s[k] == ':') break; if (k >= j) { i = j + 1; continue; } k -= i; } cm->input[pos] = s + i; cm->inputlen[pos] = k; h = hash(s + i,k); cm->hash[pos] = h; h &= cm->mask; cm->next[pos] = cm->first[h]; cm->first[h] = pos; ++pos; i = j + 1; } return 1; } alloc_free(cm->hash); } alloc_free(cm->inputlen); } alloc_free(cm->input); } alloc_free(cm->first); } return 0; } void constmap_free(cm) struct constmap *cm; { alloc_free(cm->next); alloc_free(cm->hash); alloc_free(cm->inputlen); alloc_free(cm->input); alloc_free(cm->first); } netqmail-1.06/coe.c0000644000076400007640000000013306541176434013561 0ustar nelsonnelson#include #include "coe.h" int coe(fd) int fd; { return fcntl(fd,F_SETFD,1); } netqmail-1.06/case_lowerb.c0000644000076400007640000000030106541176434015275 0ustar nelsonnelson#include "case.h" void case_lowerb(s,len) char *s; unsigned int len; { unsigned char x; while (len > 0) { --len; x = *s - 'A'; if (x <= 'Z' - 'A') *s = x + 'a'; ++s; } } netqmail-1.06/qmail-upq.sh0000644000076400007640000000036206541176434015115 0ustar nelsonnelsoncd QMAIL cd queue for dir in mess info local remote do ( cd $dir; find . -type f -print ) | ( cd $dir while read path do id=`basename "$path"` sub=`expr "$id" % SPLIT` mv "$path" "$sub"/"$id" done ) done netqmail-1.06/seek_trunc.c0000644000076400007640000000017506541176434015163 0ustar nelsonnelson#include #include "seek.h" int seek_trunc(fd,pos) int fd; seek_pos pos; { return ftruncate(fd,(off_t) pos); } netqmail-1.06/seek_set.c0000644000076400007640000000025506541176434014622 0ustar nelsonnelson#include #include "seek.h" #define SET 0 /* sigh */ int seek_set(fd,pos) int fd; seek_pos pos; { if (lseek(fd,(off_t) pos,SET) == -1) return -1; return 0; } netqmail-1.06/old-patches/0000755000076400007640000000000010003260406015032 5ustar nelsonnelsonnetqmail-1.06/old-patches/netqmail-1.04.patch0000644000076400007640000003105207747646540020302 0ustar nelsonnelsondiff -urN qmail-1.03/CHANGES netqmail-1.04/CHANGES --- qmail-1.03/CHANGES Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/CHANGES Tue Oct 28 08:26:09 2003 @@ -1,3 +1,17 @@ +20031027 version: netqmail 1.04. +20031027 doc: INSTALL points to http://lifewithqmail.org/lwq.html +20031027 doc: qmail.7 identifies installation as netqmail and points to + http://qmail.org/ +20031027 doc: qmail-queue.8 adds explanation of $QMAILQUEUE +20031027 doc: qmail-log.5 adds reference to errors from $QMAILQUEUE script +20031027 doc: FAQ also points to http://cr.yp.to/qmail/faq.html and + http://qmail.org/ +20031027 code: qmail-smtpd identifies itself as netqmail +20031027 code: if $QMAILQUEUE is set, it's invoked instead of qmail-queue +20031024 code: changed errno from int to #include. +20031024 code: fixed .qmail parsing bug. +20031024 code: recognize 0.0.0.0 as a local address. +20031024 code: sendmail's -f flag now overrides environment variables. 19980615 version: qmail 1.03. 19980614 doc: eliminated BIN.setup in favor of a web page. 19980614 code: added other auto* to qmail-showctl output. diff -urN qmail-1.03/FAQ netqmail-1.04/FAQ --- qmail-1.03/FAQ Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/FAQ Mon Oct 27 17:33:12 2003 @@ -1,3 +1,6 @@ +See http://cr.yp.to/qmail/faq.html for newer FAQs not included in this +document, and http://qmail.org/ for qmail community contributions. + 1. Controlling the appearance of outgoing messages 1.1. How do I set up host masquerading? 1.2. How do I set up user masquerading? diff -urN qmail-1.03/FILES netqmail-1.04/FILES --- qmail-1.03/FILES Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/FILES Mon Oct 27 17:33:12 2003 @@ -10,6 +10,7 @@ INSTALL.ids INSTALL.maildir INSTALL.mbox +INSTALL-1.03 INSTALL.vsm REMOVE.sendmail REMOVE.binmail diff -urN qmail-1.03/INSTALL netqmail-1.04/INSTALL --- qmail-1.03/INSTALL Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/INSTALL Mon Oct 27 17:33:12 2003 @@ -1,84 +1 @@ -SAVE COPIES OF YOUR OUTGOING MAIL! Like any other piece of software (and -information generally), the qmail system comes with NO WARRANTY. It's -much more secure and reliable than sendmail, but that's not saying much. - - -Things you have to decide before starting: - -* The qmail home directory, normally /var/qmail. To change this -directory, edit conf-qmail now. - -* The names of the qmail users and the qmail groups. To change these -names, edit conf-users and conf-groups now. - - -To create /var/qmail and configure qmail (won't interfere with sendmail): - - 1. Create the qmail home directory: - # mkdir /var/qmail - - 2. Read INSTALL.ids. You must set up the qmail group and the qmail - users before compiling the programs. - - 3. Compile the programs and create the qmail directory tree: - # make setup check - - 4. Read INSTALL.ctl and FAQ. Minimal survival command: - # ./config - - 5. Read INSTALL.alias. Minimal survival command: - # (cd ~alias; touch .qmail-postmaster .qmail-mailer-daemon .qmail-root) - # chmod 644 ~alias/.qmail* - - 6. Read INSTALL.mbox and INSTALL.vsm. - - 7. Read INSTALL.maildir. - - 8. Copy /var/qmail/boot/home (or proc) to /var/qmail/rc. - - -To test qmail deliveries (won't interfere with sendmail): - - 9. Enable deliveries of messages injected into qmail: - # csh -cf '/var/qmail/rc &' - -10. Read TEST.deliver. - - -To upgrade from sendmail to qmail: - -11. Read SENDMAIL. This is what your users will want to know about the - switch from sendmail to qmail. - -12. Read REMOVE.sendmail. You must remove sendmail before installing - qmail. - -13. Read REMOVE.binmail. - -14. Add - csh -cf '/var/qmail/rc &' - to your boot scripts, so that the qmail daemons are restarted - whenever your system reboots. Make sure you include the &. - -15. Make qmail's ``sendmail'' wrapper available to MUAs: - # ln -s /var/qmail/bin/sendmail /usr/lib/sendmail - # ln -s /var/qmail/bin/sendmail /usr/sbin/sendmail - /usr/sbin might not exist on your system. - -16. Set up qmail-smtpd in /etc/inetd.conf (all on one line): - smtp stream tcp nowait qmaild /var/qmail/bin/tcp-env - tcp-env /var/qmail/bin/qmail-smtpd - -17. Reboot. (Or kill -HUP your inetd and make sure the qmail daemons - are running.) - -18. Read TEST.receive. - - - -That's it! To report success: - % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to -Replace First M. Last with your name. - -If you have questions about qmail, join the qmail mailing list; see -http://pobox.com/~djb/qmail.html. +See http://lifewithqmail.org/lwq.html diff -urN qmail-1.03/Makefile netqmail-1.04/Makefile --- qmail-1.03/Makefile Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/Makefile Mon Oct 27 17:33:13 2003 @@ -1483,12 +1483,12 @@ trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \ datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \ lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ -auto_split.o +auto_split.o env.a ./load qmail-send qsutil.o control.o constmap.o newfield.o \ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \ - substdio.a error.a str.a fs.a auto_qmail.o auto_split.o + substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a qmail-send.0: \ qmail-send.8 diff -urN qmail-1.03/README netqmail-1.04/README --- qmail-1.03/README Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/README Mon Oct 27 17:33:13 2003 @@ -3,6 +3,15 @@ Copyright 1998 D. J. Bernstein, qmail@pobox.com +netqmail 1.04 +20031024 +No copyright claimed for changes from qmail 1.03 to netqmail 1.04 +Russell Nelson, nelson@qmail.org +NOTE: netqmail 1.04 is a community-assembled distribution of qmail from +the official qmail-1.03.tar.gz and patches approved by the community. +D. J. Bernstein did not participate in, nor has he been asked to +approve of this distribution. + qmail is a secure, reliable, efficient, simple message transfer agent. It is meant as a replacement for the entire sendmail-binmail system on typical Internet-connected UNIX hosts. See BLURB, BLURB2, BLURB3, and diff -urN qmail-1.03/UPGRADE netqmail-1.04/UPGRADE --- qmail-1.03/UPGRADE Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/UPGRADE Mon Oct 27 17:33:13 2003 @@ -3,7 +3,7 @@ much more secure and reliable than sendmail, but that's not saying much. -Here's how to upgrade to qmail 1.03. This procedure will overwrite the +Here's how to upgrade to netqmail 1.04. This procedure will overwrite the old qmail binaries. Furthermore, it may begin delivering messages from the queue before you have had a chance to test it. @@ -17,7 +17,7 @@ Before starting, compare conf* to your old conf*, and make any necessary -changes. You can copy conf* from 1.02. +changes. You can copy conf* from 1.02 or 1.03. How to install: diff -urN qmail-1.03/VERSION netqmail-1.04/VERSION --- qmail-1.03/VERSION Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/VERSION Mon Oct 27 17:33:13 2003 @@ -1 +1 @@ -qmail 1.03 +netqmail 1.04 diff -urN qmail-1.03/cdb_seek.c netqmail-1.04/cdb_seek.c --- qmail-1.03/cdb_seek.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/cdb_seek.c Mon Oct 27 17:33:13 2003 @@ -1,6 +1,5 @@ #include #include -extern int errno; #include "cdb.h" #ifndef SEEK_SET diff -urN qmail-1.03/dns.c netqmail-1.04/dns.c --- qmail-1.03/dns.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/dns.c Mon Oct 27 17:33:13 2003 @@ -7,8 +7,6 @@ #include extern int res_query(); extern int res_search(); -extern int errno; -extern int h_errno; #include "ip.h" #include "ipalloc.h" #include "fmt.h" diff -urN qmail-1.03/error.3 netqmail-1.04/error.3 --- qmail-1.03/error.3 Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/error.3 Mon Oct 27 17:33:13 2003 @@ -3,8 +3,7 @@ error \- syscall error codes .SH SYNTAX .B #include - -extern int \fBerrno\fP; +.B #include extern int \fBerror_intr\fP; .br diff -urN qmail-1.03/error.h netqmail-1.04/error.h --- qmail-1.03/error.h Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/error.h Mon Oct 27 17:33:13 2003 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; diff -urN qmail-1.03/ipme.c netqmail-1.04/ipme.c --- qmail-1.03/ipme.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/ipme.c Mon Oct 27 17:33:13 2003 @@ -46,6 +46,11 @@ ipme.len = 0; ix.pref = 0; + /* 0.0.0.0 is a special address which always refers to + * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a. + */ + byte_copy(&ix.ip,4,"\0\0\0\0"); + if (!ipalloc_append(&ipme,&ix)) { return 0; } if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; len = 256; diff -urN qmail-1.03/qmail-local.c netqmail-1.04/qmail-local.c --- qmail-1.03/qmail-local.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail-local.c Mon Oct 27 17:33:13 2003 @@ -645,7 +645,7 @@ { cmds.s[j] = 0; k = j; - while ((k > i) && (cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t')) + while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))) cmds.s[--k] = 0; switch(cmds.s[i]) { diff -urN qmail-1.03/qmail-log.5 netqmail-1.04/qmail-log.5 --- qmail-1.03/qmail-log.5 Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail-log.5 Mon Oct 27 17:33:13 2003 @@ -232,6 +232,11 @@ is unable to queue a bounce message, usually because the machine is almost out of memory. It will try again later. +This can also be caused by incorrect settings of +.B $QMAILQUEUE +or errors in a program or script which +.B $QMAILQUEUE +points to. .TP .B unable to stat ... .B qmail-send diff -urN qmail-1.03/qmail-queue.8 netqmail-1.04/qmail-queue.8 --- qmail-1.03/qmail-queue.8 Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail-queue.8 Mon Oct 27 17:33:13 2003 @@ -40,6 +40,12 @@ However, the recipients probably expect to see a proper header, as described in .BR qmail-header(5) . + +Programs included with qmail which invoke +.B qmail-queue +will invoke the contents of +.B $QMAILQUEUE +instead, if that environment variable is set. .SH "FILESYSTEM RESTRICTIONS" .B qmail-queue imposes two constraints on the queue structure: diff -urN qmail-1.03/qmail-smtpd.c netqmail-1.04/qmail-smtpd.c --- qmail-1.03/qmail-smtpd.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail-smtpd.c Mon Oct 27 17:33:13 2003 @@ -69,7 +69,7 @@ } void smtp_help() { - out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); + out("214 netqmail home page: http://qmail.org/netqmail\r\n"); } void smtp_quit() { diff -urN qmail-1.03/qmail.7 netqmail-1.04/qmail.7 --- qmail-1.03/qmail.7 Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail.7 Mon Oct 27 17:33:13 2003 @@ -55,12 +55,14 @@ and .BR qmail-pop3d (8). -This documentation describes version -1.03 +This documentation describes netqmail version +1.04 of .BR qmail . See .B http://pobox.com/~djb/qmail.html for other .BR qmail -related -software. +software, and +.B http://qmail.org/ +for other qmail community contributions. diff -urN qmail-1.03/qmail.c netqmail-1.04/qmail.c --- qmail-1.03/qmail.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/qmail.c Mon Oct 27 17:33:13 2003 @@ -6,14 +6,25 @@ #include "fd.h" #include "qmail.h" #include "auto_qmail.h" +#include "env.h" -static char *binqqargs[2] = { "bin/qmail-queue", 0 } ; +static char *binqqargs[2] = { 0, 0 } ; + +static void setup_qqargs() +{ + if(!binqqargs[0]) + binqqargs[0] = env_get("QMAILQUEUE"); + if(!binqqargs[0]) + binqqargs[0] = "bin/qmail-queue"; +} int qmail_open(qq) struct qmail *qq; { int pim[2]; int pie[2]; + + setup_qqargs(); if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } diff -urN qmail-1.03/sendmail.c netqmail-1.04/sendmail.c --- qmail-1.03/sendmail.c Mon Jun 15 04:53:16 1998 +++ netqmail-1.04/sendmail.c Mon Oct 27 17:33:13 2003 @@ -45,6 +45,38 @@ _exit(111); } +void do_sender(s) +const char *s; +{ + char *x; + int n; + int a; + int i; + + env_unset("QMAILNAME"); + env_unset("MAILNAME"); + env_unset("NAME"); + env_unset("QMAILHOST"); + env_unset("MAILHOST"); + + n = str_len(s); + a = str_rchr(s, '@'); + if (a == n) + { + env_put2("QMAILUSER", s); + return; + } + env_put2("QMAILHOST", s + a + 1); + + x = (char *) alloc((a + 1) * sizeof(char)); + if (!x) nomem(); + for (i = 0; i < a; i++) + x[i] = s[i]; + x[i] = 0; + env_put2("QMAILUSER", x); + alloc_free(x); +} + int flagh; char *sender; @@ -118,6 +150,7 @@ if (sender) { *arg++ = "-f"; *arg++ = sender; + do_sender(sender); } *arg++ = "--"; for (i = 0;i < argc;++i) *arg++ = argv[i]; netqmail-1.06/old-patches/README0000644000076400007640000000032310003260406015710 0ustar nelsonnelsonThese files are not used. Their purpose is to show the changes between netqmail-1.04 and netqmail-1.05. The latter is a combination of the original netqmail-1.04 patch and James Craig Burley's qmail-isoc patch. netqmail-1.06/old-patches/qmail-isoc.patch0000644000076400007640000002466310003530420020120 0ustar nelsonnelsonThis patch is Copyright (C) 2004 by James Craig Burley. License below. 2004-01-19 0040 EST James Craig Burley This patch improves ISO C conformance of qmail code -- specifically, of qmail-lspawn, qmail-newmrh, qmail-newu, qmail-pop3d, qmail-popup, qmail-rspawn, and qmail-smtpd. This fixes two known bugs: - qmail-smtpd can be crashed by a client sending a sufficiently long (e.g. 2GB) header line in an email. - qmail_lspawn, qmail-newmrh, qmail-newu, and qmail-rspawn might crash or otherwise misbehave on hosts with a smaller "int" type than "char *" type, e.g. 64-bit hosts with 32-bit "int"s. The other changes are unlikely to have any effect, except possibly on unusual architectures and/or in the presence of rare optimizations. This is Version 1 of this patch. It adds the changes to cdbmake_add.c, spawn.c, and, correspondingly, Makefile, which pertain to the second bug listed above. See all my qmail patches at . License: Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *** qmail-1.03/cdbmake_add.c Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/cdbmake_add.c Mon Jan 19 00:35:38 2004 *************** *** 1,2 **** --- 1,3 ---- + #include "alloc.h" #include "cdbmake.h" *** qmail-1.03/Makefile Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/Makefile Mon Jan 19 00:35:35 2004 *************** makelib cdbmake_pack.o cdbmake_hash.o cd *** 264,268 **** cdbmake_add.o: \ ! compile cdbmake_add.c cdbmake.h uint32.h ./compile cdbmake_add.c --- 264,268 ---- cdbmake_add.o: \ ! compile cdbmake_add.c cdbmake.h alloc.h uint32.h ./compile cdbmake_add.c *************** trylsock.c compile load *** 1893,1897 **** spawn.o: \ compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ ! stralloc.h gen_alloc.h select.h exit.h coe.h open.h error.h \ auto_qmail.h auto_uids.h auto_spawn.h ./chkspawn --- 1893,1897 ---- spawn.o: \ compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ ! stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \ auto_qmail.h auto_uids.h auto_spawn.h ./chkspawn *** qmail-1.03/qmail-pop3d.c Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/qmail-pop3d.c Thu Jan 15 22:08:57 2004 *************** void die_scan() { err("unable to scan $H *** 67,71 **** void err_syntax() { err("syntax error"); } ! void err_unimpl() { err("unimplemented"); } void err_deleted() { err("already deleted"); } void err_nozero() { err("messages are counted from 1"); } --- 67,71 ---- void err_syntax() { err("syntax error"); } ! void err_unimpl(arg) char *arg; { err("unimplemented"); } void err_deleted() { err("already deleted"); } void err_nozero() { err("messages are counted from 1"); } *************** void err_nosuch() { err("unable to open *** 74,78 **** void err_nounlink() { err("unable to unlink all deleted messages"); } ! void okay() { puts("+OK \r\n"); flush(); } void printfn(fn) char *fn; --- 74,78 ---- void err_nounlink() { err("unable to unlink all deleted messages"); } ! void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } void printfn(fn) char *fn; *************** void getlist() *** 147,151 **** } ! void pop3_stat() { int i; --- 147,151 ---- } ! void pop3_stat(arg) char *arg; { int i; *************** void pop3_stat() *** 162,174 **** } ! void pop3_rset() { int i; for (i = 0;i < numm;++i) m[i].flagdeleted = 0; last = 0; ! okay(); } ! void pop3_last() { puts("+OK "); --- 162,174 ---- } ! void pop3_rset(arg) char *arg; { int i; for (i = 0;i < numm;++i) m[i].flagdeleted = 0; last = 0; ! okay(0); } ! void pop3_last(arg) char *arg; { puts("+OK "); *************** void pop3_last() *** 178,182 **** } ! void pop3_quit() { int i; --- 178,182 ---- } ! void pop3_quit(arg) char *arg; { int i; *************** void pop3_quit() *** 193,197 **** rename(m[i].fn,line.s); /* if it fails, bummer */ } ! okay(); die(); } --- 193,197 ---- rename(m[i].fn,line.s); /* if it fails, bummer */ } ! okay(0); die(); } *************** void pop3_dele(arg) char *arg; *** 215,219 **** m[i].flagdeleted = 1; if (i + 1 > last) last = i + 1; ! okay(); } --- 215,219 ---- m[i].flagdeleted = 1; if (i + 1 > last) last = i + 1; ! okay(0); } *************** void dolisting(arg,flaguidl) char *arg; *** 239,243 **** } else { ! okay(); for (i = 0;i < numm;++i) if (!m[i].flagdeleted) --- 239,243 ---- } else { ! okay(0); for (i = 0;i < numm;++i) if (!m[i].flagdeleted) *************** void pop3_top(arg) char *arg; *** 268,272 **** fd = open_read(m[i].fn); if (fd == -1) { err_nosuch(); return; } ! okay(); substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); blast(&ssmsg,limit); --- 268,272 ---- fd = open_read(m[i].fn); if (fd == -1) { err_nosuch(); return; } ! okay(0); substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); blast(&ssmsg,limit); *************** char **argv; *** 300,304 **** getlist(); ! okay(); commands(&ssin,pop3commands); die(); --- 300,304 ---- getlist(); ! okay(0); commands(&ssin,pop3commands); die(); *** qmail-1.03/qmail-popup.c Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/qmail-popup.c Thu Jan 15 22:09:21 2004 *************** void die_badauth() { err("authorization *** 65,72 **** void err_syntax() { err("syntax error"); } void err_wantuser() { err("USER first"); } ! void err_authoriz() { err("authorization first"); } ! void okay() { puts("+OK \r\n"); flush(); } ! void pop3_quit() { okay(); die(); } --- 65,72 ---- void err_syntax() { err("syntax error"); } void err_wantuser() { err("USER first"); } ! void err_authoriz(arg) char *arg; { err("authorization first"); } ! void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } ! void pop3_quit(arg) char *arg; { okay(0); die(); } *************** void pop3_user(arg) char *arg; *** 137,141 **** { if (!*arg) { err_syntax(); return; } ! okay(); seenuser = 1; if (!stralloc_copys(&username,arg)) die_nomem(); --- 137,141 ---- { if (!*arg) { err_syntax(); return; } ! okay(0); seenuser = 1; if (!stralloc_copys(&username,arg)) die_nomem(); *** qmail-1.03/qmail-smtpd.c Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/qmail-smtpd.c Thu Jan 15 22:12:02 2004 *************** void straynewline() { out("451 See http: *** 52,61 **** void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } ! void err_unimpl() { out("502 unimplemented (#5.5.1)\r\n"); } void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } ! void err_noop() { out("250 ok\r\n"); } ! void err_vrfy() { out("252 send some mail, i'll try my best\r\n"); } void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } --- 52,61 ---- void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } ! void err_unimpl(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); } void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } ! void err_noop(arg) char *arg; { out("250 ok\r\n"); } ! void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); } void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } *************** void smtp_greet(code) char *code; *** 68,76 **** substdio_put(&ssout,greeting.s,greeting.len); } ! void smtp_help() { out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); } ! void smtp_quit() { smtp_greet("221 "); out("\r\n"); flush(); _exit(0); --- 68,76 ---- substdio_put(&ssout,greeting.s,greeting.len); } ! void smtp_help(arg) char *arg; { out("214 qmail home page: http://pobox.com/~djb/qmail.html\r\n"); } ! void smtp_quit(arg) char *arg; { smtp_greet("221 "); out("\r\n"); flush(); _exit(0); *************** void smtp_ehlo(arg) char *arg; *** 233,237 **** seenmail = 0; dohelo(arg); } ! void smtp_rset() { seenmail = 0; --- 233,237 ---- seenmail = 0; dohelo(arg); } ! void smtp_rset(arg) char *arg; { seenmail = 0; *************** int *hops; *** 317,322 **** if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; if (flagmaybey) if (pos == 1) flaginheader = 0; } - ++pos; if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } } --- 317,322 ---- if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; if (flagmaybey) if (pos == 1) flaginheader = 0; + ++pos; } if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } } *************** void acceptmessage(qp) unsigned long qp; *** 366,370 **** } ! void smtp_data() { int hops; unsigned long qp; --- 366,370 ---- } ! void smtp_data(arg) char *arg; { int hops; unsigned long qp; *** qmail-1.03/spawn.c Mon Jun 15 06:53:16 1998 --- qmail-1.03.0/spawn.c Mon Jan 19 00:35:38 2004 *************** *** 6,9 **** --- 6,10 ---- #include "byte.h" #include "str.h" + #include "alloc.h" #include "stralloc.h" #include "select.h" netqmail-1.06/qsutil.c0000644000076400007640000000222006541176434014333 0ustar nelsonnelson#include "stralloc.h" #include "readwrite.h" #include "substdio.h" #include "qsutil.h" static stralloc foo = {0}; static char errbuf[1]; static struct substdio sserr = SUBSTDIO_FDBUF(write,0,errbuf,1); void logsa(sa) stralloc *sa; { substdio_putflush(&sserr,sa->s,sa->len); } void log1(s1) char *s1; { substdio_putsflush(&sserr,s1); } void log2(s1,s2) char *s1; char *s2; { substdio_putsflush(&sserr,s1); substdio_putsflush(&sserr,s2); } void log3(s1,s2,s3) char *s1; char *s2; char *s3; { substdio_putsflush(&sserr,s1); substdio_putsflush(&sserr,s2); substdio_putsflush(&sserr,s3); } void nomem() { log1("alert: out of memory, sleeping...\n"); sleep(10); } void pausedir(dir) char *dir; { log3("alert: unable to opendir ",dir,", sleeping...\n"); sleep(10); } static int issafe(ch) char ch; { if (ch == '%') return 0; /* general principle: allman's code is crap */ if (ch < 33) return 0; if (ch > 126) return 0; return 1; } void logsafe(s) char *s; { int i; while (!stralloc_copys(&foo,s)) nomem(); for (i = 0;i < foo.len;++i) if (foo.s[i] == '\n') foo.s[i] = '/'; else if (!issafe(foo.s[i])) foo.s[i] = '_'; logsa(&foo); } netqmail-1.06/fork.h20000644000076400007640000000011606541176434014044 0ustar nelsonnelson#ifndef FORK_H #define FORK_H extern int fork(); extern int vfork(); #endif netqmail-1.06/tryrsolv.c0000644000076400007640000000001706541176434014720 0ustar nelsonnelsonmain() { ; } netqmail-1.06/conf-groups0000644000076400007640000000032706541176434015041 0ustar nelsonnelsonqmail nofiles These are the qmail groups. The second group should not have access to any files, but it must be usable for processes; this requirement excludes the ``nogroup'' and ``nobody'' groups on many systems. netqmail-1.06/qmail-start.90000644000076400007640000000277406541176434015214 0ustar nelsonnelson.TH qmail-start 8 .SH NAME qmail-start \- turn on mail delivery .SH SYNOPSIS .B qmail-start [ .I defaultdelivery [ .I logger arg ... ] ] .SH DESCRIPTION .B qmail-start invokes .BR qmail-send , .BR qmail-lspawn , .BR qmail-rspawn , and .BR qmail-clean , under the proper uids and gids. These four daemons cooperate to deliver messages from the queue. .B qmail-start arranges for .BR qmail-send 's activity record to be sent to .BR qmail-start 's output. See .B qmail-log(5) for the format of the activity record. Other than this, .B qmail-start does not print anything, even on failure. If .I defaultdelivery is supplied, .B qmail-start passes it to .BR qmail-lspawn . If .I logger is supplied, .B qmail-start invokes .I logger with the given arguments, and feeds .BR qmail-send 's activity record through .IR logger . Environment variables given to .B qmail-start will eventually be passed on to .BR qmail-local , so make sure to clean up the environment if you run .B qmail-start manually: .EX # env - PATH="QMAILHOME/bin:$PATH" .br qmail-start ./Mailbox splogger qmail & .br (all on one line) .EE Resource limits, controlling ttys, et al. are also passed from .B qmail-start to .BR qmail-local . Note that .B qmail-send normally juggles several simultaneous deliveries. To reduce .BR qmail-send 's impact on other programs, you can run .B qmail-start with a low priority. .SH "SEE ALSO" logger(1), splogger(1), nice(1), qmail-log(5), qmail-local(8), qmail-clean(8), qmail-lspawn(8), qmail-rspawn(8), qmail-send(8) netqmail-1.06/constmap.h0000644000076400007640000000046206541176434014651 0ustar nelsonnelson#ifndef CONSTMAP_H #define CONSTMAP_H typedef unsigned long constmap_hash; struct constmap { int num; constmap_hash mask; constmap_hash *hash; int *first; int *next; char **input; int *inputlen; } ; extern int constmap_init(); extern void constmap_free(); extern char *constmap(); #endif netqmail-1.06/ipmeprint.c0000644000076400007640000000073306541176434015030 0ustar nelsonnelson#include "subfd.h" #include "substdio.h" #include "ip.h" #include "ipme.h" #include "exit.h" char temp[IPFMT]; void main() { int j; switch(ipme_init()) { case 0: substdio_putsflush(subfderr,"out of memory\n"); _exit(111); case -1: substdio_putsflush(subfderr,"hard error\n"); _exit(100); } for (j = 0;j < ipme.len;++j) { substdio_put(subfdout,temp,ip_fmt(temp,&ipme.ix[j].ip)); substdio_puts(subfdout,"\n"); } substdio_flush(subfdout); _exit(0); } netqmail-1.06/strerr_sys.c0000644000076400007640000000030006541176434015226 0ustar nelsonnelson#include "error.h" #include "strerr.h" struct strerr strerr_sys; void strerr_sysinit() { strerr_sys.who = 0; strerr_sys.x = error_str(errno); strerr_sys.y = ""; strerr_sys.z = ""; } netqmail-1.06/headerbody.c0000644000076400007640000000324406541176434015127 0ustar nelsonnelson#include "stralloc.h" #include "substdio.h" #include "getln.h" #include "hfield.h" #include "headerbody.h" static int getsa(ss,sa,match) substdio *ss; stralloc *sa; int *match; { if (!*match) return 0; if (getln(ss,sa,match,'\n') == -1) return -1; if (*match) return 1; if (!sa->len) return 0; if (!stralloc_append(sa,"\n")) return -1; return 1; } static stralloc line = {0}; static stralloc nextline = {0}; int headerbody(ss,dohf,hdone,dobl) substdio *ss; void (*dohf)(); void (*hdone)(); void (*dobl)(); { int match; int flaglineok; match = 1; flaglineok = 0; for (;;) { switch(getsa(ss,&nextline,&match)) { case -1: return -1; case 0: if (flaglineok) dohf(&line); hdone(); /* no message body; could insert blank line here */ return 0; } if (flaglineok) { if ((nextline.s[0] == ' ') || (nextline.s[0] == '\t')) { if (!stralloc_cat(&line,&nextline)) return -1; continue; } dohf(&line); } if (nextline.len == 1) { hdone(); dobl(&nextline); break; } if (stralloc_starts(&nextline,"From ")) { if (!stralloc_copys(&line,"MBOX-Line: ")) return -1; if (!stralloc_cat(&line,&nextline)) return -1; } else if (hfield_valid(nextline.s,nextline.len)) { if (!stralloc_copy(&line,&nextline)) return -1; } else { hdone(); if (!stralloc_copys(&line,"\n")) return -1; dobl(&line); dobl(&nextline); break; } flaglineok = 1; } for (;;) switch(getsa(ss,&nextline,&match)) { case -1: return -1; case 0: return 0; case 1: dobl(&nextline); } } netqmail-1.06/lock_un.c0000644000076400007640000000035606541176434014454 0ustar nelsonnelson#include #include #include #include "hasflock.h" #include "lock.h" #ifdef HASFLOCK int lock_un(fd) int fd; { return flock(fd,LOCK_UN); } #else int lock_un(fd) int fd; { return lockf(fd,0,0); } #endif netqmail-1.06/auto_spawn.h0000644000076400007640000000011206541176434015175 0ustar nelsonnelson#ifndef AUTO_SPAWN_H #define AUTO_SPAWN_H extern int auto_spawn; #endif netqmail-1.06/exit.h0000644000076400007640000000007406541176434013775 0ustar nelsonnelson#ifndef EXIT_H #define EXIT_H extern void _exit(); #endif netqmail-1.06/BIN.README0000644000076400007640000000135706541176434014147 0ustar nelsonnelsonLike any other piece of software (and information generally), qmail comes with NO WARRANTY. Configuration: The qmail home directory is /var/qmail. (This must be a local directory, not shared among machines. Under Linux, make sure that all mail-handling filesystems are mounted with synchronous metadata.) The user-ext delimiter is -. The silent concurrency limit is 120. The queue subdirectory split is 23. To install: # make setup To set up qmail to receive and deliver mail, follow the instructions in /var/qmail/doc/fastforward/ALIASES, and then start at step 9 of /var/qmail/doc/INSTALL. Compilation environment: Oops, the package creator forgot to edit this! He's supposed to list his OS version, compiler version, hardware, and name. netqmail-1.06/alloc_re.c0000644000076400007640000000032606541176434014577 0ustar nelsonnelson#include "alloc.h" #include "byte.h" int alloc_re(x,m,n) char **x; unsigned int m; unsigned int n; { char *y; y = alloc(n); if (!y) return 0; byte_copy(y,m,*x); alloc_free(*x); *x = y; return 1; } netqmail-1.06/subfdin.c0000644000076400007640000000052406541176434014451 0ustar nelsonnelson#include "readwrite.h" #include "substdio.h" #include "subfd.h" int subfd_read(fd,buf,len) int fd; char *buf; int len; { if (substdio_flush(subfdout) == -1) return -1; return read(fd,buf,len); } char subfd_inbuf[SUBSTDIO_INSIZE]; static substdio it = SUBSTDIO_FDBUF(subfd_read,0,subfd_inbuf,SUBSTDIO_INSIZE); substdio *subfdin = ⁢ netqmail-1.06/fd_copy.30000644000076400007640000000107306541176434014362 0ustar nelsonnelson.TH fd_copy 3 .SH NAME fd_copy \- duplicate a descriptor .SH SYNTAX .B #include int \fBfd_copy\fP(\fIto\fR,\fIfrom\fR); int \fIto\fR; .br int \fIfrom\fR; .SH DESCRIPTION .B fd_copy copies descriptor .I from to descriptor .IR to . If .I to was already open, .B fd_copy closes it. .B fd_copy always leaves .I from intact; if .I to and .I from are the same number, .B fd_copy does nothing. .B fd_copy returns 0 on success, -1 on error. .B fd_copy does not guarantee that .I to will remain open, if it was open, in case of error. .SH "SEE ALSO" dup(2), fd_move(3) netqmail-1.06/cdbmss.c0000644000076400007640000000306206541176434014272 0ustar nelsonnelson#include "readwrite.h" #include "seek.h" #include "alloc.h" #include "cdbmss.h" int cdbmss_start(c,fd) struct cdbmss *c; int fd; { cdbmake_init(&c->cdbm); c->fd = fd; c->pos = sizeof(c->cdbm.final); substdio_fdbuf(&c->ss,write,fd,c->ssbuf,sizeof(c->ssbuf)); return seek_set(fd,(seek_pos) c->pos); } int cdbmss_add(c,key,keylen,data,datalen) struct cdbmss *c; unsigned char *key; unsigned int keylen; unsigned char *data; unsigned int datalen; { uint32 h; int i; cdbmake_pack(c->packbuf,(uint32) keylen); cdbmake_pack(c->packbuf + 4,(uint32) datalen); if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; if (substdio_put(&c->ss,key,keylen) == -1) return -1; if (substdio_put(&c->ss,data,datalen) == -1) return -1; h = CDBMAKE_HASHSTART; for (i = 0;i < keylen;++i) h = cdbmake_hashadd(h,(unsigned int) key[i]); if (!cdbmake_add(&c->cdbm,h,c->pos,alloc)) return -1; c->pos += 8 + keylen + datalen; /* XXX: overflow? */ return 0; } int cdbmss_finish(c) struct cdbmss *c; { int i; uint32 len; uint32 u; if (!cdbmake_split(&c->cdbm,alloc)) return -1; for (i = 0;i < 256;++i) { len = cdbmake_throw(&c->cdbm,c->pos,i); for (u = 0;u < len;++u) { cdbmake_pack(c->packbuf,c->cdbm.hash[u].h); cdbmake_pack(c->packbuf + 4,c->cdbm.hash[u].p); if (substdio_put(&c->ss,c->packbuf,8) == -1) return -1; c->pos += 8; /* XXX: overflow? */ } } if (substdio_flush(&c->ss) == -1) return -1; if (seek_begin(c->fd) == -1) return -1; return substdio_putflush(&c->ss,c->cdbm.final,sizeof(c->cdbm.final)); } netqmail-1.06/qmail-clean.c0000644000076400007640000000425306541176434015205 0ustar nelsonnelson#include #include #include "readwrite.h" #include "sig.h" #include "now.h" #include "str.h" #include "direntry.h" #include "getln.h" #include "stralloc.h" #include "substdio.h" #include "subfd.h" #include "byte.h" #include "scan.h" #include "fmt.h" #include "error.h" #include "exit.h" #include "fmtqfn.h" #include "auto_qmail.h" #define OSSIFIED 129600 /* see qmail-send.c */ stralloc line = {0}; void cleanuppid() { DIR *dir; direntry *d; struct stat st; datetime_sec time; time = now(); dir = opendir("pid"); if (!dir) return; while (d = readdir(dir)) { if (str_equal(d->d_name,".")) continue; if (str_equal(d->d_name,"..")) continue; if (!stralloc_copys(&line,"pid/")) continue; if (!stralloc_cats(&line,d->d_name)) continue; if (!stralloc_0(&line)) continue; if (stat(line.s,&st) == -1) continue; if (time < st.st_atime + OSSIFIED) continue; unlink(line.s); } closedir(dir); } char fnbuf[FMTQFN]; void respond(s) char *s; { if (substdio_putflush(subfdoutsmall,s,1) == -1) _exit(100); } void main() { int i; int match; int cleanuploop; unsigned long id; if (chdir(auto_qmail) == -1) _exit(111); if (chdir("queue") == -1) _exit(111); sig_pipeignore(); if (!stralloc_ready(&line,200)) _exit(111); cleanuploop = 0; for (;;) { if (cleanuploop) --cleanuploop; else { cleanuppid(); cleanuploop = 30; } if (getln(subfdinsmall,&line,&match,'\0') == -1) break; if (!match) break; if (line.len < 7) { respond("x"); continue; } if (line.len > 100) { respond("x"); continue; } if (line.s[line.len - 1]) { respond("x"); continue; } /* impossible */ for (i = 5;i < line.len - 1;++i) if ((unsigned char) (line.s[i] - '0') > 9) { respond("x"); continue; } if (!scan_ulong(line.s + 5,&id)) { respond("x"); continue; } if (byte_equal(line.s,5,"foop/")) { #define U(prefix,flag) fmtqfn(fnbuf,prefix,id,flag); \ if (unlink(fnbuf) == -1) if (errno != error_noent) { respond("!"); continue; } U("intd/",0) U("mess/",1) respond("+"); } else if (byte_equal(line.s,4,"todo/")) { U("intd/",0) U("todo/",0) respond("+"); } else respond("x"); } _exit(0); } netqmail-1.06/conf-users0000644000076400007640000000053306541176434014662 0ustar nelsonnelsonalias qmaild qmaill root qmailp qmailq qmailr qmails The qmail system is heavily partitioned for security; it does almost nothing as root. The first eight lines of this file are the alias user, the daemon user, the log user, the owner of miscellaneous files such as binaries, the passwd user, the queue user, the remote user, and the send user. netqmail-1.06/proc+df.sh0000644000076400007640000000046006541176434014536 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using dot-forward to support sendmail-style ~/.forward files. # Using procmail to deliver messages to /var/spool/mail/$USER by default. exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|dot-forward .forward |preline procmail' splogger qmail netqmail-1.06/fmt_ulong.c0000644000076400007640000000050006541176434015003 0ustar nelsonnelson#include "fmt.h" unsigned int fmt_ulong(s,u) register char *s; register unsigned long u; { register unsigned int len; register unsigned long q; len = 1; q = u; while (q > 9) { ++len; q /= 10; } if (s) { s += len; do { *--s = '0' + (u % 10); u /= 10; } while(u); /* handles u == 0 */ } return len; } netqmail-1.06/qmail-smtpd.c0000644000076400007640000002612710724070436015247 0ustar nelsonnelson#include "sig.h" #include "readwrite.h" #include "stralloc.h" #include "substdio.h" #include "alloc.h" #include "auto_qmail.h" #include "control.h" #include "received.h" #include "constmap.h" #include "error.h" #include "ipme.h" #include "ip.h" #include "qmail.h" #include "str.h" #include "fmt.h" #include "scan.h" #include "byte.h" #include "case.h" #include "env.h" #include "now.h" #include "exit.h" #include "rcpthosts.h" #include "timeoutread.h" #include "timeoutwrite.h" #include "commands.h" #define MAXHOPS 100 unsigned int databytes = 0; int timeout = 1200; int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(timeout,fd,buf,len); if (r <= 0) _exit(1); return r; } char ssoutbuf[512]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); void flush() { substdio_flush(&ssout); } void out(s) char *s; { substdio_puts(&ssout,s); } void die_read() { _exit(1); } void die_alarm() { out("451 timeout (#4.4.2)\r\n"); flush(); _exit(1); } void die_nomem() { out("421 out of memory (#4.3.0)\r\n"); flush(); _exit(1); } void die_control() { out("421 unable to read controls (#4.3.0)\r\n"); flush(); _exit(1); } void die_ipme() { out("421 unable to figure out my IP addresses (#4.3.0)\r\n"); flush(); _exit(1); } void straynewline() { out("451 See http://pobox.com/~djb/docs/smtplf.html.\r\n"); flush(); _exit(1); } void err_bmf() { out("553 sorry, your envelope sender is in my badmailfrom list (#5.7.1)\r\n"); } void err_nogateway() { out("553 sorry, that domain isn't in my list of allowed rcpthosts (#5.7.1)\r\n"); } void err_unimpl(arg) char *arg; { out("502 unimplemented (#5.5.1)\r\n"); } void err_syntax() { out("555 syntax error (#5.5.4)\r\n"); } void err_wantmail() { out("503 MAIL first (#5.5.1)\r\n"); } void err_wantrcpt() { out("503 RCPT first (#5.5.1)\r\n"); } void err_noop(arg) char *arg; { out("250 ok\r\n"); } void err_vrfy(arg) char *arg; { out("252 send some mail, i'll try my best\r\n"); } void err_qqt() { out("451 qqt failure (#4.3.0)\r\n"); } stralloc greeting = {0}; void smtp_greet(code) char *code; { substdio_puts(&ssout,code); substdio_put(&ssout,greeting.s,greeting.len); } void smtp_help(arg) char *arg; { out("214 netqmail home page: http://qmail.org/netqmail\r\n"); } void smtp_quit(arg) char *arg; { smtp_greet("221 "); out("\r\n"); flush(); _exit(0); } char *remoteip; char *remotehost; char *remoteinfo; char *local; char *relayclient; stralloc helohost = {0}; char *fakehelo; /* pointer into helohost, or 0 */ void dohelo(arg) char *arg; { if (!stralloc_copys(&helohost,arg)) die_nomem(); if (!stralloc_0(&helohost)) die_nomem(); fakehelo = case_diffs(remotehost,helohost.s) ? helohost.s : 0; } int liphostok = 0; stralloc liphost = {0}; int bmfok = 0; stralloc bmf = {0}; struct constmap mapbmf; void setup() { char *x; unsigned long u; if (control_init() == -1) die_control(); if (control_rldef(&greeting,"control/smtpgreeting",1,(char *) 0) != 1) die_control(); liphostok = control_rldef(&liphost,"control/localiphost",1,(char *) 0); if (liphostok == -1) die_control(); if (control_readint(&timeout,"control/timeoutsmtpd") == -1) die_control(); if (timeout <= 0) timeout = 1; if (rcpthosts_init() == -1) die_control(); bmfok = control_readfile(&bmf,"control/badmailfrom",0); if (bmfok == -1) die_control(); if (bmfok) if (!constmap_init(&mapbmf,bmf.s,bmf.len,0)) die_nomem(); if (control_readint(&databytes,"control/databytes") == -1) die_control(); x = env_get("DATABYTES"); if (x) { scan_ulong(x,&u); databytes = u; } if (!(databytes + 1)) --databytes; remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); relayclient = env_get("RELAYCLIENT"); dohelo(remotehost); } stralloc addr = {0}; /* will be 0-terminated, if addrparse returns 1 */ int addrparse(arg) char *arg; { int i; char ch; char terminator; struct ip_address ip; int flagesc; int flagquoted; terminator = '>'; i = str_chr(arg,'<'); if (arg[i]) arg += i + 1; else { /* partner should go read rfc 821 */ terminator = ' '; arg += str_chr(arg,':'); if (*arg == ':') ++arg; while (*arg == ' ') ++arg; } /* strip source route */ if (*arg == '@') while (*arg) if (*arg++ == ':') break; if (!stralloc_copys(&addr,"")) die_nomem(); flagesc = 0; flagquoted = 0; for (i = 0;ch = arg[i];++i) { /* copy arg to addr, stripping quotes */ if (flagesc) { if (!stralloc_append(&addr,&ch)) die_nomem(); flagesc = 0; } else { if (!flagquoted && (ch == terminator)) break; switch(ch) { case '\\': flagesc = 1; break; case '"': flagquoted = !flagquoted; break; default: if (!stralloc_append(&addr,&ch)) die_nomem(); } } } /* could check for termination failure here, but why bother? */ if (!stralloc_append(&addr,"")) die_nomem(); if (liphostok) { i = byte_rchr(addr.s,addr.len,'@'); if (i < addr.len) /* if not, partner should go read rfc 821 */ if (addr.s[i + 1] == '[') if (!addr.s[i + 1 + ip_scanbracket(addr.s + i + 1,&ip)]) if (ipme_is(&ip)) { addr.len = i + 1; if (!stralloc_cat(&addr,&liphost)) die_nomem(); if (!stralloc_0(&addr)) die_nomem(); } } if (addr.len > 900) return 0; return 1; } int bmfcheck() { int j; if (!bmfok) return 0; if (constmap(&mapbmf,addr.s,addr.len - 1)) return 1; j = byte_rchr(addr.s,addr.len,'@'); if (j < addr.len) if (constmap(&mapbmf,addr.s + j,addr.len - j - 1)) return 1; return 0; } int addrallowed() { int r; r = rcpthosts(addr.s,str_len(addr.s)); if (r == -1) die_control(); return r; } int seenmail = 0; int flagbarf; /* defined if seenmail */ stralloc mailfrom = {0}; stralloc rcptto = {0}; void smtp_helo(arg) char *arg; { smtp_greet("250 "); out("\r\n"); seenmail = 0; dohelo(arg); } void smtp_ehlo(arg) char *arg; { smtp_greet("250-"); out("\r\n250-PIPELINING\r\n250 8BITMIME\r\n"); seenmail = 0; dohelo(arg); } void smtp_rset(arg) char *arg; { seenmail = 0; out("250 flushed\r\n"); } void smtp_mail(arg) char *arg; { if (!addrparse(arg)) { err_syntax(); return; } flagbarf = bmfcheck(); seenmail = 1; if (!stralloc_copys(&rcptto,"")) die_nomem(); if (!stralloc_copys(&mailfrom,addr.s)) die_nomem(); if (!stralloc_0(&mailfrom)) die_nomem(); out("250 ok\r\n"); } void smtp_rcpt(arg) char *arg; { if (!seenmail) { err_wantmail(); return; } if (!addrparse(arg)) { err_syntax(); return; } if (flagbarf) { err_bmf(); return; } if (relayclient) { --addr.len; if (!stralloc_cats(&addr,relayclient)) die_nomem(); if (!stralloc_0(&addr)) die_nomem(); } else if (!addrallowed()) { err_nogateway(); return; } if (!stralloc_cats(&rcptto,"T")) die_nomem(); if (!stralloc_cats(&rcptto,addr.s)) die_nomem(); if (!stralloc_0(&rcptto)) die_nomem(); out("250 ok\r\n"); } int saferead(fd,buf,len) int fd; char *buf; int len; { int r; flush(); r = timeoutread(timeout,fd,buf,len); if (r == -1) if (errno == error_timeout) die_alarm(); if (r <= 0) die_read(); return r; } char ssinbuf[1024]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); struct qmail qqt; unsigned int bytestooverflow = 0; void put(ch) char *ch; { if (bytestooverflow) if (!--bytestooverflow) qmail_fail(&qqt); qmail_put(&qqt,ch,1); } void blast(hops) int *hops; { char ch; int state; int flaginheader; int pos; /* number of bytes since most recent \n, if fih */ int flagmaybex; /* 1 if this line might match RECEIVED, if fih */ int flagmaybey; /* 1 if this line might match \r\n, if fih */ int flagmaybez; /* 1 if this line might match DELIVERED, if fih */ state = 1; *hops = 0; flaginheader = 1; pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; for (;;) { substdio_get(&ssin,&ch,1); if (flaginheader) { if (pos < 9) { if (ch != "delivered"[pos]) if (ch != "DELIVERED"[pos]) flagmaybez = 0; if (flagmaybez) if (pos == 8) ++*hops; if (pos < 8) if (ch != "received"[pos]) if (ch != "RECEIVED"[pos]) flagmaybex = 0; if (flagmaybex) if (pos == 7) ++*hops; if (pos < 2) if (ch != "\r\n"[pos]) flagmaybey = 0; if (flagmaybey) if (pos == 1) flaginheader = 0; ++pos; } if (ch == '\n') { pos = 0; flagmaybex = flagmaybey = flagmaybez = 1; } } switch(state) { case 0: if (ch == '\n') straynewline(); if (ch == '\r') { state = 4; continue; } break; case 1: /* \r\n */ if (ch == '\n') straynewline(); if (ch == '.') { state = 2; continue; } if (ch == '\r') { state = 4; continue; } state = 0; break; case 2: /* \r\n + . */ if (ch == '\n') straynewline(); if (ch == '\r') { state = 3; continue; } state = 0; break; case 3: /* \r\n + .\r */ if (ch == '\n') return; put("."); put("\r"); if (ch == '\r') { state = 4; continue; } state = 0; break; case 4: /* + \r */ if (ch == '\n') { state = 1; break; } if (ch != '\r') { put("\r"); state = 0; } } put(&ch); } } char accept_buf[FMT_ULONG]; void acceptmessage(qp) unsigned long qp; { datetime_sec when; when = now(); out("250 ok "); accept_buf[fmt_ulong(accept_buf,(unsigned long) when)] = 0; out(accept_buf); out(" qp "); accept_buf[fmt_ulong(accept_buf,qp)] = 0; out(accept_buf); out("\r\n"); } void smtp_data(arg) char *arg; { int hops; unsigned long qp; char *qqx; if (!seenmail) { err_wantmail(); return; } if (!rcptto.len) { err_wantrcpt(); return; } seenmail = 0; if (databytes) bytestooverflow = databytes + 1; if (qmail_open(&qqt) == -1) { err_qqt(); return; } qp = qmail_qp(&qqt); out("354 go ahead\r\n"); received(&qqt,"SMTP",local,remoteip,remotehost,remoteinfo,fakehelo); blast(&hops); hops = (hops >= MAXHOPS); if (hops) qmail_fail(&qqt); qmail_from(&qqt,mailfrom.s); qmail_put(&qqt,rcptto.s,rcptto.len); qqx = qmail_close(&qqt); if (!*qqx) { acceptmessage(qp); return; } if (hops) { out("554 too many hops, this message is looping (#5.4.6)\r\n"); return; } if (databytes) if (!bytestooverflow) { out("552 sorry, that message size exceeds my databytes limit (#5.3.4)\r\n"); return; } if (*qqx == 'D') out("554 "); else out("451 "); out(qqx + 1); out("\r\n"); } struct commands smtpcommands[] = { { "rcpt", smtp_rcpt, 0 } , { "mail", smtp_mail, 0 } , { "data", smtp_data, flush } , { "quit", smtp_quit, flush } , { "helo", smtp_helo, flush } , { "ehlo", smtp_ehlo, flush } , { "rset", smtp_rset, 0 } , { "help", smtp_help, flush } , { "noop", err_noop, flush } , { "vrfy", err_vrfy, flush } , { 0, err_unimpl, flush } } ; void main() { sig_pipeignore(); if (chdir(auto_qmail) == -1) die_control(); setup(); if (ipme_init() != 1) die_ipme(); smtp_greet("220 "); out(" ESMTP\r\n"); if (commands(&ssin,&smtpcommands) == 0) die_read(); die_nomem(); } netqmail-1.06/now.c0000644000076400007640000000015406541176434013621 0ustar nelsonnelson#include #include "datetime.h" #include "now.h" datetime_sec now() { return time((long *) 0); } netqmail-1.06/qmail-qstat.80000644000076400007640000000053306541176434015201 0ustar nelsonnelson.TH qmail-qstat 8 .SH NAME qmail-qstat \- summarize status of mail queue .SH SYNOPSIS .B qmail-qstat .SH DESCRIPTION .B qmail-qstat gives a human-readable breakdown of the number of messages at various spots in the mail queue. .B qmail-qstat must be run either as .B root or with group id .BR qmail . .SH "SEE ALSO" qmail-qread(8), qmail-send(8) netqmail-1.06/trigger.h0000644000076400007640000000020406541176434014462 0ustar nelsonnelson#ifndef TRIGGER_H #define TRIGGER_H extern void trigger_set(); extern void trigger_selprep(); extern int trigger_pulled(); #endif netqmail-1.06/cdb_hash.c0000644000076400007640000000030606541176434014550 0ustar nelsonnelson#include "cdb.h" uint32 cdb_hash(buf,len) unsigned char *buf; unsigned int len; { uint32 h; h = 5381; while (len) { --len; h += (h << 5); h ^= (uint32) *buf++; } return h; } netqmail-1.06/qmail-popup.c0000644000076400007640000001000610724070436015250 0ustar nelsonnelson#include "commands.h" #include "fd.h" #include "sig.h" #include "stralloc.h" #include "substdio.h" #include "alloc.h" #include "wait.h" #include "str.h" #include "byte.h" #include "now.h" #include "fmt.h" #include "exit.h" #include "readwrite.h" #include "timeoutread.h" #include "timeoutwrite.h" void die() { _exit(1); } int saferead(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutread(1200,fd,buf,len); if (r <= 0) die(); return r; } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(1200,fd,buf,len); if (r <= 0) die(); return r; } char ssoutbuf[128]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); char ssinbuf[128]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); void puts(s) char *s; { substdio_puts(&ssout,s); } void flush() { substdio_flush(&ssout); } void err(s) char *s; { puts("-ERR "); puts(s); puts("\r\n"); flush(); } void die_usage() { err("usage: popup hostname subprogram"); die(); } void die_nomem() { err("out of memory"); die(); } void die_pipe() { err("unable to open pipe"); die(); } void die_write() { err("unable to write pipe"); die(); } void die_fork() { err("unable to fork"); die(); } void die_childcrashed() { err("aack, child crashed"); } void die_badauth() { err("authorization failed"); } void err_syntax() { err("syntax error"); } void err_wantuser() { err("USER first"); } void err_authoriz(arg) char *arg; { err("authorization first"); } void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } void pop3_quit(arg) char *arg; { okay(0); die(); } char unique[FMT_ULONG + FMT_ULONG + 3]; char *hostname; stralloc username = {0}; int seenuser = 0; char **childargs; substdio ssup; char upbuf[128]; void doanddie(user,userlen,pass) char *user; unsigned int userlen; /* including 0 byte */ char *pass; { int child; int wstat; int pi[2]; if (fd_copy(2,1) == -1) die_pipe(); close(3); if (pipe(pi) == -1) die_pipe(); if (pi[0] != 3) die_pipe(); switch(child = fork()) { case -1: die_fork(); case 0: close(pi[1]); sig_pipedefault(); execvp(*childargs,childargs); _exit(1); } close(pi[0]); substdio_fdbuf(&ssup,write,pi[1],upbuf,sizeof upbuf); if (substdio_put(&ssup,user,userlen) == -1) die_write(); if (substdio_put(&ssup,pass,str_len(pass) + 1) == -1) die_write(); if (substdio_puts(&ssup,"<") == -1) die_write(); if (substdio_puts(&ssup,unique) == -1) die_write(); if (substdio_puts(&ssup,hostname) == -1) die_write(); if (substdio_put(&ssup,">",2) == -1) die_write(); if (substdio_flush(&ssup) == -1) die_write(); close(pi[1]); byte_zero(pass,str_len(pass)); byte_zero(upbuf,sizeof upbuf); if (wait_pid(&wstat,child) == -1) die(); if (wait_crashed(wstat)) die_childcrashed(); if (wait_exitcode(wstat)) die_badauth(); die(); } void pop3_greet() { char *s; s = unique; s += fmt_uint(s,getpid()); *s++ = '.'; s += fmt_ulong(s,(unsigned long) now()); *s++ = '@'; *s++ = 0; puts("+OK <"); puts(unique); puts(hostname); puts(">\r\n"); flush(); } void pop3_user(arg) char *arg; { if (!*arg) { err_syntax(); return; } okay(0); seenuser = 1; if (!stralloc_copys(&username,arg)) die_nomem(); if (!stralloc_0(&username)) die_nomem(); } void pop3_pass(arg) char *arg; { if (!seenuser) { err_wantuser(); return; } if (!*arg) { err_syntax(); return; } doanddie(username.s,username.len,arg); } void pop3_apop(arg) char *arg; { char *space; space = arg + str_chr(arg,' '); if (!*space) { err_syntax(); return; } *space++ = 0; doanddie(arg,space - arg,space); } struct commands pop3commands[] = { { "user", pop3_user, 0 } , { "pass", pop3_pass, 0 } , { "apop", pop3_apop, 0 } , { "quit", pop3_quit, 0 } , { "noop", okay, 0 } , { 0, err_authoriz, 0 } } ; void main(argc,argv) int argc; char **argv; { sig_alarmcatch(die); sig_pipeignore(); hostname = argv[1]; if (!hostname) die_usage(); childargs = argv + 2; if (!*childargs) die_usage(); pop3_greet(); commands(&ssin,pop3commands); die(); } netqmail-1.06/wait_pid.c0000644000076400007640000000130506541176434014615 0ustar nelsonnelson#include #include #include "error.h" #include "haswaitp.h" #ifdef HASWAITPID int wait_pid(wstat,pid) int *wstat; int pid; { int r; do r = waitpid(pid,wstat,0); while ((r == -1) && (errno == error_intr)); return r; } #else /* XXX untested */ /* XXX breaks down with more than two children */ static int oldpid = 0; static int oldwstat; /* defined if(oldpid) */ int wait_pid(wstat,pid) int *wstat; int pid; { int r; if (pid == oldpid) { *wstat = oldwstat; oldpid = 0; return pid; } do { r = wait(wstat); if ((r != pid) && (r != -1)) { oldwstat = *wstat; oldpid = r; continue; } } while ((r == -1) && (errno == error_intr)); return r; } #endif netqmail-1.06/readsubdir.h0000644000076400007640000000041306541176434015145 0ustar nelsonnelson#ifndef READSUBDIR_H #define READSUBDIR_H #include "direntry.h" typedef struct readsubdir { DIR *dir; int pos; char *name; void (*pause)(); } readsubdir; extern void readsubdir_init(); extern int readsubdir_next(); #define READSUBDIR_NAMELEN 10 #endif netqmail-1.06/prot.h0000644000076400007640000000012506541176434014005 0ustar nelsonnelson#ifndef PROT_H #define PROT_H extern int prot_gid(); extern int prot_uid(); #endif netqmail-1.06/open_trunc.c0000644000076400007640000000023406541176434015171 0ustar nelsonnelson#include #include #include "open.h" int open_trunc(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY | O_TRUNC | O_CREAT,0644); } netqmail-1.06/instcheck.c0000644000076400007640000000437506541176434015002 0ustar nelsonnelson#include #include #include "strerr.h" #include "error.h" #include "readwrite.h" #include "exit.h" extern void hier(); #define FATAL "instcheck: fatal: " #define WARNING "instcheck: warning: " void perm(prefix1,prefix2,prefix3,file,type,uid,gid,mode) char *prefix1; char *prefix2; char *prefix3; char *file; int type; int uid; int gid; int mode; { struct stat st; if (stat(file,&st) == -1) { if (errno == error_noent) strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," does not exist",0); else strerr_warn4(WARNING,"unable to stat .../",file,": ",&strerr_sys); return; } if ((uid != -1) && (st.st_uid != uid)) strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong owner",0); if ((gid != -1) && (st.st_gid != gid)) strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong group",0); if ((st.st_mode & 07777) != mode) strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong permissions",0); if ((st.st_mode & S_IFMT) != type) strerr_warn6(WARNING,prefix1,prefix2,prefix3,file," has wrong type",0); } void h(home,uid,gid,mode) char *home; int uid; int gid; int mode; { perm("","","",home,S_IFDIR,uid,gid,mode); } void d(home,subdir,uid,gid,mode) char *home; char *subdir; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); perm("",home,"/",subdir,S_IFDIR,uid,gid,mode); } void p(home,fifo,uid,gid,mode) char *home; char *fifo; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); perm("",home,"/",fifo,S_IFIFO,uid,gid,mode); } void c(home,subdir,file,uid,gid,mode) char *home; char *subdir; char *file; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (chdir(subdir) == -1) strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); perm(".../",subdir,"/",file,S_IFREG,uid,gid,mode); } void z(home,file,len,uid,gid,mode) char *home; char *file; int len; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); perm("",home,"/",file,S_IFREG,uid,gid,mode); } void main() { hier(); _exit(0); } netqmail-1.06/subgetopt.30000644000076400007640000001325006541176434014753 0ustar nelsonnelson.TH subgetopt 3 .SH NAME subgetopt \- get option character from command line .SH SYNTAX .B #include char *\fBsgoptarg\fP; .br int \fBsgoptind\fP; .br int \fBsgoptpos\fP; .br int \fBsgoptdone\fP; .br int \fBsgoptproblem\fP; int \fBsgopt(\fP\fIargc,argv,opts\fR\fB)\fP; int \fIargc\fR; .br char **\fIargv\fR; .br char *\fIopts\fR; .SH DESCRIPTION .B sgopt returns the next valid command-line option character from .IR argv . Valid option characters are listed in the .I opts string. .I opts may be empty. A character in .I opts may be followed by a colon, in which case it takes an .I option argument\fR. Avoid using the characters ?, :, and \- as option characters. Below .I option argument is abbreviated as .I optarg and .I command-line argument is abbreviated as .IR cmdarg . Options are listed in cmdargs which begin with a minus sign. Several options which do not take optargs may be combined into one cmdarg. An option which takes an optarg may be handled in two ways. If it appears at the very end of a cmdarg, then the entire next cmdarg is the optarg. But if there are any characters in the cmdarg after the option character, then those characters form the optarg. The optarg is returned in .BR sgoptarg . Next time .B sgopt looks at the cmdarg which follows the optarg. If a cmdarg does not begin with a hyphen, or if it is a lone hyphen not followed by any characters, or if it begins with two hyphens, then it terminates option processing, and .B sgopt returns an appropriate code. If there are two hyphens, .B sgopt will advance attention to the next cmdarg, so it can be called again to read further options. .SH "PROPER USAGE" .B sgoptproblem should be used only when .B sgopt returns ?. .B sgoptind and .B sgoptpos are defined all the time. .B sgoptarg is defined all the time; it is null unless .B sgopt has just returned an option with optarg. .B sgopt is typically used as follows. .EX #include main(argc,argv) int argc; char **argv; { int opt; while ((opt = sgopt(argc,argv,"a:s")) != sgoptdone) .br switch(opt) { .br case 'a': .br printf("opt a with optarg %s\\n",sgoptarg); break; .br case 's': .br printf("opt s with no optarg\\n"); break; .br case '?': .br if (argv[sgoptind] && (sgoptind < argc)) .br printf("illegal opt %c\\n",sgoptproblem); .br else .br printf("missing arg, opt %c\\n",sgoptproblem); .br exit(1); .br } argv += sgoptind; .br while (*argv) printf("argument %s\\n",*argv++); .br exit(0); .br } .EE The end of the command line is marked by either .IR argc , or a null pointer in .IR argv , whichever comes first. Normally these two markers coincide, so it is redundant to test for both .I argv\fB[sgoptind] and .B sgoptind < \fIargc\fR. The above code shows both tests as an illustration. .B Multiple option sets: One useful technique is to call .B sgopt with a primary .I opts until it returns EOF, then call .B sgopt with a secondary .I opts until it returns EOF. The user can provide primary options, then a double hyphen, and then secondary options. No special handling is needed if some or all of the options are omitted. The same technique can be used for any number of option sets in series. .B Multiple command lines: Before parsing a new .BR argv , make sure to set .B sgoptind and .B sgoptpos back to 1 and 0. .SH "PARSING STAGES" .B sgopt keeps track of its position in .I argv with .B sgoptind and .BR sgoptpos , which are initialized to 1 and 0. It looks at .I argv\fB[sgoptind][sgoptpos] and following characters. .B sgopt indicates that no more options are available by returning .BR sgoptdone , which is initialized to .BR SUBGETOPTDONE , which is defined as \-1. .B sgopt begins by setting .B optarg to null. .B Ending conditions: If .I argv is null, or .B sgoptind is larger than .IR argc , or the current cmdarg .I argv\fB[sgoptind] is null, then .B sgopt returns .BR optdone . .B Stage one: If the current character is zero, .B sgopt moves to the beginning of the next cmdarg. It then checks the ending conditions again. .B Stage two: If the current position is the begining of the cmdarg, .B sgopt checks whether the current character is a minus sign. If not it returns .BR optdone . It then moves to the next character. If that character is zero, .B sgopt moves back to the beginning of the cmdarg, and returns .BR sgoptdone . If the character is a minus sign, .B sgopt moves to the beginning of the next cmdarg, and returns .BR sgoptdone . .B Stage three: .B sgopt records the current character, .IR c , and moves to the next character. There are three possibilities: (1) .I c is an option character without optarg in .IR opts , or (2) .I c is an option character with optarg in .IR opts , or (3) .I c does not appear in .IR opts . (1) If .I c appears as an option character without optarg in .IR opts , .B sgopt returns .IR c . (2) If .I c appears as an option character with optarg in .IR opts , .B sgopt sets .B sgoptarg to the current position, and moves to the next cmdarg. If .B sgoptarg is nonempty, .B sgopt returns .IR c . Then .B sgopt sets .B sgoptarg to the current cmdarg. If the current cmdarg is null, or past .IR argc , .B sgopt sets .B sgoptproblem to .I c and returns ?. Otherwise .B sgopt moves to the next argument and returns .IR c . (2) If .I c does not appear in .IR opts , .B sgopt sets .B sgoptproblem to .I c and returns ?. .SH "SYNTAX NOTE" .B sgopt is actually a macro abbreviation for .BR subgetopt . The external .B sg variables are also macros for .BR subget . These macros are defined in .BR , unless .B SUBGETOPTNOSHORT is defined when .B is included. .SH VERSION subgetopt version 0.9, 931129. .SH AUTHOR Placed into the public domain by Daniel J. Bernstein. netqmail-1.06/UPGRADE0000644000076400007640000000466010724070436013663 0ustar nelsonnelsonSAVE COPIES OF YOUR OUTGOING MAIL! Like any other piece of software (and information generally), the qmail system comes with NO WARRANTY. It's much more secure and reliable than sendmail, but that's not saying much. Here's how to upgrade to netqmail 1.05. This procedure will overwrite the old qmail binaries. Furthermore, it may begin delivering messages from the queue before you have had a chance to test it. WARNING for upgrades from 1.00 or 1.01: qlist has been split into a separate package. You can obtain it from http://pobox.com/~djb/qlist.html if you have any users who need it. WARNING for upgrades from 1.01: recipientmap is gone. The virtualdomains mechanism has been expanded to support virtual users. Before starting, compare conf* to your old conf*, and make any necessary changes. You can copy conf* from 1.02 or 1.03. How to install: 1. Compile the programs and create the formatted man pages: # make it man 2. Inform your users that mail will not be accepted for a few minutes. 3. Disable deliveries by killing your old qmail-send. Wait for it to print ``exiting'' in the log. 4. Disable SMTP service by commenting out the smtp line in inetd.conf; kill -HUP your inetd. (If you are using tcpserver, simply kill -STOP your tcpserver. If you are running a QMTP server, disable that too.) Wait for current qmail-smtpd processes to die. 5. Install the new binaries and man pages: # make setup check 6. If your boot scripts are using qmail-start instead of /var/qmail/rc: Copy /var/qmail/boot/home to /var/qmail/rc. (Use home+df instead if you have installed dot-forward; use proc or proc+df if you are using procmail by default for local deliveries.) Compare /var/qmail/rc to your qmail-start boot line, and edit /var/qmail/rc if necessary. Replace your qmail-start boot line with csh -cf '/var/qmail/rc &' 7. Reenable deliveries: # csh -cf '/var/qmail/rc &' 8. Read TEST.deliver. 9. Reenable SMTP service by restoring the smtp line in inetd.conf; kill -HUP your inetd. (If you are using tcpserver, simply kill -CONT your tcpserver. If you are running a QMTP server, reenable that too.) 10. Read TEST.receive. That's it! To report success: % ( echo 'First M. Last'; cat `cat SYSDEPS` ) | mail djb-qst@cr.yp.to Replace First M. Last with your name. If you have questions about qmail, join the qmail mailing list; see http://pobox.com/~djb/qmail.html. netqmail-1.06/error_temp.c0000644000076400007640000000177206541176434015203 0ustar nelsonnelson#include #include "error.h" #define X(n) if (e == n) return 1; int error_temp(e) int e; { X(error_intr) X(error_nomem) X(error_txtbsy) X(error_io) X(error_timeout) X(error_wouldblock) X(error_again) #ifdef EDEADLK X(EDEADLK) #endif #ifdef EBUSY X(EBUSY) #endif #ifdef ENFILE X(ENFILE) #endif #ifdef EMFILE X(EMFILE) #endif #ifdef EFBIG X(EFBIG) #endif #ifdef ENOSPC X(ENOSPC) #endif #ifdef ENETDOWN X(ENETDOWN) #endif #ifdef ENETUNREACH X(ENETUNREACH) #endif #ifdef ENETRESET X(ENETRESET) #endif #ifdef ECONNABORTED X(ECONNABORTED) #endif #ifdef ECONNRESET X(ECONNRESET) #endif #ifdef ENOBUFS X(ENOBUFS) #endif #ifdef ETOOMANYREFS X(ETOOMANYREFS) #endif #ifdef ECONNREFUSED X(ECONNREFUSED) #endif #ifdef EHOSTDOWN X(EHOSTDOWN) #endif #ifdef EHOSTUNREACH X(EHOSTUNREACH) #endif #ifdef EPROCLIM X(EPROCLIM) #endif #ifdef EUSERS X(EUSERS) #endif #ifdef EDQUOT X(EDQUOT) #endif #ifdef ESTALE X(ESTALE) #endif #ifdef ENOLCK X(ENOLCK) #endif return 0; } netqmail-1.06/config-fast.sh0000644000076400007640000000171506541176434015412 0ustar nelsonnelsonfqdn="$1" echo Your fully qualified host name is "$fqdn". echo Putting "$fqdn" into control/me... echo "$fqdn" > QMAIL/control/me chmod 644 QMAIL/control/me ( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | ( read ddom echo Putting "$ddom" into control/defaultdomain... echo "$ddom" > QMAIL/control/defaultdomain chmod 644 QMAIL/control/defaultdomain ) ) ( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | ( read pdom echo Putting "$pdom" into control/plusdomain... echo "$pdom" > QMAIL/control/plusdomain chmod 644 QMAIL/control/plusdomain ) ) echo Putting "$fqdn" into control/locals... echo "$fqdn" >> QMAIL/control/locals chmod 644 QMAIL/control/locals echo Putting "$fqdn" into control/rcpthosts... echo "$fqdn" >> QMAIL/control/rcpthosts chmod 644 QMAIL/control/rcpthosts echo "Now qmail will refuse to accept SMTP messages except to $fqdn." echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!' netqmail-1.06/error_str.c0000644000076400007640000001266706541176434015053 0ustar nelsonnelson#include #include "error.h" #define X(e,s) if (i == e) return s; char *error_str(i) int i; { X(0,"no error") X(error_intr,"interrupted system call") X(error_nomem,"out of memory") X(error_noent,"file does not exist") X(error_txtbsy,"text busy") X(error_io,"input/output error") X(error_exist,"file already exists") X(error_timeout,"timed out") X(error_inprogress,"operation in progress") X(error_again,"temporary failure") X(error_wouldblock,"input/output would block") X(error_pipe,"broken pipe") X(error_perm,"permission denied") X(error_acces,"access denied") #ifdef ESRCH X(ESRCH,"no such process") #endif #ifdef ENXIO X(ENXIO,"device not configured") #endif #ifdef E2BIG X(E2BIG,"argument list too long") #endif #ifdef ENOEXEC X(ENOEXEC,"exec format error") #endif #ifdef EBADF X(EBADF,"file descriptor not open") #endif #ifdef ECHILD X(ECHILD,"no child processes") #endif #ifdef EDEADLK X(EDEADLK,"operation would cause deadlock") #endif #ifdef EFAULT X(EFAULT,"bad address") #endif #ifdef ENOTBLK X(ENOTBLK,"not a block device") #endif #ifdef EBUSY X(EBUSY,"device busy") #endif #ifdef EXDEV X(EXDEV,"cross-device link") #endif #ifdef ENODEV X(ENODEV,"device does not support operation") #endif #ifdef ENOTDIR X(ENOTDIR,"not a directory") #endif #ifdef EISDIR X(EISDIR,"is a directory") #endif #ifdef EINVAL X(EINVAL,"invalid argument") #endif #ifdef ENFILE X(ENFILE,"system cannot open more files") #endif #ifdef EMFILE X(EMFILE,"process cannot open more files") #endif #ifdef ENOTTY X(ENOTTY,"not a tty") #endif #ifdef EFBIG X(EFBIG,"file too big") #endif #ifdef ENOSPC X(ENOSPC,"out of disk space") #endif #ifdef ESPIPE X(ESPIPE,"unseekable descriptor") #endif #ifdef EROFS X(EROFS,"read-only file system") #endif #ifdef EMLINK X(EMLINK,"too many links") #endif #ifdef EDOM X(EDOM,"input out of range") #endif #ifdef ERANGE X(ERANGE,"output out of range") #endif #ifdef EALREADY X(EALREADY,"operation already in progress") #endif #ifdef ENOTSOCK X(ENOTSOCK,"not a socket") #endif #ifdef EDESTADDRREQ X(EDESTADDRREQ,"destination address required") #endif #ifdef EMSGSIZE X(EMSGSIZE,"message too long") #endif #ifdef EPROTOTYPE X(EPROTOTYPE,"incorrect protocol type") #endif #ifdef ENOPROTOOPT X(ENOPROTOOPT,"protocol not available") #endif #ifdef EPROTONOSUPPORT X(EPROTONOSUPPORT,"protocol not supported") #endif #ifdef ESOCKTNOSUPPORT X(ESOCKTNOSUPPORT,"socket type not supported") #endif #ifdef EOPNOTSUPP X(EOPNOTSUPP,"operation not supported") #endif #ifdef EPFNOSUPPORT X(EPFNOSUPPORT,"protocol family not supported") #endif #ifdef EAFNOSUPPORT X(EAFNOSUPPORT,"address family not supported") #endif #ifdef EADDRINUSE X(EADDRINUSE,"address already used") #endif #ifdef EADDRNOTAVAIL X(EADDRNOTAVAIL,"address not available") #endif #ifdef ENETDOWN X(ENETDOWN,"network down") #endif #ifdef ENETUNREACH X(ENETUNREACH,"network unreachable") #endif #ifdef ENETRESET X(ENETRESET,"network reset") #endif #ifdef ECONNABORTED X(ECONNABORTED,"connection aborted") #endif #ifdef ECONNRESET X(ECONNRESET,"connection reset") #endif #ifdef ENOBUFS X(ENOBUFS,"out of buffer space") #endif #ifdef EISCONN X(EISCONN,"already connected") #endif #ifdef ENOTCONN X(ENOTCONN,"not connected") #endif #ifdef ESHUTDOWN X(ESHUTDOWN,"socket shut down") #endif #ifdef ETOOMANYREFS X(ETOOMANYREFS,"too many references") #endif #ifdef ECONNREFUSED X(ECONNREFUSED,"connection refused") #endif #ifdef ELOOP X(ELOOP,"symbolic link loop") #endif #ifdef ENAMETOOLONG X(ENAMETOOLONG,"file name too long") #endif #ifdef EHOSTDOWN X(EHOSTDOWN,"host down") #endif #ifdef EHOSTUNREACH X(EHOSTUNREACH,"host unreachable") #endif #ifdef ENOTEMPTY X(ENOTEMPTY,"directory not empty") #endif #ifdef EPROCLIM X(EPROCLIM,"too many processes") #endif #ifdef EUSERS X(EUSERS,"too many users") #endif #ifdef EDQUOT X(EDQUOT,"disk quota exceeded") #endif #ifdef ESTALE X(ESTALE,"stale NFS file handle") #endif #ifdef EREMOTE X(EREMOTE,"too many levels of remote in path") #endif #ifdef EBADRPC X(EBADRPC,"RPC structure is bad") #endif #ifdef ERPCMISMATCH X(ERPCMISMATCH,"RPC version mismatch") #endif #ifdef EPROGUNAVAIL X(EPROGUNAVAIL,"RPC program unavailable") #endif #ifdef EPROGMISMATCH X(EPROGMISMATCH,"program version mismatch") #endif #ifdef EPROCUNAVAIL X(EPROCUNAVAIL,"bad procedure for program") #endif #ifdef ENOLCK X(ENOLCK,"no locks available") #endif #ifdef ENOSYS X(ENOSYS,"system call not available") #endif #ifdef EFTYPE X(EFTYPE,"bad file type") #endif #ifdef EAUTH X(EAUTH,"authentication error") #endif #ifdef ENEEDAUTH X(ENEEDAUTH,"not authenticated") #endif #ifdef ENOSTR X(ENOSTR,"not a stream device") #endif #ifdef ETIME X(ETIME,"timer expired") #endif #ifdef ENOSR X(ENOSR,"out of stream resources") #endif #ifdef ENOMSG X(ENOMSG,"no message of desired type") #endif #ifdef EBADMSG X(EBADMSG,"bad message type") #endif #ifdef EIDRM X(EIDRM,"identifier removed") #endif #ifdef ENONET X(ENONET,"machine not on network") #endif #ifdef ERREMOTE X(ERREMOTE,"object not local") #endif #ifdef ENOLINK X(ENOLINK,"link severed") #endif #ifdef EADV X(EADV,"advertise error") #endif #ifdef ESRMNT X(ESRMNT,"srmount error") #endif #ifdef ECOMM X(ECOMM,"communication error") #endif #ifdef EPROTO X(EPROTO,"protocol error") #endif #ifdef EMULTIHOP X(EMULTIHOP,"multihop attempted") #endif #ifdef EREMCHG X(EREMCHG,"remote address changed") #endif return "unknown error"; } netqmail-1.06/PIC.local2rem0000644000076400007640000000236106541176434015071 0ustar nelsonnelson Original message: To: bill@irs.gov Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to bill@irs.gov | From: joe@heaven.af.mil | To: bill@irs.gov | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, bill@irs.gov. | Is irs.gov in locals? No. | Is bill@irs.gov in virtualdomains? No. | Is irs.gov in virtualdomains? No. | Is .gov in virtualdomains? No. | Deliver remotely to bill@irs.gov. V qmail-rspawn Run qmail-remote. | V qmail-remote Look at host name, irs.gov. Is irs.gov listed in smtproutes? No. Look up DNS MX/A for irs.gov and connect to it by SMTP: MAIL FROM: RCPT TO: netqmail-1.06/slurpclose.c0000644000076400007640000000062406541176434015213 0ustar nelsonnelson#include "stralloc.h" #include "readwrite.h" #include "slurpclose.h" #include "error.h" int slurpclose(fd,sa,bufsize) int fd; stralloc *sa; int bufsize; { int r; for (;;) { if (!stralloc_readyplus(sa,bufsize)) { close(fd); return -1; } r = read(fd,sa->s + sa->len,bufsize); if (r == -1) if (errno == error_intr) continue; if (r <= 0) { close(fd); return r; } sa->len += r; } } netqmail-1.06/envelopes.50000644000076400007640000001135706541176434014747 0ustar nelsonnelson.TH envelopes 5 .SH "NAME" envelopes \- sender/recipient lists attached to messages .SH "INTRODUCTION" Electronic mail messages are delivered in .IR envelopes . An envelope lists a .I sender and one or more .IR recipients . Usually these envelope addresses are the same as the addresses listed in the message header: .EX (envelope) from djb to root .br From: djb .br To: root .EE In more complicated situations, though, the envelope addresses may differ from the header addresses. .SH "ENVELOPE EXAMPLES" When a message is delivered to several people at different locations, it is first photocopied and placed into several envelopes: .EX (envelope) from djb to root .br From: djb Copy #1 of message .br To: root, god@brl.mil .EE .EX (envelope) from djb to god@brl.mil .br From: djb Copy #2 of message .br To: root, god@brl.mil .EE When a message is delivered to several people at the same location, the sender doesn't have to photocopy it. He can instead stuff it into one envelope with several addresses; the recipients will make the photocopy: .EX (envelope) from djb to god@brl.mil, angel@brl.mil .br From: djb .br To: god@brl.mil, angel@brl.mil, joe, frde .EE Bounced mail is sent back to the envelope sender address. The bounced mail doesn't list an envelope sender, so bounce loops are impossible: .EX (envelope) from <> to djb .br From: MAILER-DAEMON .br To: djb .br Subject: unknown user frde .EE The recipient of a message may make another copy and forward it in a new envelope: .EX (envelope) from djb to joe .br From: djb Original message .br To: joe .EE .EX (envelope) from joe to fred .br From: djb Forwarded message .br To: joe .EE A mailing list works almost the same way: .EX (envelope) from djb to sos-list .br From: djb Original message .br To: sos-list .EE .EX (envelope) from sos-owner to god@brl.mil .br From: djb Forwarded message .br To: sos-list to recipient #1 .EE .EX (envelope) from sos-owner to frde .br From: djb Forwarded message .br To: sos-list to recipient #2 .EE Notice that the mailing list is set up to replace the envelope sender with something new, .BR sos-owner . So bounces will come back to .BR sos-owner : .EX (envelope) from <> to sos-owner .br From: MAILER-DAEMON .br To: sos-owner .br Subject: unknown user frde .EE It's a good idea to set up an extra address, .BR sos-owner , like this: the original envelope sender (\fBdjb\fP) has no way to fix bad .B sos-list addresses, and of course bounces must not be sent to .B sos-list itself. .SH "HOW ENVELOPE ADDRESSES ARE STORED" Envelope sender and envelope recipient addresses are transmitted and recorded in several ways. When a user injects mail through .BR qmail-inject , he can supply a .B Return-Path line or a .B \-f option for the envelope sender; by default the envelope sender is his login name. The envelope recipient addresses can be taken from the command line or from various header fields, depending on the options to .BR qmail-inject . Similar comments apply to .BR sendmail . When a message is transferred from one machine to another through SMTP, the envelope sender is given in a .B MAIL FROM command, the envelope recipients are given in .B RCPT TO commands, and the message is supplied separately by a .B DATA command. When a message is delivered by .B qmail to a single local recipient, .B qmail-local records the recipient in .B Delivered-To and the envelope sender in .BR Return-Path . It uses .B Delivered-To to detect mail forwarding loops. .B sendmail normally records the envelope sender in .BR Return-Path . It does not record envelope recipient addresses, on the theory that they are redundant: you received the mail, so you must have been one of the envelope recipients. Note that, if the header doesn't have any recipient addresses, .B sendmail will move envelope recipient addresses back into the header. This situation occurs if all addresses were originally listed as .BR Bcc , since .B Bcc is automatically removed. When .B sendmail sees this, it creates a new .B Apparently-To header field with the envelope recipient addresses. This has the strange effect that each blind-carbon-copy recipient will see a list of all recipients on the same machine. When a message is stored in .B mbox format, the envelope sender is recorded at the top of the message as a UUCP-style .B From (no colon) line. Note that this line is less reliable than the .B Return-Path line added by .B qmail-local or .B sendmail\fP. .SH "SEE ALSO" qmail-header(5), qmail-local(8), qmail-inject(8) netqmail-1.06/fmtqfn.h0000644000076400007640000000021706541176434014316 0ustar nelsonnelson#ifndef FMTQFN_H #define FMTQFN_H extern unsigned int fmtqfn(); #define FMTQFN 40 /* maximum space needed, if len(dirslash) <= 10 */ #endif netqmail-1.06/conf-spawn0000644000076400007640000000025006541176434014645 0ustar nelsonnelson120 This is a silent concurrency limit. You can't set it above 255. On some systems you can't set it above 125. qmail will refuse to compile if the limit is too high. netqmail-1.06/qmail-local.c0000644000076400007640000004307610724070436015214 0ustar nelsonnelson#include #include #include "readwrite.h" #include "sig.h" #include "env.h" #include "byte.h" #include "exit.h" #include "fork.h" #include "open.h" #include "wait.h" #include "lock.h" #include "seek.h" #include "substdio.h" #include "getln.h" #include "strerr.h" #include "subfd.h" #include "sgetopt.h" #include "alloc.h" #include "error.h" #include "stralloc.h" #include "fmt.h" #include "str.h" #include "now.h" #include "case.h" #include "quote.h" #include "qmail.h" #include "slurpclose.h" #include "myctime.h" #include "gfrom.h" #include "auto_patrn.h" void usage() { strerr_die1x(100,"qmail-local: usage: qmail-local [ -nN ] user homedir local dash ext domain sender aliasempty"); } void temp_nomem() { strerr_die1x(111,"Out of memory. (#4.3.0)"); } void temp_rewind() { strerr_die1x(111,"Unable to rewind message. (#4.3.0)"); } void temp_childcrashed() { strerr_die1x(111,"Aack, child crashed. (#4.3.0)"); } void temp_fork() { strerr_die3x(111,"Unable to fork: ",error_str(errno),". (#4.3.0)"); } void temp_read() { strerr_die3x(111,"Unable to read message: ",error_str(errno),". (#4.3.0)"); } void temp_slowlock() { strerr_die1x(111,"File has been locked for 30 seconds straight. (#4.3.0)"); } void temp_qmail(fn) char *fn; { strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.3.0)"); } int flagdoit; int flag99; char *user; char *homedir; char *local; char *dash; char *ext; char *host; char *sender; char *aliasempty; stralloc safeext = {0}; stralloc ufline = {0}; stralloc rpline = {0}; stralloc envrecip = {0}; stralloc dtline = {0}; stralloc qme = {0}; stralloc ueo = {0}; stralloc cmds = {0}; stralloc messline = {0}; stralloc foo = {0}; char buf[1024]; char outbuf[1024]; /* child process */ char fntmptph[80 + FMT_ULONG * 2]; char fnnewtph[80 + FMT_ULONG * 2]; void tryunlinktmp() { unlink(fntmptph); } void sigalrm() { tryunlinktmp(); _exit(3); } void maildir_child(dir) char *dir; { unsigned long pid; unsigned long time; char host[64]; char *s; int loop; struct stat st; int fd; substdio ss; substdio ssout; sig_alarmcatch(sigalrm); if (chdir(dir) == -1) { if (error_temp(errno)) _exit(1); _exit(2); } pid = getpid(); host[0] = 0; gethostname(host,sizeof(host)); for (loop = 0;;++loop) { time = now(); s = fntmptph; s += fmt_str(s,"tmp/"); s += fmt_ulong(s,time); *s++ = '.'; s += fmt_ulong(s,pid); *s++ = '.'; s += fmt_strn(s,host,sizeof(host)); *s++ = 0; if (stat(fntmptph,&st) == -1) if (errno == error_noent) break; /* really should never get to this point */ if (loop == 2) _exit(1); sleep(2); } str_copy(fnnewtph,fntmptph); byte_copy(fnnewtph,3,"new"); alarm(86400); fd = open_excl(fntmptph); if (fd == -1) _exit(1); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); if (substdio_put(&ssout,rpline.s,rpline.len) == -1) goto fail; if (substdio_put(&ssout,dtline.s,dtline.len) == -1) goto fail; switch(substdio_copy(&ssout,&ss)) { case -2: tryunlinktmp(); _exit(4); case -3: goto fail; } if (substdio_flush(&ssout) == -1) goto fail; if (fsync(fd) == -1) goto fail; if (close(fd) == -1) goto fail; /* NFS dorks */ if (link(fntmptph,fnnewtph) == -1) goto fail; /* if it was error_exist, almost certainly successful; i hate NFS */ tryunlinktmp(); _exit(0); fail: tryunlinktmp(); _exit(1); } /* end child process */ void maildir(fn) char *fn; { int child; int wstat; if (seek_begin(0) == -1) temp_rewind(); switch(child = fork()) { case -1: temp_fork(); case 0: maildir_child(fn); _exit(111); } wait_pid(&wstat,child); if (wait_crashed(wstat)) temp_childcrashed(); switch(wait_exitcode(wstat)) { case 0: break; case 2: strerr_die1x(111,"Unable to chdir to maildir. (#4.2.1)"); case 3: strerr_die1x(111,"Timeout on maildir delivery. (#4.3.0)"); case 4: strerr_die1x(111,"Unable to read message. (#4.3.0)"); default: strerr_die1x(111,"Temporary error on maildir delivery. (#4.3.0)"); } } void mailfile(fn) char *fn; { int fd; substdio ss; substdio ssout; int match; seek_pos pos; int flaglocked; if (seek_begin(0) == -1) temp_rewind(); fd = open_append(fn); if (fd == -1) strerr_die5x(111,"Unable to open ",fn,": ",error_str(errno),". (#4.2.1)"); sig_alarmcatch(temp_slowlock); alarm(30); flaglocked = (lock_ex(fd) != -1); alarm(0); sig_alarmdefault(); seek_end(fd); pos = seek_cur(fd); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); substdio_fdbuf(&ssout,write,fd,outbuf,sizeof(outbuf)); if (substdio_put(&ssout,ufline.s,ufline.len)) goto writeerrs; if (substdio_put(&ssout,rpline.s,rpline.len)) goto writeerrs; if (substdio_put(&ssout,dtline.s,dtline.len)) goto writeerrs; for (;;) { if (getln(&ss,&messline,&match,'\n') != 0) { strerr_warn3("Unable to read message: ",error_str(errno),". (#4.3.0)",0); if (flaglocked) seek_trunc(fd,pos); close(fd); _exit(111); } if (!match && !messline.len) break; if (gfrom(messline.s,messline.len)) if (substdio_bput(&ssout,">",1)) goto writeerrs; if (substdio_bput(&ssout,messline.s,messline.len)) goto writeerrs; if (!match) { if (substdio_bputs(&ssout,"\n")) goto writeerrs; break; } } if (substdio_bputs(&ssout,"\n")) goto writeerrs; if (substdio_flush(&ssout)) goto writeerrs; if (fsync(fd) == -1) goto writeerrs; close(fd); return; writeerrs: strerr_warn5("Unable to write ",fn,": ",error_str(errno),". (#4.3.0)",0); if (flaglocked) seek_trunc(fd,pos); close(fd); _exit(111); } void mailprogram(prog) char *prog; { int child; char *(args[4]); int wstat; if (seek_begin(0) == -1) temp_rewind(); switch(child = fork()) { case -1: temp_fork(); case 0: args[0] = "/bin/sh"; args[1] = "-c"; args[2] = prog; args[3] = 0; sig_pipedefault(); execv(*args,args); strerr_die3x(111,"Unable to run /bin/sh: ",error_str(errno),". (#4.3.0)"); } wait_pid(&wstat,child); if (wait_crashed(wstat)) temp_childcrashed(); switch(wait_exitcode(wstat)) { case 100: case 64: case 65: case 70: case 76: case 77: case 78: case 112: _exit(100); case 0: break; case 99: flag99 = 1; break; default: _exit(111); } } unsigned long mailforward_qp = 0; void mailforward(recips) char **recips; { struct qmail qqt; char *qqx; substdio ss; int match; if (seek_begin(0) == -1) temp_rewind(); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); if (qmail_open(&qqt) == -1) temp_fork(); mailforward_qp = qmail_qp(&qqt); qmail_put(&qqt,dtline.s,dtline.len); do { if (getln(&ss,&messline,&match,'\n') != 0) { qmail_fail(&qqt); break; } qmail_put(&qqt,messline.s,messline.len); } while (match); qmail_from(&qqt,ueo.s); while (*recips) qmail_to(&qqt,*recips++); qqx = qmail_close(&qqt); if (!*qqx) return; strerr_die3x(*qqx == 'D' ? 100 : 111,"Unable to forward message: ",qqx + 1,"."); } void bouncexf() { int match; substdio ss; if (seek_begin(0) == -1) temp_rewind(); substdio_fdbuf(&ss,read,0,buf,sizeof(buf)); for (;;) { if (getln(&ss,&messline,&match,'\n') != 0) temp_read(); if (!match) break; if (messline.len <= 1) break; if (messline.len == dtline.len) if (!str_diffn(messline.s,dtline.s,dtline.len)) strerr_die1x(100,"This message is looping: it already has my Delivered-To line. (#5.4.6)"); } } void checkhome() { struct stat st; if (stat(".",&st) == -1) strerr_die3x(111,"Unable to stat home directory: ",error_str(errno),". (#4.3.0)"); if (st.st_mode & auto_patrn) strerr_die1x(111,"Uh-oh: home directory is writable. (#4.7.0)"); if (st.st_mode & 01000) if (flagdoit) strerr_die1x(111,"Home directory is sticky: user is editing his .qmail file. (#4.2.1)"); else strerr_warn1("Warning: home directory is sticky.",0); } int qmeox(dashowner) char *dashowner; { struct stat st; if (!stralloc_copys(&qme,".qmail")) temp_nomem(); if (!stralloc_cats(&qme,dash)) temp_nomem(); if (!stralloc_cat(&qme,&safeext)) temp_nomem(); if (!stralloc_cats(&qme,dashowner)) temp_nomem(); if (!stralloc_0(&qme)) temp_nomem(); if (stat(qme.s,&st) == -1) { if (error_temp(errno)) temp_qmail(qme.s); return -1; } return 0; } int qmeexists(fd,cutable) int *fd; int *cutable; { struct stat st; if (!stralloc_0(&qme)) temp_nomem(); *fd = open_read(qme.s); if (*fd == -1) { if (error_temp(errno)) temp_qmail(qme.s); if (errno == error_perm) temp_qmail(qme.s); if (errno == error_acces) temp_qmail(qme.s); return 0; } if (fstat(*fd,&st) == -1) temp_qmail(qme.s); if ((st.st_mode & S_IFMT) == S_IFREG) { if (st.st_mode & auto_patrn) strerr_die1x(111,"Uh-oh: .qmail file is writable. (#4.7.0)"); *cutable = !!(st.st_mode & 0100); return 1; } close(*fd); return 0; } /* "" "": "" */ /* "-/" "": "-/" "-/default" */ /* "-/" "a": "-/a" "-/default" */ /* "-/" "a-": "-/a-" "-/a-default" "-/default" */ /* "-/" "a-b": "-/a-b" "-/a-default" "-/default" */ /* "-/" "a-b-": "-/a-b-" "-/a-b-default" "-/a-default" "-/default" */ /* "-/" "a-b-c": "-/a-b-c" "-/a-b-default" "-/a-default" "-/default" */ void qmesearch(fd,cutable) int *fd; int *cutable; { int i; if (!stralloc_copys(&qme,".qmail")) temp_nomem(); if (!stralloc_cats(&qme,dash)) temp_nomem(); if (!stralloc_cat(&qme,&safeext)) temp_nomem(); if (qmeexists(fd,cutable)) { if (safeext.len >= 7) { i = safeext.len - 7; if (!byte_diff("default",7,safeext.s + i)) if (i <= str_len(ext)) /* paranoia */ if (!env_put2("DEFAULT",ext + i)) temp_nomem(); } return; } for (i = safeext.len;i >= 0;--i) if (!i || (safeext.s[i - 1] == '-')) { if (!stralloc_copys(&qme,".qmail")) temp_nomem(); if (!stralloc_cats(&qme,dash)) temp_nomem(); if (!stralloc_catb(&qme,safeext.s,i)) temp_nomem(); if (!stralloc_cats(&qme,"default")) temp_nomem(); if (qmeexists(fd,cutable)) { if (i <= str_len(ext)) /* paranoia */ if (!env_put2("DEFAULT",ext + i)) temp_nomem(); return; } } *fd = -1; } unsigned long count_file = 0; unsigned long count_forward = 0; unsigned long count_program = 0; char count_buf[FMT_ULONG]; void count_print() { substdio_puts(subfdoutsmall,"did "); substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_file)); substdio_puts(subfdoutsmall,"+"); substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_forward)); substdio_puts(subfdoutsmall,"+"); substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,count_program)); substdio_puts(subfdoutsmall,"\n"); if (mailforward_qp) { substdio_puts(subfdoutsmall,"qp "); substdio_put(subfdoutsmall,count_buf,fmt_ulong(count_buf,mailforward_qp)); substdio_puts(subfdoutsmall,"\n"); } substdio_flush(subfdoutsmall); } void sayit(type,cmd,len) char *type; char *cmd; int len; { substdio_puts(subfdoutsmall,type); substdio_put(subfdoutsmall,cmd,len); substdio_putsflush(subfdoutsmall,"\n"); } void main(argc,argv) int argc; char **argv; { int opt; int i; int j; int k; int fd; int numforward; char **recips; datetime_sec starttime; int flagforwardonly; char *x; umask(077); sig_pipeignore(); if (!env_init()) temp_nomem(); flagdoit = 1; while ((opt = getopt(argc,argv,"nN")) != opteof) switch(opt) { case 'n': flagdoit = 0; break; case 'N': flagdoit = 1; break; default: usage(); } argc -= optind; argv += optind; if (!(user = *argv++)) usage(); if (!(homedir = *argv++)) usage(); if (!(local = *argv++)) usage(); if (!(dash = *argv++)) usage(); if (!(ext = *argv++)) usage(); if (!(host = *argv++)) usage(); if (!(sender = *argv++)) usage(); if (!(aliasempty = *argv++)) usage(); if (*argv) usage(); if (homedir[0] != '/') usage(); if (chdir(homedir) == -1) strerr_die5x(111,"Unable to switch to ",homedir,": ",error_str(errno),". (#4.3.0)"); checkhome(); if (!env_put2("HOST",host)) temp_nomem(); if (!env_put2("HOME",homedir)) temp_nomem(); if (!env_put2("USER",user)) temp_nomem(); if (!env_put2("LOCAL",local)) temp_nomem(); if (!stralloc_copys(&envrecip,local)) temp_nomem(); if (!stralloc_cats(&envrecip,"@")) temp_nomem(); if (!stralloc_cats(&envrecip,host)) temp_nomem(); if (!stralloc_copy(&foo,&envrecip)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("RECIPIENT",foo.s)) temp_nomem(); if (!stralloc_copys(&dtline,"Delivered-To: ")) temp_nomem(); if (!stralloc_cat(&dtline,&envrecip)) temp_nomem(); for (i = 0;i < dtline.len;++i) if (dtline.s[i] == '\n') dtline.s[i] = '_'; if (!stralloc_cats(&dtline,"\n")) temp_nomem(); if (!stralloc_copy(&foo,&dtline)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("DTLINE",foo.s)) temp_nomem(); if (flagdoit) bouncexf(); if (!env_put2("SENDER",sender)) temp_nomem(); if (!quote2(&foo,sender)) temp_nomem(); if (!stralloc_copys(&rpline,"Return-Path: <")) temp_nomem(); if (!stralloc_cat(&rpline,&foo)) temp_nomem(); for (i = 0;i < rpline.len;++i) if (rpline.s[i] == '\n') rpline.s[i] = '_'; if (!stralloc_cats(&rpline,">\n")) temp_nomem(); if (!stralloc_copy(&foo,&rpline)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("RPLINE",foo.s)) temp_nomem(); if (!stralloc_copys(&ufline,"From ")) temp_nomem(); if (*sender) { int len; int i; char ch; len = str_len(sender); if (!stralloc_readyplus(&ufline,len)) temp_nomem(); for (i = 0;i < len;++i) { ch = sender[i]; if ((ch == ' ') || (ch == '\t') || (ch == '\n')) ch = '-'; ufline.s[ufline.len + i] = ch; } ufline.len += len; } else if (!stralloc_cats(&ufline,"MAILER-DAEMON")) temp_nomem(); if (!stralloc_cats(&ufline," ")) temp_nomem(); starttime = now(); if (!stralloc_cats(&ufline,myctime(starttime))) temp_nomem(); if (!stralloc_copy(&foo,&ufline)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("UFLINE",foo.s)) temp_nomem(); x = ext; if (!env_put2("EXT",x)) temp_nomem(); x += str_chr(x,'-'); if (*x) ++x; if (!env_put2("EXT2",x)) temp_nomem(); x += str_chr(x,'-'); if (*x) ++x; if (!env_put2("EXT3",x)) temp_nomem(); x += str_chr(x,'-'); if (*x) ++x; if (!env_put2("EXT4",x)) temp_nomem(); if (!stralloc_copys(&safeext,ext)) temp_nomem(); case_lowerb(safeext.s,safeext.len); for (i = 0;i < safeext.len;++i) if (safeext.s[i] == '.') safeext.s[i] = ':'; i = str_len(host); i = byte_rchr(host,i,'.'); if (!stralloc_copyb(&foo,host,i)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("HOST2",foo.s)) temp_nomem(); i = byte_rchr(host,i,'.'); if (!stralloc_copyb(&foo,host,i)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("HOST3",foo.s)) temp_nomem(); i = byte_rchr(host,i,'.'); if (!stralloc_copyb(&foo,host,i)) temp_nomem(); if (!stralloc_0(&foo)) temp_nomem(); if (!env_put2("HOST4",foo.s)) temp_nomem(); flagforwardonly = 0; qmesearch(&fd,&flagforwardonly); if (fd == -1) if (*dash) strerr_die1x(100,"Sorry, no mailbox here by that name. (#5.1.1)"); if (!stralloc_copys(&ueo,sender)) temp_nomem(); if (str_diff(sender,"")) if (str_diff(sender,"#@[]")) if (qmeox("-owner") == 0) { if (qmeox("-owner-default") == 0) { if (!stralloc_copys(&ueo,local)) temp_nomem(); if (!stralloc_cats(&ueo,"-owner-@")) temp_nomem(); if (!stralloc_cats(&ueo,host)) temp_nomem(); if (!stralloc_cats(&ueo,"-@[]")) temp_nomem(); } else { if (!stralloc_copys(&ueo,local)) temp_nomem(); if (!stralloc_cats(&ueo,"-owner@")) temp_nomem(); if (!stralloc_cats(&ueo,host)) temp_nomem(); } } if (!stralloc_0(&ueo)) temp_nomem(); if (!env_put2("NEWSENDER",ueo.s)) temp_nomem(); if (!stralloc_ready(&cmds,0)) temp_nomem(); cmds.len = 0; if (fd != -1) if (slurpclose(fd,&cmds,256) == -1) temp_nomem(); if (!cmds.len) { if (!stralloc_copys(&cmds,aliasempty)) temp_nomem(); flagforwardonly = 0; } if (!cmds.len || (cmds.s[cmds.len - 1] != '\n')) if (!stralloc_cats(&cmds,"\n")) temp_nomem(); numforward = 0; i = 0; for (j = 0;j < cmds.len;++j) if (cmds.s[j] == '\n') { switch(cmds.s[i]) { case '#': case '.': case '/': case '|': break; default: ++numforward; } i = j + 1; } recips = (char **) alloc((numforward + 1) * sizeof(char *)); if (!recips) temp_nomem(); numforward = 0; flag99 = 0; i = 0; for (j = 0;j < cmds.len;++j) if (cmds.s[j] == '\n') { cmds.s[j] = 0; k = j; while ((k > i) && ((cmds.s[k - 1] == ' ') || (cmds.s[k - 1] == '\t'))) cmds.s[--k] = 0; switch(cmds.s[i]) { case 0: /* k == i */ if (i) break; strerr_die1x(111,"Uh-oh: first line of .qmail file is blank. (#4.2.1)"); case '#': break; case '.': case '/': ++count_file; if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has file delivery but has x bit set. (#4.7.0)"); if (cmds.s[k - 1] == '/') if (flagdoit) maildir(cmds.s + i); else sayit("maildir ",cmds.s + i,k - i); else if (flagdoit) mailfile(cmds.s + i); else sayit("mbox ",cmds.s + i,k - i); break; case '|': ++count_program; if (flagforwardonly) strerr_die1x(111,"Uh-oh: .qmail has prog delivery but has x bit set. (#4.7.0)"); if (flagdoit) mailprogram(cmds.s + i + 1); else sayit("program ",cmds.s + i + 1,k - i - 1); break; case '+': if (str_equal(cmds.s + i + 1,"list")) flagforwardonly = 1; break; case '&': ++i; default: ++count_forward; if (flagdoit) recips[numforward++] = cmds.s + i; else sayit("forward ",cmds.s + i,k - i); break; } i = j + 1; if (flag99) break; } if (numforward) if (flagdoit) { recips[numforward] = 0; mailforward(recips); } count_print(); _exit(0); } netqmail-1.06/ip.h0000644000076400007640000000030406541176434013430 0ustar nelsonnelson#ifndef IP_H #define IP_H struct ip_address { unsigned char d[4]; } ; extern unsigned int ip_fmt(); #define IPFMT 19 extern unsigned int ip_scan(); extern unsigned int ip_scanbracket(); #endif netqmail-1.06/auto-uid.c0000644000076400007640000000174506541176434014554 0ustar nelsonnelson#include #include #include "subfd.h" #include "substdio.h" #include "readwrite.h" #include "exit.h" #include "scan.h" #include "fmt.h" char buf1[256]; substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); void outs(s) /* was named puts, but Solaris pwd.h includes stdio.h. dorks. */ char *s; { if (substdio_puts(&ss1,s) == -1) _exit(111); } void main(argc,argv) int argc; char **argv; { char *name; char *value; struct passwd *pw; char strnum[FMT_ULONG]; name = argv[1]; if (!name) _exit(100); value = argv[2]; if (!value) _exit(100); pw = getpwnam(value); if (!pw) { substdio_puts(subfderr,"fatal: unable to find user "); substdio_puts(subfderr,value); substdio_puts(subfderr,"\n"); substdio_flush(subfderr); _exit(111); } strnum[fmt_ulong(strnum,(unsigned long) pw->pw_uid)] = 0; outs("int "); outs(name); outs(" = "); outs(strnum); outs(";\n"); if (substdio_flush(&ss1) == -1) _exit(111); _exit(0); } netqmail-1.06/REMOVE.sendmail0000644000076400007640000000237606541176434015375 0ustar nelsonnelsonHere's how to remove sendmail from your system. 1. Find sendmail in your boot scripts. It's usually in either /etc/rc or /etc/init.d/sendmail. It looks like sendmail -bd -q15m -q15m means that it should run the queue every 15 minutes; you may see a different number. Comment out this line. 2. Kill the sendmail daemon. You should first kill -STOP the daemon; if any children are running, you should kill -CONT, wait, kill -STOP again, and repeat ad nauseam. If there aren't any children, kill -TERM and then kill -CONT. 3. Check whether you have any messages in the sendmail queue, /var/spool/mqueue. If you do, you will have to try flushing them with sendmail.bak -q. If necessary, wait a while and run sendmail.bak -q again. Repeat until the queue is empty. This may take several days. 4. Remove the setuid bit on the sendmail binary, to prevent local users from gaining extra privileges through sendmail's security holes. The binary may be at several different locations: # chmod 0 /usr/lib/sendmail # chmod 0 /usr/sbin/sendmail # chmod 0 /usr/lib/sendmail.mx 5. Move the sendmail binary out of the way: # mv /usr/lib/sendmail /usr/lib/sendmail.bak # mv /usr/sbin/sendmail /usr/sbin/sendmail.bak netqmail-1.06/token822.h0000644000076400007640000000134306541176434014400 0ustar nelsonnelson#ifndef TOKEN822_H #define TOKEN822_H struct token822 { int type; char *s; int slen; } ; #include "gen_alloc.h" GEN_ALLOC_typedef(token822_alloc,struct token822,t,len,a) extern int token822_parse(); extern int token822_addrlist(); extern int token822_unquote(); extern int token822_unparse(); extern void token822_free(); extern void token822_reverse(); extern int token822_ready(); extern int token822_readyplus(); extern int token822_append(); #define TOKEN822_ATOM 1 #define TOKEN822_QUOTE 2 #define TOKEN822_LITERAL 3 #define TOKEN822_COMMENT 4 #define TOKEN822_LEFT 5 #define TOKEN822_RIGHT 6 #define TOKEN822_AT 7 #define TOKEN822_COMMA 8 #define TOKEN822_SEMI 9 #define TOKEN822_COLON 10 #define TOKEN822_DOT 11 #endif netqmail-1.06/substdi.c0000644000076400007640000000311706541176434014475 0ustar nelsonnelson#include "substdio.h" #include "byte.h" #include "error.h" static int oneread(op,fd,buf,len) register int (*op)(); register int fd; register char *buf; register int len; { register int r; for (;;) { r = op(fd,buf,len); if (r == -1) if (errno == error_intr) continue; return r; } } static int getthis(s,buf,len) register substdio *s; register char *buf; register int len; { register int r; register int q; r = s->p; q = r - len; if (q > 0) { r = len; s->p = q; } else s->p = 0; byte_copy(buf,r,s->x + s->n); s->n += r; return r; } int substdio_feed(s) register substdio *s; { register int r; register int q; if (s->p) return s->p; q = s->n; r = oneread(s->op,s->fd,s->x,q); if (r <= 0) return r; s->p = r; q -= r; s->n = q; if (q > 0) /* damn, gotta shift */ byte_copyr(s->x + q,r,s->x); return r; } int substdio_bget(s,buf,len) register substdio *s; register char *buf; register int len; { register int r; if (s->p > 0) return getthis(s,buf,len); r = s->n; if (r <= len) return oneread(s->op,s->fd,buf,r); r = substdio_feed(s); if (r <= 0) return r; return getthis(s,buf,len); } int substdio_get(s,buf,len) register substdio *s; register char *buf; register int len; { register int r; if (s->p > 0) return getthis(s,buf,len); if (s->n <= len) return oneread(s->op,s->fd,buf,len); r = substdio_feed(s); if (r <= 0) return r; return getthis(s,buf,len); } char *substdio_peek(s) register substdio *s; { return s->x + s->n; } void substdio_seek(s,len) register substdio *s; register int len; { s->n += len; s->p -= len; } netqmail-1.06/case_diffs.c0000644000076400007640000000061106541176434015102 0ustar nelsonnelson#include "case.h" int case_diffs(s,t) register char *s; register char *t; { register unsigned char x; register unsigned char y; for (;;) { x = *s++ - 'A'; if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; y = *t++ - 'A'; if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; if (x != y) break; if (!x) break; } return ((int)(unsigned int) x) - ((int)(unsigned int) y); } netqmail-1.06/qmail-tcpto.80000644000076400007640000000115506541176434015177 0ustar nelsonnelson.TH qmail-tcpto 8 .SH NAME qmail-tcpto \- print TCP timeout table .SH SYNOPSIS .B qmail-tcpto .SH DESCRIPTION After an SMTP connection attempt times out, .B qmail-remote records the relevant IP address. If the same address fails again (after at least two minutes with no intervening successful connections), .B qmail-remote assumes that further attempts will fail for at least another hour. .B qmail-tcpto prints .BR qmail-remote 's current list of timeouts. .B qmail-tcpto must be run either as .B root or with user id .B qmailr and group id .BR qmail . .SH "SEE ALSO" qmail-qread(8), qmail-remote(8), qmail-tcpok(8) netqmail-1.06/qmail-pw2u.c0000644000076400007640000002156306541176434015023 0ustar nelsonnelson#include #include #include "substdio.h" #include "readwrite.h" #include "subfd.h" #include "sgetopt.h" #include "control.h" #include "constmap.h" #include "stralloc.h" #include "fmt.h" #include "str.h" #include "scan.h" #include "open.h" #include "error.h" #include "getln.h" #include "auto_break.h" #include "auto_qmail.h" #include "auto_usera.h" void die_chdir() { substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to chdir\n"); _exit(111); } void die_nomem() { substdio_putsflush(subfderr,"qmail-pw2u: fatal: out of memory\n"); _exit(111); } void die_read() { substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read input\n"); _exit(111); } void die_write() { substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to write output\n"); _exit(111); } void die_control() { substdio_putsflush(subfderr,"qmail-pw2u: fatal: unable to read controls\n"); _exit(111); } void die_alias() { substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find "); substdio_puts(subfderr,auto_usera); substdio_puts(subfderr," user\n"); substdio_flush(subfderr); _exit(111); } void die_home(fn) char *fn; { substdio_puts(subfderr,"qmail-pw2u: fatal: unable to stat "); substdio_puts(subfderr,fn); substdio_puts(subfderr,"\n"); substdio_flush(subfderr); _exit(111); } void die_user(s,len) char *s; unsigned int len; { substdio_puts(subfderr,"qmail-pw2u: fatal: unable to find "); substdio_put(subfderr,s,len); substdio_puts(subfderr," user for subuser\n"); substdio_flush(subfderr); _exit(111); } char *dashcolon = "-:"; int flagalias = 0; int flagnoupper = 1; int homestrategy = 2; /* 2: skip if home does not exist; skip if home is not owned by user */ /* 1: stop if home does not exist; skip if home is not owned by user */ /* 0: don't worry about home */ int okincl; stralloc incl = {0}; struct constmap mapincl; int okexcl; stralloc excl = {0}; struct constmap mapexcl; int okmana; stralloc mana = {0}; struct constmap mapmana; stralloc allusers = {0}; struct constmap mapuser; stralloc uugh = {0}; stralloc user = {0}; stralloc uidstr = {0}; stralloc gidstr = {0}; stralloc home = {0}; unsigned long uid; stralloc line = {0}; void doaccount() { struct stat st; int i; char *mailnames; char *x; unsigned int xlen; if (byte_chr(line.s,line.len,'\0') < line.len) return; x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (!stralloc_copyb(&user,x,i)) die_nomem(); if (!stralloc_0(&user)) die_nomem(); ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (!stralloc_copyb(&uidstr,x,i)) die_nomem(); if (!stralloc_0(&uidstr)) die_nomem(); scan_ulong(uidstr.s,&uid); ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (!stralloc_copyb(&gidstr,x,i)) die_nomem(); if (!stralloc_0(&gidstr)) die_nomem(); ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (!stralloc_copyb(&home,x,i)) die_nomem(); if (!stralloc_0(&home)) die_nomem(); if (!uid) return; if (flagnoupper) for (i = 0;i < user.len;++i) if ((user.s[i] >= 'A') && (user.s[i] <= 'Z')) return; if (okincl) if (!constmap(&mapincl,user.s,user.len - 1)) return; if (okexcl) if (constmap(&mapexcl,user.s,user.len - 1)) return; if (homestrategy) { if (stat(home.s,&st) == -1) { if (errno != error_noent) die_home(home.s); if (homestrategy == 1) die_home(home.s); return; } if (st.st_uid != uid) return; } if (!stralloc_copys(&uugh,":")) die_nomem(); if (!stralloc_cats(&uugh,user.s)) die_nomem(); if (!stralloc_cats(&uugh,":")) die_nomem(); if (!stralloc_cats(&uugh,uidstr.s)) die_nomem(); if (!stralloc_cats(&uugh,":")) die_nomem(); if (!stralloc_cats(&uugh,gidstr.s)) die_nomem(); if (!stralloc_cats(&uugh,":")) die_nomem(); if (!stralloc_cats(&uugh,home.s)) die_nomem(); if (!stralloc_cats(&uugh,":")) die_nomem(); /* XXX: avoid recording in allusers unless sub actually needs it */ if (!stralloc_cats(&allusers,user.s)) die_nomem(); if (!stralloc_cats(&allusers,":")) die_nomem(); if (!stralloc_catb(&allusers,uugh.s,uugh.len)) die_nomem(); if (!stralloc_0(&allusers)) die_nomem(); if (str_equal(user.s,auto_usera)) { if (substdio_puts(subfdout,"+") == -1) die_write(); if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); if (substdio_puts(subfdout,dashcolon) == -1) die_write(); if (substdio_puts(subfdout,":\n") == -1) die_write(); flagalias = 1; } mailnames = 0; if (okmana) mailnames = constmap(&mapmana,user.s,user.len - 1); if (!mailnames) mailnames = user.s; for (;;) { while (*mailnames == ':') ++mailnames; if (!*mailnames) break; i = str_chr(mailnames,':'); if (substdio_puts(subfdout,"=") == -1) die_write(); if (substdio_put(subfdout,mailnames,i) == -1) die_write(); if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); if (substdio_puts(subfdout,"::\n") == -1) die_write(); if (*auto_break) { if (substdio_puts(subfdout,"+") == -1) die_write(); if (substdio_put(subfdout,mailnames,i) == -1) die_write(); if (substdio_put(subfdout,auto_break,1) == -1) die_write(); if (substdio_put(subfdout,uugh.s,uugh.len) == -1) die_write(); if (substdio_puts(subfdout,dashcolon) == -1) die_write(); if (substdio_puts(subfdout,":\n") == -1) die_write(); } mailnames += i; } } stralloc sub = {0}; void dosubuser() { int i; char *x; unsigned int xlen; char *uugh; x = line.s; xlen = line.len; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (!stralloc_copyb(&sub,x,i)) die_nomem(); ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; uugh = constmap(&mapuser,x,i); if (!uugh) die_user(x,i); ++i; x += i; xlen -= i; i = byte_chr(x,xlen,':'); if (i == xlen) return; if (substdio_puts(subfdout,"=") == -1) die_write(); if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); if (substdio_puts(subfdout,uugh) == -1) die_write(); if (substdio_puts(subfdout,dashcolon) == -1) die_write(); if (substdio_put(subfdout,x,i) == -1) die_write(); if (substdio_puts(subfdout,":\n") == -1) die_write(); if (*auto_break) { if (substdio_puts(subfdout,"+") == -1) die_write(); if (substdio_put(subfdout,sub.s,sub.len) == -1) die_write(); if (substdio_put(subfdout,auto_break,1) == -1) die_write(); if (substdio_puts(subfdout,uugh) == -1) die_write(); if (substdio_puts(subfdout,dashcolon) == -1) die_write(); if (substdio_put(subfdout,x,i) == -1) die_write(); if (substdio_puts(subfdout,"-:\n") == -1) die_write(); } } int fd; substdio ss; char ssbuf[SUBSTDIO_INSIZE]; void main(argc,argv) int argc; char **argv; { int opt; int match; while ((opt = getopt(argc,argv,"/ohHuUc:C")) != opteof) switch(opt) { case '/': dashcolon = "-/:"; break; case 'o': homestrategy = 2; break; case 'h': homestrategy = 1; break; case 'H': homestrategy = 0; break; case 'u': flagnoupper = 0; break; case 'U': flagnoupper = 1; break; case 'c': *auto_break = *optarg; break; case 'C': *auto_break = 0; break; case '?': default: _exit(100); } if (chdir(auto_qmail) == -1) die_chdir(); /* no need for control_init() */ okincl = control_readfile(&incl,"users/include",0); if (okincl == -1) die_control(); if (okincl) if (!constmap_init(&mapincl,incl.s,incl.len,0)) die_nomem(); okexcl = control_readfile(&excl,"users/exclude",0); if (okexcl == -1) die_control(); if (okexcl) if (!constmap_init(&mapexcl,excl.s,excl.len,0)) die_nomem(); okmana = control_readfile(&mana,"users/mailnames",0); if (okmana == -1) die_control(); if (okmana) if (!constmap_init(&mapmana,mana.s,mana.len,1)) die_nomem(); if (!stralloc_copys(&allusers,"")) die_nomem(); for (;;) { if (getln(subfdin,&line,&match,'\n') == -1) die_read(); doaccount(); if (!match) break; } if (!flagalias) die_alias(); fd = open_read("users/subusers"); if (fd == -1) { if (errno != error_noent) die_control(); } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); if (!constmap_init(&mapuser,allusers.s,allusers.len,1)) die_nomem(); for (;;) { if (getln(&ss,&line,&match,'\n') == -1) die_read(); dosubuser(); if (!match) break; } close(fd); } fd = open_read("users/append"); if (fd == -1) { if (errno != error_noent) die_control(); } else { substdio_fdbuf(&ss,read,fd,ssbuf,sizeof(ssbuf)); for (;;) { if (getln(&ss,&line,&match,'\n') == -1) die_read(); if (substdio_put(subfdout,line.s,line.len) == -1) die_write(); if (!match) break; } } if (substdio_puts(subfdout,".\n") == -1) die_write(); if (substdio_flush(subfdout) == -1) die_write(); _exit(0); } netqmail-1.06/alloc.c0000644000076400007640000000150106541176434014105 0ustar nelsonnelson#include "alloc.h" #include "error.h" extern char *malloc(); extern void free(); #define ALIGNMENT 16 /* XXX: assuming that this alignment is enough */ #define SPACE 4096 /* must be multiple of ALIGNMENT */ typedef union { char irrelevant[ALIGNMENT]; double d; } aligned; static aligned realspace[SPACE / ALIGNMENT]; #define space ((char *) realspace) static unsigned int avail = SPACE; /* multiple of ALIGNMENT; 0<=avail<=SPACE */ /*@null@*//*@out@*/char *alloc(n) unsigned int n; { char *x; n = ALIGNMENT + n - (n & (ALIGNMENT - 1)); /* XXX: could overflow */ if (n <= avail) { avail -= n; return space + avail; } x = malloc(n); if (!x) errno = error_nomem; return x; } void alloc_free(x) char *x; { if (x >= space) if (x < space + SPACE) return; /* XXX: assuming that pointers are flat */ free(x); } netqmail-1.06/qmail-tcpok.c0000644000076400007640000000172606541176434015245 0ustar nelsonnelson#include "strerr.h" #include "substdio.h" #include "lock.h" #include "open.h" #include "readwrite.h" #include "auto_qmail.h" #include "exit.h" #define FATAL "qmail-tcpok: fatal: " char buf[1024]; /* XXX: must match size in tcpto_clean.c, tcpto.c */ substdio ss; void main() { int fd; int i; if (chdir(auto_qmail) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); if (chdir("queue/lock") == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,"/queue/lock: "); fd = open_write("tcpto"); if (fd == -1) strerr_die4sys(111,FATAL,"unable to write ",auto_qmail,"/queue/lock/tcpto: "); if (lock_ex(fd) == -1) strerr_die4sys(111,FATAL,"unable to lock ",auto_qmail,"/queue/lock/tcpto: "); substdio_fdbuf(&ss,write,fd,buf,sizeof buf); for (i = 0;i < sizeof buf;++i) substdio_put(&ss,"",1); if (substdio_flush(&ss) == -1) strerr_die4sys(111,FATAL,"unable to clear ",auto_qmail,"/queue/lock/tcpto: "); _exit(0); } netqmail-1.06/substdio.c0000644000076400007640000000034706541176434014656 0ustar nelsonnelson#include "substdio.h" void substdio_fdbuf(s,op,fd,buf,len) register substdio *s; register int (*op)(); register int fd; register char *buf; register int len; { s->x = buf; s->fd = fd; s->op = op; s->p = 0; s->n = len; } netqmail-1.06/gfrom.c0000644000076400007640000000025506541176434014132 0ustar nelsonnelson#include "str.h" #include "gfrom.h" int gfrom(s,len) char *s; int len; { while ((len > 0) && (*s == '>')) { ++s; --len; } return (len >= 5) && !str_diffn(s,"From ",5); } netqmail-1.06/open_write.c0000644000076400007640000000020306541176434015164 0ustar nelsonnelson#include #include #include "open.h" int open_write(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY); } netqmail-1.06/qmail-remote.80000644000076400007640000000743206541176434015345 0ustar nelsonnelson.TH qmail-remote 8 .SH NAME qmail-remote \- send mail via SMTP .SH SYNOPSIS .B qmail-remote .I host .I sender .I recip [ .I recip ... ] .SH DESCRIPTION .B qmail-remote reads a mail message from its input and sends the message to one or more recipients at a remote host. The remote host is .BR qmail-remote 's first argument, .IR host . .B qmail-remote sends the message to .IR host , or to a mail exchanger for .I host listed in the Domain Name System, via the Simple Mail Transfer Protocol (SMTP). .I host can be either a fully-qualified domain name: .EX silverton.berkeley.edu .EE or an IP address enclosed in brackets: .EX [128.32.183.163] .EE The envelope recipient addresses are listed as .I recip arguments to .BR qmail-remote . The envelope sender address is listed as .I sender\fP. Note that .B qmail-remote does not take options and does not follow the .B getopt standard. .SH TRANSPARENCY End-of-file in SMTP is encoded as dot CR LF. A dot at the beginning of a line is encoded as dot dot. It is impossible in SMTP to send a message that does not end with a newline. .B qmail-remote converts the UNIX newline convention into the SMTP newline convention by inserting CR before each LF. It is a violation of the SMTP protocol to send a message that contains long lines or non-ASCII characters. However, .B qmail-remote will happily send such messages. It is the user's responsibility to avoid generating illegal messages. .SH "RESULTS" .B qmail-remote prints some number of .I recipient reports\fP, followed by a .I message report\fR. Each report is terminated by a 0 byte. Each report begins with a single letter: .TP 5 r Recipient report: acceptance. .TP 5 h Recipient report: permanent rejection. .TP 5 s Recipient report: temporary rejection. .TP 5 K Message report: success. .I host has taken responsibility for delivering the message to each acceptable recipient. .TP 5 Z Message report: temporary failure. .TP 5 D Message report: permanent failure. .PP After this letter comes a human-readable description of what happened. The recipient reports will always be printed in the same order as .BR qmail-remote 's .I recip arguments. Note that in failure cases there may be fewer recipient reports than .I recip arguments. .B qmail-remote always exits zero. .SH "CONTROL FILES" .TP 5 .I helohost Current host name, for use solely in saying hello to the remote SMTP server. Default: .IR me , if that is supplied; otherwise .B qmail-remote refuses to run. .TP 5 .I smtproutes Artificial SMTP routes. Each route has the form .IR domain\fB:\fIrelay , without any extra spaces. If .I domain matches .IR host , .B qmail-remote will connect to .IR relay , as if .I host had .I relay as its only MX. (It will also avoid doing any CNAME lookups on .IR recip .) .I host may include a colon and a port number to use instead of the normal SMTP port, 25: .EX inside.af.mil:firewall.af.mil:26 .EE .I relay may be empty; this tells .B qmail-remote to look up MX records as usual. .I smtproutes may include wildcards: .EX .af.mil: :heaven.af.mil .EE Here any address ending with .B .af.mil (but not .B af.mil itself) is routed by its MX records; any other address is artificially routed to .BR heaven.af.mil . The .B qmail system does not protect you if you create an artificial mail loop between machines. However, you are always safe using .I smtproutes if you do not accept mail from the network. .TP 5 .I timeoutconnect Number of seconds .B qmail-remote will wait for the remote SMTP server to accept a connection. Default: 60. The kernel normally imposes a 75-second upper limit. .TP 5 .I timeoutremote Number of seconds .B qmail-remote will wait for each response from the remote SMTP server. Default: 1200. .SH "SEE ALSO" addresses(5), envelopes(5), qmail-control(5), qmail-send(8), qmail-smtpd(8), qmail-tcpok(8), qmail-tcpto(8) netqmail-1.06/maildir.h0000644000076400007640000000034506541176434014446 0ustar nelsonnelson#ifndef MAILDIR_H #define MAILDIR_H #include "strerr.h" extern struct strerr maildir_chdir_err; extern struct strerr maildir_scan_err; extern int maildir_chdir(); extern void maildir_clean(); extern int maildir_scan(); #endif netqmail-1.06/seek_end.c0000644000076400007640000000023106541176434014567 0ustar nelsonnelson#include #include "seek.h" #define END 2 /* sigh */ int seek_end(fd) int fd; { if (lseek(fd,(off_t) 0,END) == -1) return -1; return 0; } netqmail-1.06/cdb.30000644000076400007640000000220406541176434013464 0ustar nelsonnelson.TH cdb 3 .SH NAME cdb \- read from a constant database .SH SYNTAX .B #include int \fBcdb_seek(\fP\fIfd,key,len,dlen\fR\fB)\fP; int \fIfd\fR; .br char *\fIkey\fR; .br unsigned int \fIlen\fR; .br uint32 *\fIdlen\fR; .SH DESCRIPTION .B cdb_seek looks up .I key in a constant database. It returns 1 if .I key is present, 0 if .I key is not present, or \-1 if there was a read error. .I key is an array of .I len characters. .B cdb_seek needs an open file descriptor, .IR fd , pointing to the database. If .B cdb_seek returns 1, it points .I fd at the beginning of the data portion of the first record indexed by .IR key , and it stores the data length in .IR dlen. .B cdb_seek does not provide a way to read subsequent records with the same key. It's fine to do several .B cdb_seek lookups with the same open file descriptor. Beware, however, that two simultaneous .B cdb_seek lookups can fail horribly; separate processes should not share the same database descriptor. Furthermore, any updates after the database was opened will be invisible. It's rarely a good idea for a long-running program to hold a database open. .SH "SEE ALSO" cdbget(1) netqmail-1.06/qmail-newmrh.90000644000076400007640000000150206541176434015343 0ustar nelsonnelson.TH qmail-newmrh 8 .SH NAME qmail-newmrh \- prepare morercpthosts for qmail-smtpd .SH SYNOPSIS .B qmail-newmrh .SH DESCRIPTION .B qmail-newmrh reads the instructions in .B QMAILHOME/control/morercpthosts and writes them into .B QMAILHOME/control/morercpthosts.cdb in a binary format suited for quick access by .BR qmail-smtpd . If there is a problem with .BR control/morercpthosts , .B qmail-newmrh complains and leaves .B control/morercpthosts.cdb alone. .B qmail-newmrh ensures that .B control/morercpthosts.cdb is updated atomically, so .B qmail-smtpd never has to wait for .B qmail-newmrh to finish. However, .B qmail-newmrh makes no attempt to protect against two simultaneous updates of .BR control/morercpthosts.cdb . The binary .B control/morercpthosts.cdb format is portable across machines. .SH "SEE ALSO" qmail-smtpd(8) netqmail-1.06/getln.30000644000076400007640000000126506541176434014053 0ustar nelsonnelson.TH getln 3 .SH NAME getln \- read one line of data .SH SYNTAX .B #include int \fBgetln\fP(&\fIss\fR,&\fIsa\fR,&\fImatch\fR,\fIsep\fR); substdio \fIss\fR; .br stralloc \fIsa\fR; .br int \fImatch\fR; .br int \fIsep\fR; .SH DESCRIPTION .B getln reads a line of characters, terminated by a .I sep character, from .IR ss . It returns the line in .I sa and sets .I match to 1. If .B getln sees end-of-input before it sees .IR sep , it returns the partial line in .I sa and sets .I match to 0. .B getln normally returns 0. If it runs out of memory, or encounters an error from .IR ss , it returns -1, setting .B errno appropriately. .SH "SEE ALSO" stralloc(3), substdio(3), getln2(3) netqmail-1.06/qmail-getpw.90000644000076400007640000000411606541176434015175 0ustar nelsonnelson.TH qmail-getpw 8 .SH NAME qmail-getpw \- give addresses to users .SH SYNOPSIS .B qmail-getpw .I local .SH DESCRIPTION In .BR qmail , each user controls a vast array of local addresses. .B qmail-getpw finds the user that controls a particular address, .IR local . It prints six pieces of information, each terminated by NUL: .IR user ; .IR uid ; .IR gid ; .IR homedir ; .IR dash ; and .IR ext . The user's account name is .IR user ; the user's uid and gid in decimal are .I uid and .IR gid ; the user's home directory is .IR homedir ; and messages to .I local will be handled by .IR homedir\fB/.qmail\fIdashext . In case of trouble, .B qmail-getpw exits nonzero without printing anything. .B WARNING: The operating system's .B getpwnam function, which is at the heart of .BR qmail-getpw , is inherently unreliable: it fails to distinguish between temporary errors and nonexistent users. Future versions of .B getpwnam should return ETXTBSY to indicate temporary errors and ESRCH to indicate nonexistent users. .SH "RULES" .B qmail-getpw considers an account in .B /etc/passwd to be a user if (1) the account has a nonzero uid, (2) the account's home directory exists (and is visible to .BR qmail-getpw ), and (3) the account owns its home directory. .B qmail-getpw ignores account names containing uppercase letters. .B qmail-getpw also assumes that all account names are shorter than 32 characters. .B qmail-getpw gives each user control over the basic .I user address and all addresses of the form .IR user\fBBREAK\fIanything . When .I local is .IR user , .I dash and .I ext are both empty. When .I local is .IR user\fBBREAK\fIanything , .I dash is a hyphen and .I ext is .IR anything . .I user may appear in any combination of uppercase and lowercase letters at the front of .IR local . A catch-all user, .BR alias , controls all other addresses. In this case .I ext is .I local and .I dash is a hyphen. You can override all of .BR qmail-getpw 's decisions with the .B qmail-users mechanism, which is reliable, highly configurable, and much faster than .BR qmail-getpw . .SH "SEE ALSO" qmail-users(5), qmail-lspawn(8) netqmail-1.06/auto_break.h0000644000076400007640000000011506541176434015134 0ustar nelsonnelson#ifndef AUTO_BREAK_H #define AUTO_BREAK_H extern char auto_break[]; #endif netqmail-1.06/SECURITY0000644000076400007640000001357606541176434014060 0ustar nelsonnelsonBackground: Every few months CERT announces Yet Another Security Hole In Sendmail---something that lets local or even remote users take complete control of the machine. I'm sure there are many more holes waiting to be discovered; sendmail's design means that any minor bug in 46000 lines of code is a major security risk. Other popular mailers, such as Smail, and even mailing-list managers, such as Majordomo, seem nearly as bad. Note added in 1998: I wrote the above paragraph in December 1995, when the latest version of sendmail was 8.6.12 (with 41000 lines of code). Fourteen security holes were discovered from sendmail 8.6.12 through 8.8.5. See http://pobox.com/~djb/docs/maildisasters/sendmail.html. I started working on qmail because I was sick of this cycle of doom. Here are some of the things I did to make sure that qmail will never let an intruder into your machine. 1. Programs and files are not addresses. Don't treat them as addresses. sendmail treats programs and files as addresses. Obviously random people can't be allowed to execute arbitrary programs or write to arbitrary files, so sendmail goes through horrendous contortions trying to keep track of whether a local user was ``responsible'' for an address. This has proven to be an unmitigated disaster. In qmail, programs and files are not addresses. The local delivery agent, qmail-local, can run programs or write to files as directed by ~user/.qmail, but it's always running as that user. (The notion of ``user'' is configurable, but root is never a user. To prevent silly mistakes, qmail-local makes sure that neither ~user nor ~user/.qmail is group-writable or world-writable.) Security impact: .qmail, like .cshrc and .exrc and various other files, means that anyone who can write arbitrary files as a user can execute arbitrary programs as that user. That's it. 2. Do as little as possible in setuid programs. A setuid program must operate in a very dangerous environment: a user is under complete control of its fds, args, environ, cwd, tty, rlimits, timers, signals, and more. Even worse, the list of controlled items varies from one vendor's UNIX to the next, so it is very difficult to write portable code that cleans up everything. Of the twenty most recent sendmail security holes, eleven worked only because the entire sendmail system is setuid. Only one qmail program is setuid: qmail-queue. Its only purpose is to add a new mail message to the outgoing queue. 3. Do as little as possible as root. The entire sendmail system runs as root, so there's no way that its mistakes can be caught by the operating system's built-in protections. In contrast, only two qmail programs, qmail-start and qmail-lspawn, run as root. 4. Move separate functions into mutually untrusting programs. Five of the qmail programs---qmail-smtpd, qmail-send, qmail-rspawn, qmail-remote, and tcp-env---are not security-critical. Even if all of these programs are completely compromised, so that an intruder has control over the qmaild, qmails, and qmailr accounts and the mail queue, he still can't take over your system. None of the other programs trust the results from these five. In fact, these programs don't even trust each other. They are in three groups: tcp-env and qmail-smtpd, which run as qmaild; qmail-rspawn and qmail-remote, which run as qmailr; and qmail-send, the queue manager, which runs as qmails. Each group is immune from attacks by the others. (From root's point of view, as long as root doesn't send any mail, only qmail-start and qmail-lspawn are security-critical. They don't write any files or start any other programs as root.) 5. Don't parse. I have discovered that there are two types of command interfaces in the world of computing: good interfaces and user interfaces. The essence of user interfaces is _parsing_---converting an unstructured sequence of commands, in a format usually determined more by psychology than by solid engineering, into structured data. When another programmer wants to talk to a user interface, he has to _quote_: convert his structured data into an unstructured sequence of commands that the parser will, he hopes, convert back into the original structured data. This situation is a recipe for disaster. The parser often has bugs: it fails to handle some inputs according to the documented interface. The quoter often has bugs: it produces outputs that do not have the right meaning. Only on rare joyous occasions does it happen that the parser and the quoter both misinterpret the interface in the same way. When the original data is controlled by a malicious user, many of these bugs translate into security holes. Some examples: the Linux login -froot security hole; the classic find | xargs rm security hole; the Majordomo injection security hole. Even a simple parser like getopt is complicated enough for people to screw up the quoting. In qmail, all the internal file structures are incredibly simple: text0 lines beginning with single-character commands. (text0 format means that lines are separated by a 0 byte instead of line feed.) The program-level interfaces don't take options. All the complexity of parsing RFC 822 address lists and rewriting headers is in the qmail-inject program, which runs without privileges and is essentially part of the UA. 6. Keep it simple, stupid. See BLURB for some of the reasons that qmail is so much smaller than sendmail. There's nothing inherently complicated about writing a mailer. (Except RFC 822 support; but that's only in qmail-inject.) Security holes can't show up in features that don't exist. 7. Write bug-free code. I've mostly given up on the standard C library. Many of its facilities, particularly stdio, seem designed to encourage bugs. A big chunk of qmail is stolen from a basic C library that I've been developing for several years for a variety of applications. The stralloc concept and getln() make it very easy to avoid buffer overruns, memory leaks, and artificial line length limits. netqmail-1.06/rcpthosts.h0000644000076400007640000000014606541176434015055 0ustar nelsonnelson#ifndef RCPTHOSTS_H #define RCPTHOSTS_H extern int rcpthosts_init(); extern int rcpthosts(); #endif netqmail-1.06/qmail-popup.80000644000076400007640000000254606541176434015216 0ustar nelsonnelson.TH qmail-popup 8 .SH NAME qmail-popup \- read a POP username and password .SH SYNOPSIS .B qmail-popup .I hostname .I subprogram .SH DESCRIPTION .B qmail-popup reads a POP username and password from the network. It then runs .IR subprogram . .B qmail-popup is most commonly invoked from .B inetd as .EX qmail-popup CHANGEME checkpassword qmail-pop3d Maildir .EE with CHANGEME replaced by the fully qualified domain name of the local host. .B qmail-popup expects descriptor 0 to read from the network and descriptor 1 to write to the network. It reads a username and password from descriptor 0 in POP's USER-PASS style or APOP style. It invokes .IR subprogram , with the same descriptors 0 and 1; descriptor 2 writing to the network; and descriptor 3 reading the username, a 0 byte, the password, another 0 byte, an APOP timestamp derived from .IR hostname , and a final 0 byte. .B qmail-popup then waits for .I subprogram to finish. It prints an error message if .I subprogram crashes or exits nonzero. .B qmail-popup should be used only within a secure network. Otherwise an eavesdropper can steal passwords. Even if you use APOP, an active attacker can still take over the connection and wreak havoc. .B qmail-popup has a 20-minute idle timeout. .B qmail-popup is based on a program contributed by Russ Nelson. .SH "SEE ALSO" maildir(5), qmail-local(8), qmail-pop3d(8) netqmail-1.06/trydrent.c0000644000076400007640000000013306541176434014666 0ustar nelsonnelson#include #include void foo() { DIR *dir; struct dirent *d; } netqmail-1.06/str.h0000644000076400007640000000042706541176434013636 0ustar nelsonnelson#ifndef STR_H #define STR_H extern unsigned int str_copy(); extern int str_diff(); extern int str_diffn(); extern unsigned int str_len(); extern unsigned int str_chr(); extern unsigned int str_rchr(); extern int str_start(); #define str_equal(s,t) (!str_diff((s),(t))) #endif netqmail-1.06/quote.h0000644000076400007640000000015306541176434014157 0ustar nelsonnelson#ifndef QUOTE_H #define QUOTE_H extern int quote_need(); extern int quote(); extern int quote2(); #endif netqmail-1.06/pinq.sh0000644000076400007640000000005606541176434014156 0ustar nelsonnelsonQMAIL/bin/maildir2mbox && exec pine ${1+"$@"} netqmail-1.06/prot.c0000644000076400007640000000071606541176434014006 0ustar nelsonnelson#include "hasshsgr.h" #include "prot.h" /* XXX: there are more portability problems here waiting to leap out at me */ int prot_gid(gid) int gid; { #ifdef HASSHORTSETGROUPS short x[2]; x[0] = gid; x[1] = 73; /* catch errors */ if (setgroups(1,x) == -1) return -1; #else if (setgroups(1,&gid) == -1) return -1; #endif return setgid(gid); /* _should_ be redundant, but on some systems it isn't */ } int prot_uid(uid) int uid; { return setuid(uid); } netqmail-1.06/getln.h0000644000076400007640000000012206541176434014127 0ustar nelsonnelson#ifndef GETLN_H #define GETLN_H extern int getln(); extern int getln2(); #endif netqmail-1.06/splogger.80000644000076400007640000000170406541176434014567 0ustar nelsonnelson.TH splogger 8 .SH NAME splogger \- make entries in syslog .SH SYNOPSIS .B splogger [ .I tag [ .I fac ] ] .SH DESCRIPTION .B splogger reads a series of messages and feeds them to .BR syslog . At the front of each message it puts .I tag (default: .BR splogger ) and a numerical timestamp. .B splogger checks for .B alert: or .B warning: at the beginning of each message. It selects a priority of LOG_ALERT, LOG_WARNING, or LOG_INFO accordingly. .B splogger logs messages with facility .IR fac . .I fac (default: 2) must be numeric. .B splogger converts unprintable characters to question marks. .B splogger does not log blank lines. .B splogger folds messages after 800 characters, since .B syslog can't handle long messages. .B splogger uses a + after the timestamp to mark folded lines. Note that the .B syslog mechanism is inherently unreliable: it does not guarantee that messages will be logged. It is also very slow. .SH "SEE ALSO" syslog(3), logger(8) netqmail-1.06/INTERNALS0000644000076400007640000001545606541176434014147 0ustar nelsonnelson1. Overview Here's the data flow in the qmail suite: qmail-smtpd --- qmail-queue --- qmail-send --- qmail-rspawn --- qmail-remote / | \ qmail-inject _/ qmail-clean \_ qmail-lspawn --- qmail-local Every message is added to a central queue directory by qmail-queue. qmail-queue is invoked as needed, usually by qmail-inject for locally generated messages, qmail-smtpd for messages received through SMTP, qmail-local for forwarded messages, or qmail-send for bounce messages. Every message is then delivered by qmail-send, in cooperation with qmail-lspawn and qmail-rspawn, and cleaned up by qmail-clean. These four programs are long-running daemons. The queue is designed to be crashproof, provided that the underlying filesystem is crashproof. All cleanups are handled by qmail-send and qmail-clean without human intervention. See section 6 for more details. 2. Queue structure Each message in the queue is identified by a unique number, let's say 457. The queue is organized into several directories, each of which may contain files related to message 457: mess/457: the message todo/457: the envelope: where the message came from, where it's going intd/457: the envelope, under construction by qmail-queue info/457: the envelope sender address, after preprocessing local/457: local envelope recipient addresses, after preprocessing remote/457: remote envelope recipient addresses, after preprocessing bounce/457: permanent delivery errors Here are all possible states for a message. + means a file exists; - means it does not exist; ? means it may or may not exist. S1. -mess -intd -todo -info -local -remote -bounce S2. +mess -intd -todo -info -local -remote -bounce S3. +mess +intd -todo -info -local -remote -bounce S4. +mess ?intd +todo ?info ?local ?remote -bounce (queued) S5. +mess -intd -todo +info ?local ?remote ?bounce (preprocessed) Guarantee: If mess/457 exists, it has inode number 457. 3. How messages enter the queue To add a message to the queue, qmail-queue first creates a file in a separate directory, pid/, with a unique name. The filesystem assigns that file a unique inode number. qmail-queue looks at that number, say 457. By the guarantee above, message 457 must be in state S1. qmail-queue renames pid/whatever as mess/457, moving to S2. It writes the message to mess/457. It then creates intd/457, moving to S3, and writes the envelope information to intd/457. Finally qmail-queue creates a new link, todo/457, for intd/457, moving to S4. At that instant the message has been successfully queued, and qmail-queue leaves it for further handling by qmail-send. qmail-queue starts a 24-hour timer before touching any files, and commits suicide if the timer expires. 4. How queued messages are preprocessed Once a message has been queued, qmail-send must decide which recipients are local and which recipients are remote. It may also rewrite some recipient addresses. When qmail-send notices todo/457, it knows that message 457 is in S4. It removes info/457, local/457, and remote/457 if they exist. Then it reads through todo/457. It creates info/457, possibly local/457, and possibly remote/457. When it is done, it removes intd/457. The message is still in S4 at this point. Finally qmail-send removes todo/457, moving to S5. At that instant the message has been successfully preprocessed. 5. How preprocessed messages are delivered Messages at S5 are handled as follows. Each address in local/457 and remote/457 is marked either NOT DONE or DONE. DONE: The message was successfully delivered, or the last delivery attempt met with permanent failure. Either way, qmail-send should not attempt further delivery to this address. NOT DONE: If there have been any delivery attempts, they have all met with temporary failure. Either way, qmail-send should try delivery in the future. qmail-send may at its leisure try to deliver a message to a NOT DONE address. If the message is successfully delivered, qmail-send marks the address as DONE. If the delivery attempt meets with permanent failure, qmail-send first appends a note to bounce/457, creating bounce/457 if necessary; then it marks the address as DONE. Note that bounce/457 is not crashproof. qmail-send may handle bounce/457 at any time, as follows: it (1) injects a new bounce message, created from bounce/457 and mess/457; (2) deletes bounce/457. When all addresses in local/457 are DONE, qmail-send deletes local/457. Same for remote/457. When local/457 and remote/457 are gone, qmail-send eliminates the message, as follows. First, if bounce/457 exists, qmail-send handles it as described above. Once bounce/457 is definitely gone, qmail-send deletes info/457, moving to S2, and finally mess/457, moving to S1. 6. Cleanups If the computer crashes while qmail-queue is trying to queue a message, or while qmail-send is eliminating a message, the message may be left in state S2 or S3. When qmail-send sees a message in state S2 or S3---other than one it is currently eliminating!---where mess/457 is more than 36 hours old, it deletes intd/457 if that exists, then deletes mess/457. Note that any qmail-queue handling the message must be dead. Similarly, when qmail-send sees a file in the pid/ directory that is more than 36 hours old, it deletes it. Cleanups are not necessary if the computer crashes while qmail-send is delivering a message. At worst a message may be delivered twice. (There is no way for a distributed mail system to eliminate the possibility of duplication. What if an SMTP connection is broken just before the server acknowledges successful receipt of the message? The client must assume the worst and send the message again. Similarly, if the computer crashes just before qmail-send marks a message as DONE, the new qmail-send must assume the worst and send the message again. The usual solutions in the database literature---e.g., keeping log files---amount to saying that it's the recipient's computer's job to discard duplicate messages.) 7. Further notes Currently info/457 serves two purposes: first, it records the envelope sender; second, its modification time is used to decide when a message has been in the queue too long. In the future info/457 may store more information. Any non-backwards-compatible changes will be identified by version numbers. When qmail-queue has successfully placed a message into the queue, it pulls a trigger offered by qmail-send. Here is the current triggering mechanism: lock/trigger is a named pipe. Before scanning todo/, qmail-send opens lock/trigger O_NDELAY for reading. It then selects for readability on lock/trigger. qmail-queue pulls the trigger by writing a byte O_NDELAY to lock/trigger. This makes lock/trigger readable and wakes up qmail-send. Before scanning todo/ again, qmail-send closes and reopens lock/trigger. netqmail-1.06/qmail-pop3d.c0000644000076400007640000001371710724070436015146 0ustar nelsonnelson#include #include #include "commands.h" #include "sig.h" #include "getln.h" #include "stralloc.h" #include "substdio.h" #include "alloc.h" #include "open.h" #include "prioq.h" #include "scan.h" #include "fmt.h" #include "str.h" #include "exit.h" #include "maildir.h" #include "readwrite.h" #include "timeoutread.h" #include "timeoutwrite.h" void die() { _exit(0); } int saferead(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutread(1200,fd,buf,len); if (r <= 0) die(); return r; } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(1200,fd,buf,len); if (r <= 0) die(); return r; } char ssoutbuf[1024]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); char ssinbuf[128]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); void put(buf,len) char *buf; int len; { substdio_put(&ssout,buf,len); } void puts(s) char *s; { substdio_puts(&ssout,s); } void flush() { substdio_flush(&ssout); } void err(s) char *s; { puts("-ERR "); puts(s); puts("\r\n"); flush(); } void die_nomem() { err("out of memory"); die(); } void die_nomaildir() { err("this user has no $HOME/Maildir"); die(); } void die_scan() { err("unable to scan $HOME/Maildir"); die(); } void err_syntax() { err("syntax error"); } void err_unimpl(arg) char *arg; { err("unimplemented"); } void err_deleted() { err("already deleted"); } void err_nozero() { err("messages are counted from 1"); } void err_toobig() { err("not that many messages"); } void err_nosuch() { err("unable to open that message"); } void err_nounlink() { err("unable to unlink all deleted messages"); } void okay(arg) char *arg; { puts("+OK \r\n"); flush(); } void printfn(fn) char *fn; { fn += 4; put(fn,str_chr(fn,':')); } char strnum[FMT_ULONG]; stralloc line = {0}; void blast(ssfrom,limit) substdio *ssfrom; unsigned long limit; { int match; int inheaders = 1; for (;;) { if (getln(ssfrom,&line,&match,'\n') != 0) die(); if (!match && !line.len) break; if (match) --line.len; /* no way to pass this info over POP */ if (limit) if (!inheaders) if (!--limit) break; if (!line.len) inheaders = 0; else if (line.s[0] == '.') put(".",1); put(line.s,line.len); put("\r\n",2); if (!match) break; } put("\r\n.\r\n",5); flush(); } stralloc filenames = {0}; prioq pq = {0}; struct message { int flagdeleted; unsigned long size; char *fn; } *m; int numm; int last = 0; void getlist() { struct prioq_elt pe; struct stat st; int i; maildir_clean(&line); if (maildir_scan(&pq,&filenames,1,1) == -1) die_scan(); numm = pq.p ? pq.len : 0; m = (struct message *) alloc(numm * sizeof(struct message)); if (!m) die_nomem(); for (i = 0;i < numm;++i) { if (!prioq_min(&pq,&pe)) { numm = i; break; } prioq_delmin(&pq); m[i].fn = filenames.s + pe.id; m[i].flagdeleted = 0; if (stat(m[i].fn,&st) == -1) m[i].size = 0; else m[i].size = st.st_size; } } void pop3_stat(arg) char *arg; { int i; unsigned long total; total = 0; for (i = 0;i < numm;++i) if (!m[i].flagdeleted) total += m[i].size; puts("+OK "); put(strnum,fmt_uint(strnum,numm)); puts(" "); put(strnum,fmt_ulong(strnum,total)); puts("\r\n"); flush(); } void pop3_rset(arg) char *arg; { int i; for (i = 0;i < numm;++i) m[i].flagdeleted = 0; last = 0; okay(0); } void pop3_last(arg) char *arg; { puts("+OK "); put(strnum,fmt_uint(strnum,last)); puts("\r\n"); flush(); } void pop3_quit(arg) char *arg; { int i; for (i = 0;i < numm;++i) if (m[i].flagdeleted) { if (unlink(m[i].fn) == -1) err_nounlink(); } else if (str_start(m[i].fn,"new/")) { if (!stralloc_copys(&line,"cur/")) die_nomem(); if (!stralloc_cats(&line,m[i].fn + 4)) die_nomem(); if (!stralloc_cats(&line,":2,")) die_nomem(); if (!stralloc_0(&line)) die_nomem(); rename(m[i].fn,line.s); /* if it fails, bummer */ } okay(0); die(); } int msgno(arg) char *arg; { unsigned long u; if (!scan_ulong(arg,&u)) { err_syntax(); return -1; } if (!u) { err_nozero(); return -1; } --u; if (u >= numm) { err_toobig(); return -1; } if (m[u].flagdeleted) { err_deleted(); return -1; } return u; } void pop3_dele(arg) char *arg; { int i; i = msgno(arg); if (i == -1) return; m[i].flagdeleted = 1; if (i + 1 > last) last = i + 1; okay(0); } void list(i,flaguidl) int i; int flaguidl; { put(strnum,fmt_uint(strnum,i + 1)); puts(" "); if (flaguidl) printfn(m[i].fn); else put(strnum,fmt_ulong(strnum,m[i].size)); puts("\r\n"); } void dolisting(arg,flaguidl) char *arg; int flaguidl; { unsigned int i; if (*arg) { i = msgno(arg); if (i == -1) return; puts("+OK "); list(i,flaguidl); } else { okay(0); for (i = 0;i < numm;++i) if (!m[i].flagdeleted) list(i,flaguidl); puts(".\r\n"); } flush(); } void pop3_uidl(arg) char *arg; { dolisting(arg,1); } void pop3_list(arg) char *arg; { dolisting(arg,0); } substdio ssmsg; char ssmsgbuf[1024]; void pop3_top(arg) char *arg; { int i; unsigned long limit; int fd; i = msgno(arg); if (i == -1) return; arg += scan_ulong(arg,&limit); while (*arg == ' ') ++arg; if (scan_ulong(arg,&limit)) ++limit; else limit = 0; fd = open_read(m[i].fn); if (fd == -1) { err_nosuch(); return; } okay(0); substdio_fdbuf(&ssmsg,read,fd,ssmsgbuf,sizeof(ssmsgbuf)); blast(&ssmsg,limit); close(fd); } struct commands pop3commands[] = { { "quit", pop3_quit, 0 } , { "stat", pop3_stat, 0 } , { "list", pop3_list, 0 } , { "uidl", pop3_uidl, 0 } , { "dele", pop3_dele, 0 } , { "retr", pop3_top, 0 } , { "rset", pop3_rset, 0 } , { "last", pop3_last, 0 } , { "top", pop3_top, 0 } , { "noop", okay, 0 } , { 0, err_unimpl, 0 } } ; void main(argc,argv) int argc; char **argv; { sig_alarmcatch(die); sig_pipeignore(); if (!argv[1]) die_nomaildir(); if (chdir(argv[1]) == -1) die_nomaildir(); getlist(); okay(0); commands(&ssin,pop3commands); die(); } netqmail-1.06/auto_split.h0000644000076400007640000000011206541176434015200 0ustar nelsonnelson#ifndef AUTO_SPLIT_H #define AUTO_SPLIT_H extern int auto_split; #endif netqmail-1.06/gfrom.h0000644000076400007640000000007506541176434014137 0ustar nelsonnelson#ifndef GFROM_H #define GFROM_H extern int gfrom(); #endif netqmail-1.06/cdbmss.h0000644000076400007640000000032006541176434014271 0ustar nelsonnelson#ifndef CDBMSS_H #define CDBMSS_H #include "cdbmake.h" #include "substdio.h" struct cdbmss { char ssbuf[1024]; struct cdbmake cdbm; substdio ss; char packbuf[8]; uint32 pos; int fd; } ; #endif netqmail-1.06/PIC.local2ext0000644000076400007640000000301606541176434015104 0ustar nelsonnelson Original message: To: fred-sos Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to fred-sos@heaven.af.mil | From: joe@heaven.af.mil | To: fred-sos@heaven.af.mil | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, fred-sos@heaven.af.mil. | Is heaven.af.mil in locals? Yes. | Deliver locally to fred-sos@heaven.af.mil. V qmail-lspawn ./Mailbox | Look at mailbox name, fred-sos. | Is fred-sos listed in qmail-users? No. | Is there a fred-sos account? No. | Is there a fred account? Yes. | Is fred's uid nonzero? Yes. | Is ~fred visible to the qmailp user? Yes. | Is ~fred owned by fred? Yes. | Give control of the message to fred. | Run qmail-local. V qmail-local fred ~fred fred-sos - sos heaven.af.mil joe@heaven.af.mil ./Mailbox Does ~fred/.qmail-sos exist? Yes: "./Extramail". Write message to ./Extramail in mbox format. netqmail-1.06/TARGETS0000644000076400007640000001034706541176434013713 0ustar nelsonnelsonauto-ccld.sh make-load find-systype systype load make-compile compile fork.h qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o slurpclose.o make-makelib makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o case_starts.o case.a getln.o getln2.o getln.a subgetopt.o sgetopt.o getopt.a sig_alarm.o hassgprm.h sig_block.o hassgact.h sig_catch.o sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o sig.a open_append.o open_excl.o open_read.o open_trunc.o open_write.o open.a seek_cur.o seek_end.o seek_set.o seek_trunc.o seek.a hasflock.h lock_ex.o lock_exnb.o lock_un.o lock.a fd_copy.o fd_move.o fd.a haswaitp.h wait_pid.o wait_nohang.o wait.a env.o envread.o env.a stralloc_eady.o stralloc_pend.o stralloc_copy.o stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o stralloc_catb.o stralloc_arts.o stralloc.a alloc.o alloc_re.o alloc.a strerr_sys.o strerr_die.o strerr.a substdio.o substdi.o substdo.o subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o substdio_copy.o substdio.a error.o error_str.o error_temp.o error.a str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o byte_cr.o byte_zero.o str.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o scan_ulong.o scan_8long.o fs.a datetime.o datetime_un.o datetime.a auto-str.o auto-str auto_qmail.c auto_qmail.o auto-int8.o auto-int8 auto_patrn.c auto_patrn.o socket.lib qmail-local uint32.h qmail-lspawn.o select.h chkspawn.o auto-int.o auto-int auto_spawn.c auto_spawn.o chkspawn spawn.o chkshsgr.o chkshsgr hasshsgr.h prot.o coe.o cdb_hash.o cdb_unpack.o cdb_seek.o cdb.a auto-uid.o auto-uid auto-gid.o auto-gid auto_uids.c auto_uids.o qmail-lspawn qmail-getpw.o auto_break.c auto_break.o auto_usera.c auto_usera.o qmail-getpw qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o timeoutconn.o tcpto.o dns.o ip.o ipalloc.o hassalen.h ipme.o ndelay.o ndelay_off.o ndelay.a dns.lib qmail-remote qmail-rspawn.o tcpto_clean.o qmail-rspawn direntry.h qmail-clean.o fmtqfn.o auto_split.c auto_split.o qmail-clean qmail-send.o qsutil.o newfield.o prioq.o hasmkffo.h fifo.o hasnpbg1.h trigger.o readsubdir.o date822fmt.o qmail-send qmail-start.o qmail-start splogger.o syslog.lib splogger qmail-queue.o triggerpull.o qmail-queue qmail-inject.o headerbody.o hfield.o token822.o qmail-inject predate.o predate datemail mailsubj qmail-upq qmail-showctl.o qmail-showctl qmail-newu.o cdbmss.o cdbmake_pack.o cdbmake_hash.o cdbmake_add.o cdbmake.a qmail-newu qmail-pw2u.o qmail-pw2u qmail-qread.o qmail-qread qmail-qstat qmail-tcpto.o qmail-tcpto qmail-tcpok.o qmail-tcpok qmail-pop3d.o commands.o maildir.o qmail-pop3d qmail-popup.o qmail-popup qmail-qmqpc.o qmail-qmqpc qmail-qmqpd.o received.o qmail-qmqpd qmail-qmtpd.o rcpthosts.o qmail-qmtpd qmail-smtpd.o qmail-smtpd sendmail.o sendmail tcp-env.o remoteinfo.o tcp-env qmail-newmrh.o qmail-newmrh config config-fast dnscname.o dnsdoe.o dnscname dnsptr.o dnsptr dnsip.o dnsip dnsmxip.o dnsmxip dnsfq.o dnsfq hostname.o hostname ipmeprint.o ipmeprint qreceipt.o qreceipt qsmhook.o qsmhook qbiff.o qbiff forward.o forward preline.o preline condredirect.o condredirect bouncesaying.o bouncesaying except.o except maildirmake.o maildirmake maildir2mbox.o maildir2mbox maildirwatch.o maildirwatch qail elq pinq idedit.o idedit install-big.o install.o install-big hier.o install instcheck.o instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df binm3 binm3+df it qmail-local.0 qmail-lspawn.0 qmail-getpw.8 qmail-getpw.0 qmail-remote.0 qmail-rspawn.0 qmail-clean.0 qmail-send.8 qmail-send.0 qmail-start.8 qmail-start.0 splogger.0 qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.8 qmail-newu.0 qmail-pw2u.8 qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 qmail-smtpd.0 tcp-env.0 qmail-newmrh.8 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.7 qmail-limits.0 qmail-log.0 qmail-control.5 qmail-control.0 qmail-header.0 qmail-users.5 qmail-users.0 dot-qmail.5 dot-qmail.0 qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 envelopes.0 forgeries.0 man setup check netqmail-1.06/fd_move.30000644000076400007640000000076506541176434014365 0ustar nelsonnelson.TH fd_move 3 .SH NAME fd_move \- renumber a descriptor .SH SYNTAX .B #include int \fBfd_move\fP(\fIto\fR,\fIfrom\fR); int \fIto\fR; .br int \fIfrom\fR; .SH DESCRIPTION .B fd_move moves descriptor .I from to descriptor .IR to . If .I to was already open, .B fd_move closes it. If the move is successful, .B fd_move closes .IR from . Exception: if .I to and .I from are the same number, .B fd_move does nothing. .B fd_move returns 0 on success, -1 on error. .SH "SEE ALSO" dup(2), fd_copy(3) netqmail-1.06/sig_block.c0000644000076400007640000000120306541176434014746 0ustar nelsonnelson#include #include "sig.h" #include "hassgprm.h" void sig_block(sig) int sig; { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigaddset(&ss,sig); sigprocmask(SIG_BLOCK,&ss,(sigset_t *) 0); #else sigblock(1 << (sig - 1)); #endif } void sig_unblock(sig) int sig; { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigaddset(&ss,sig); sigprocmask(SIG_UNBLOCK,&ss,(sigset_t *) 0); #else sigsetmask(sigsetmask(~0) & ~(1 << (sig - 1))); #endif } void sig_blocknone() { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); #else sigsetmask(0); #endif } netqmail-1.06/dnsptr.c0000644000076400007640000000067206541176434014335 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "stralloc.h" #include "str.h" #include "scan.h" #include "dns.h" #include "dnsdoe.h" #include "ip.h" #include "exit.h" stralloc sa = {0}; struct ip_address ip; void main(argc,argv) int argc; char **argv; { if (!argv[1]) _exit(100); ip_scan(argv[1],&ip); dns_init(0); dnsdoe(dns_ptr(&sa,&ip)); substdio_putflush(subfdout,sa.s,sa.len); substdio_putsflush(subfdout,"\n"); _exit(0); } netqmail-1.06/coe.30000644000076400007640000000060006541176434013500 0ustar nelsonnelson.TH coe 3 .SH NAME coe \- set close-on-exec flag for a descriptor .SH SYNTAX .B #include int \fBcoe\fP(\fIfd\fR); int \fIfd\fR; .SH DESCRIPTION .B coe sets the close-on-exec flag for file descriptor .IR fd , returning 0 if it was successful or -1 on error. If .B coe is successful, .I fd will be closed when the process calls .BR execve . .SH "SEE ALSO" execve(2), fcntl(2) netqmail-1.06/install-big.c0000644000076400007640000003603206541176434015227 0ustar nelsonnelson#include "auto_qmail.h" #include "auto_split.h" #include "auto_uids.h" #include "fmt.h" #include "fifo.h" char buf[100 + FMT_ULONG]; void dsplit(base,uid,mode) char *base; /* must be under 100 bytes */ int uid; int mode; { char *x; unsigned long i; d(auto_qmail,base,uid,auto_gidq,mode); for (i = 0;i < auto_split;++i) { x = buf; x += fmt_str(x,base); x += fmt_str(x,"/"); x += fmt_ulong(x,i); *x = 0; d(auto_qmail,buf,uid,auto_gidq,mode); } } void hier() { h(auto_qmail,auto_uido,auto_gidq,0755); d(auto_qmail,"control",auto_uido,auto_gidq,0755); d(auto_qmail,"users",auto_uido,auto_gidq,0755); d(auto_qmail,"bin",auto_uido,auto_gidq,0755); d(auto_qmail,"boot",auto_uido,auto_gidq,0755); d(auto_qmail,"doc",auto_uido,auto_gidq,0755); d(auto_qmail,"man",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat7",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat8",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man1",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man5",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man7",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755); d(auto_qmail,"alias",auto_uida,auto_gidq,02755); d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); dsplit("queue/mess",auto_uidq,0750); dsplit("queue/info",auto_uids,0700); dsplit("queue/local",auto_uids,0700); dsplit("queue/remote",auto_uids,0700); d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.maildir",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.mbox",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.vsm",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","TEST.deliver",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","TEST.receive",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","REMOVE.sendmail",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","REMOVE.binmail",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2alias",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2ext",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2local",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2rem",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2virt",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.nullclient",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-control.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-control.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-header.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-header.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-log.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-log.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-users.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","qmail-limits.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","qmail-limits.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","bouncesaying.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildirwatch.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildirwatch.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","mailsubj.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","mailsubj.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","qreceipt.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","qreceipt.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","qbiff.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","qbiff.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","preline.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","preline.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","tcp-env.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","tcp-env.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-local.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-local.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-lspawn.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-lspawn.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-getpw.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-getpw.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-remote.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-remote.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-rspawn.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-rspawn.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-clean.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-clean.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-send.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-send.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-start.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-start.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","splogger.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","splogger.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-queue.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-queue.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-inject.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-pw2u.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qread.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qread.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qstat.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qstat.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-tcpok.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-tcpok.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-tcpto.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-tcpto.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-pop3d.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-pop3d.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-popup.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-popup.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmqpc.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmqpc.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmqpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmqpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmtpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmtpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-smtpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644); c(auto_qmail,"bin","dot-forward",auto_uido,auto_gidq,0755); c(auto_qmail,"man/man1","dot-forward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","dot-forward.0",auto_uido,auto_gidq,0644); d(auto_qmail,"doc/fastforward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","fastforward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","printforward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","setforward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","newaliases",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","printmaillist",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","setmaillist",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","newinclude",auto_uido,auto_gidq,0755); c(auto_qmail,"doc/fastforward","ALIASES",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","fastforward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","printforward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","setforward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","newaliases.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","printmaillist.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","setmaillist.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","newinclude.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","fastforward.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","printforward.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","setforward.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","newaliases.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","printmaillist.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","setmaillist.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","newinclude.0",auto_uido,auto_gidq,0644); } netqmail-1.06/INSTALL.ids0000644000076400007640000000554006541176434014465 0ustar nelsonnelsonHere's how to set up the qmail groups and the qmail users. On some systems there are commands that make this easy. Solaris and Linux: # groupadd nofiles # useradd -g nofiles -d /var/qmail/alias alias # useradd -g nofiles -d /var/qmail qmaild # useradd -g nofiles -d /var/qmail qmaill # useradd -g nofiles -d /var/qmail qmailp # groupadd qmail # useradd -g qmail -d /var/qmail qmailq # useradd -g qmail -d /var/qmail qmailr # useradd -g qmail -d /var/qmail qmails FreeBSD 2.2: # pw groupadd nofiles # pw useradd alias -g nofiles -d /var/qmail/alias -s /nonexistent # pw useradd qmaild -g nofiles -d /var/qmail -s /nonexistent # pw useradd qmaill -g nofiles -d /var/qmail -s /nonexistent # pw useradd qmailp -g nofiles -d /var/qmail -s /nonexistent # pw groupadd qmail # pw useradd qmailq -g qmail -d /var/qmail -s /nonexistent # pw useradd qmailr -g qmail -d /var/qmail -s /nonexistent # pw useradd qmails -g qmail -d /var/qmail -s /nonexistent BSDI 2.0: # addgroup nofiles # adduser -g nofiles -H/var/qmail/alias -G,,, -s/dev/null -P'*' alias # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmaild # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmaill # adduser -g nofiles -H/var/qmail -G,,, -s/dev/null -P'*' qmailp # addgroup qmail # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmailq # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmailr # adduser -g qmail -H/var/qmail -G,,, -s/dev/null -P'*' qmails AIX: # mkgroup -A nofiles # mkuser pgrp=nofiles home=/var/qmail/alias shell=/bin/true alias # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmaild # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmaill # mkuser pgrp=nofiles home=/var/qmail shell=/bin/true qmailp # mkgroup -A qmail # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmailq # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmailr # mkuser pgrp=qmail home=/var/qmail shell=/bin/true qmails On other systems, you will have to edit /etc/group and /etc/passwd manually. First add two new lines to /etc/group, something like qmail:*:2107: nofiles:*:2108: where 2107 and 2108 are different from the other gids in /etc/group. Next (using vipw) add six new lines to /etc/passwd, something like alias:*:7790:2108::/var/qmail/alias:/bin/true qmaild:*:7791:2108::/var/qmail:/bin/true qmaill:*:7792:2108::/var/qmail:/bin/true qmailp:*:7793:2108::/var/qmail:/bin/true qmailq:*:7794:2107::/var/qmail:/bin/true qmailr:*:7795:2107::/var/qmail:/bin/true qmails:*:7796:2107::/var/qmail:/bin/true where 7790 through 7796 are _new_ uids, 2107 is the qmail gid, and 2108 is the nofiles gid. Make sure you use the nofiles gid for qmaild, qmaill, qmailp, and alias, and the qmail gid for qmailq, qmailr, and qmails. netqmail-1.06/direntry.30000644000076400007640000000116106541176434014575 0ustar nelsonnelson.TH direntry 3 .SH NAME direntry \- read directory entries .SH SYNTAX .B #include DIR *\fBopendir\fP(\fIfn\fR); struct direntry *\fBreaddir\fP(\fIdir\fP); void \fBclosedir\fP(\fIdir\fP); DIR *\fIdir\fR; .br char *\fIfn\fR; .SH DESCRIPTION The point of .B direntry.h is to provide a uniform interface to BSD's .B sys/dir.h and POSIX's .BR dirent.h . The .B readdir interface is highly unsatisfactory. It does not distinguish between I/O errors and end-of-directory. It uses .BR malloc . The return type for .B closedir varies: some implementations return the .B close return value. .SH "SEE ALSO" readdir(3) netqmail-1.06/splogger.c0000644000076400007640000000316206541176434014642 0ustar nelsonnelson#include #include #include #include "error.h" #include "substdio.h" #include "subfd.h" #include "exit.h" #include "str.h" #include "scan.h" #include "fmt.h" char buf[800]; /* syslog truncates long lines (or crashes); GPACIC */ int bufpos = 0; /* 0 <= bufpos < sizeof(buf) */ int flagcont = 0; int priority; /* defined if flagcont */ char stamp[FMT_ULONG + FMT_ULONG + 3]; /* defined if flagcont */ void stamp_make() { struct timeval tv; char *s; gettimeofday(&tv,(struct timezone *) 0); s = stamp; s += fmt_ulong(s,(unsigned long) tv.tv_sec); *s++ = '.'; s += fmt_uint0(s,(unsigned int) tv.tv_usec,6); *s = 0; } void flush() { if (bufpos) { buf[bufpos] = 0; if (flagcont) syslog(priority,"%s+%s",stamp,buf); /* logger folds invisibly; GPACIC */ else { stamp_make(); priority = LOG_INFO; if (str_start(buf,"warning:")) priority = LOG_WARNING; if (str_start(buf,"alert:")) priority = LOG_ALERT; syslog(priority,"%s %s",stamp,buf); flagcont = 1; } } bufpos = 0; } void main(argc,argv) int argc; char **argv; { char ch; if (argv[1]) if (argv[2]) { unsigned long facility; scan_ulong(argv[2],&facility); openlog(argv[1],0,facility << 3); } else openlog(argv[1],0,LOG_MAIL); else openlog("splogger",0,LOG_MAIL); for (;;) { if (substdio_get(subfdin,&ch,1) < 1) _exit(0); if (ch == '\n') { flush(); flagcont = 0; continue; } if (bufpos == sizeof(buf) - 1) flush(); if ((ch < 32) || (ch > 126)) ch = '?'; /* logger truncates at 0; GPACIC */ buf[bufpos++] = ch; } } netqmail-1.06/dnsmxip.c0000644000076400007640000000142006541176434014475 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "stralloc.h" #include "fmt.h" #include "dns.h" #include "dnsdoe.h" #include "ip.h" #include "ipalloc.h" #include "now.h" #include "exit.h" char temp[IPFMT + FMT_ULONG]; stralloc sa = {0}; ipalloc ia = {0}; void main(argc,argv) int argc; char **argv; { int j; unsigned long r; if (!argv[1]) _exit(100); if (!stralloc_copys(&sa,argv[1])) { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); } r = now() + getpid(); dns_init(0); dnsdoe(dns_mxip(&ia,&sa,r)); for (j = 0;j < ia.len;++j) { substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip)); substdio_puts(subfdout," "); substdio_put(subfdout,temp,fmt_ulong(temp,(unsigned long) ia.ix[j].pref)); substdio_putsflush(subfdout,"\n"); } _exit(0); } netqmail-1.06/preline.c0000644000076400007640000000436206541176434014461 0ustar nelsonnelson#include "fd.h" #include "sgetopt.h" #include "readwrite.h" #include "strerr.h" #include "substdio.h" #include "exit.h" #include "fork.h" #include "wait.h" #include "env.h" #include "sig.h" #include "error.h" #define FATAL "preline: fatal: " void die_usage() { strerr_die1x(100,"preline: usage: preline cmd [ arg ... ]"); } int flagufline = 1; char *ufline; int flagrpline = 1; char *rpline; int flagdtline = 1; char *dtline; char outbuf[SUBSTDIO_OUTSIZE]; char inbuf[SUBSTDIO_INSIZE]; substdio ssout = SUBSTDIO_FDBUF(write,1,outbuf,sizeof outbuf); substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); void main(argc,argv) int argc; char **argv; { int opt; int pi[2]; int pid; int wstat; sig_pipeignore(); if (!(ufline = env_get("UFLINE"))) die_usage(); if (!(rpline = env_get("RPLINE"))) die_usage(); if (!(dtline = env_get("DTLINE"))) die_usage(); while ((opt = getopt(argc,argv,"frdFRD")) != opteof) switch(opt) { case 'f': flagufline = 0; break; case 'r': flagrpline = 0; break; case 'd': flagdtline = 0; break; case 'F': flagufline = 1; break; case 'R': flagrpline = 1; break; case 'D': flagdtline = 1; break; default: die_usage(); } argc -= optind; argv += optind; if (!*argv) die_usage(); if (pipe(pi) == -1) strerr_die2sys(111,FATAL,"unable to create pipe: "); pid = fork(); if (pid == -1) strerr_die2sys(111,FATAL,"unable to fork: "); if (pid == 0) { close(pi[1]); if (fd_move(0,pi[0]) == -1) strerr_die2sys(111,FATAL,"unable to set up fds: "); sig_pipedefault(); execvp(*argv,argv); strerr_die4sys(error_temp(errno) ? 111 : 100,FATAL,"unable to run ",*argv,": "); } close(pi[0]); if (fd_move(1,pi[1]) == -1) strerr_die2sys(111,FATAL,"unable to set up fds: "); if (flagufline) substdio_bputs(&ssout,ufline); if (flagrpline) substdio_bputs(&ssout,rpline); if (flagdtline) substdio_bputs(&ssout,dtline); if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to copy input: "); substdio_flush(&ssout); close(1); if (wait_pid(&wstat,pid) == -1) strerr_die2sys(111,FATAL,"wait failed: "); if (wait_crashed(wstat)) strerr_die2x(111,FATAL,"child crashed"); _exit(wait_exitcode(wstat)); } netqmail-1.06/qmail-inject.80000644000076400007640000001273406541176434015327 0ustar nelsonnelson.TH qmail-inject 8 .SH NAME qmail-inject \- preprocess and send a mail message .SH SYNOPSIS .B qmail-inject [ .B \-nNaAhH ] [ .B \-f\fIsender ] [ .I recip ... ] .SH DESCRIPTION .B qmail-inject reads a mail message from its standard input, adds appropriate information to the message header, and invokes .B qmail-queue to send the message to one or more recipients. See .B qmail-header(5) for information on how .B qmail-inject rewrites header fields. .B qmail-inject normally exits 0. It exits 100 if it was invoked improperly or if there is a severe syntax error in the message. It exits 111 for temporary errors. .SH "ENVIRONMENT VARIABLES" For the convenience of users who do not run .B qmail-inject directly, .B qmail-inject takes many options through environment variables. The user name in the .B From header field is set by .BR QMAILUSER , .BR MAILUSER , .BR USER , or .BR LOGNAME , whichever comes first. The host name is normally set by the .I defaulthost control but can be overridden with .B QMAILHOST or .BR MAILHOST . The personal name is .BR QMAILNAME , .BR MAILNAME , or .BR NAME . The default envelope sender address is the same as the default .B From address, but it can be overridden with .B QMAILSUSER and .BR QMAILSHOST . It may also be modified by the .B r and .B m letters described below. Bounces will be sent to this address. If .B QMAILMFTFILE is set, .B qmail-inject reads a list of mailing list addresses, one per line, from that file. If To+Cc includes one of those addresses (without regard to case), .B qmail-inject adds a Mail-Followup-To field with all the To+Cc addresses. .B qmail-inject does not add Mail-Followup-To to a message that already has one. The .B QMAILINJECT environment variable can contain any of the following letters: .TP .B c Use address-comment style for the .B From field. Normally .B qmail-inject uses name-address style. .TP .B s Do not look at any incoming .B Return-Path field. Normally, if .B Return-Path is supplied, it sets the envelope sender address, overriding all environment variables. .B Return-Path is deleted in any case. .TP .B f Delete any incoming .B From field. Normally, if .B From is supplied, it overrides the usual .B From field created by .BR qmail-inject . .TP .B i Delete any incoming .B Message-ID field. Normally, if .B Message-ID is supplied, it overrides the usual .B Message-ID field created by .BR qmail-inject . .TP .B r Use a per-recipient VERP. .B qmail-inject will append each recipient address to the envelope sender of the copy going to that recipient. .TP .B m Use a per-message VERP. .B qmail-inject will append the current date and process ID to the envelope sender. .SH OPTIONS .TP .B \-a Send the message to all addresses given as .I recip arguments; do not use header recipient addresses. .TP .B \-h Send the message to all header recipient addresses. For non-forwarded messages, this means the addresses listed under .BR To , .BR Cc , .BR Bcc , .BR Apparently-To . For forwarded messages, this means the addresses listed under .BR Resent-To , .BR Resent-Cc , .BR Resent-Bcc . Do not use any .I recip arguments. .TP .B \-A (Default.) Send the message to all addresses given as .I recip arguments. If no .I recip arguments are supplied, send the message to all header recipient addresses. .TP .B \-H Send the message to all header recipient addresses, and to all addresses given as .I recip arguments. .TP .B \-f\fIsender Pass .I sender to .B qmail-queue as the envelope sender address. This overrides .B Return-Path and all environment variables. .TP .B \-N (Default.) Feed the resulting message to .BR qmail-queue . .TP .B \-n Print the message rather than feeding it to .BR qmail-queue . .SH "CONTROL FILES" .TP 5 .I defaultdomain Default domain name. Default: .IR me , if that is supplied; otherwise the literal name .BR defaultdomain , which is probably not what you want. .B qmail-inject adds this name to any host name without dots, including .I defaulthost if .I defaulthost does not have dots. (Exception: see .IR plusdomain .) The .B QMAILDEFAULTDOMAIN environment variable overrides .IR defaultdomain . .TP 5 .I defaulthost Default host name. Default: .IR me , if that is supplied; otherwise the literal name .BR defaulthost , which is probably not what you want. .B qmail-inject adds this name to any address without a host name. .I defaulthost need not be the current host's name. For example, you may prefer that outgoing mail show just your domain name. The .B QMAILDEFAULTHOST environment variable overrides .IR defaulthost . .TP 5 .I idhost Host name for Message-IDs. Default: .IR me , if that is supplied; otherwise the literal name .BR idhost , which is certainly not what you want. .I idhost need not be the current host's name. For example, you may prefer to use fake host names in Message-IDs. However, .I idhost must be a fully-qualified name within your domain, and each host in your domain should use a different .IR idhost . The .B QMAILIDHOST environment variable overrides .IR idhost . .TP 5 .I plusdomain Plus domain name. Default: .IR me , if that is supplied; otherwise the literal name .BR plusdomain , which is probably not what you want. .B qmail-inject adds this name to any host name that ends with a plus sign, including .I defaulthost if .I defaulthost ends with a plus sign. If a host name does not have dots but ends with a plus sign, .B qmail-inject uses .IR plusdomain , not .IR defaultdomain . The .B QMAILPLUSDOMAIN environment variable overrides .IR plusdomain . .SH "SEE ALSO" addresses(5), qmail-control(5), qmail-header(5), qmail-queue(8) netqmail-1.06/sig_term.c0000644000076400007640000000037006541176434014627 0ustar nelsonnelson#include #include "sig.h" void sig_termblock() { sig_block(SIGTERM); } void sig_termunblock() { sig_unblock(SIGTERM); } void sig_termcatch(f) void (*f)(); { sig_catch(SIGTERM,f); } void sig_termdefault() { sig_catch(SIGTERM,SIG_DFL); } netqmail-1.06/env.h0000644000076400007640000000044006541176434013611 0ustar nelsonnelson#ifndef ENV_H #define ENV_H extern int env_isinit; extern int env_init(); extern int env_put(); extern int env_put2(); extern int env_unset(); extern /*@null@*/char *env_get(); extern char *env_pick(); extern void env_clear(); extern char *env_findeq(); extern char **environ; #endif netqmail-1.06/fork.h10000644000076400007640000000011506541176434014042 0ustar nelsonnelson#ifndef FORK_H #define FORK_H extern int fork(); #define vfork fork #endif netqmail-1.06/error.h0000644000076400007640000000066010724070436014147 0ustar nelsonnelson#ifndef ERROR_H #define ERROR_H #include extern int error_intr; extern int error_nomem; extern int error_noent; extern int error_txtbsy; extern int error_io; extern int error_exist; extern int error_timeout; extern int error_inprogress; extern int error_wouldblock; extern int error_again; extern int error_pipe; extern int error_perm; extern int error_acces; extern char *error_str(); extern int error_temp(); #endif netqmail-1.06/ipalloc.h0000644000076400007640000000037006541176434014446 0ustar nelsonnelson#ifndef IPALLOC_H #define IPALLOC_H #include "ip.h" struct ip_mx { struct ip_address ip; int pref; } ; #include "gen_alloc.h" GEN_ALLOC_typedef(ipalloc,struct ip_mx,ix,len,a) extern int ipalloc_readyplus(); extern int ipalloc_append(); #endif netqmail-1.06/qbiff.c0000644000076400007640000000555406541176434014116 0ustar nelsonnelson#include #include #include #ifndef UTMP_FILE #ifdef _PATH_UTMP #define UTMP_FILE _PATH_UTMP #else #define UTMP_FILE "/etc/utmp" #endif #endif #include "readwrite.h" #include "stralloc.h" #include "substdio.h" #include "subfd.h" #include "open.h" #include "byte.h" #include "str.h" #include "headerbody.h" #include "hfield.h" #include "env.h" #include "exit.h" substdio ssutmp; char bufutmp[sizeof(struct utmp) * 16]; int fdutmp; substdio sstty; char buftty[1024]; int fdtty; struct utmp ut; char line[sizeof(ut.ut_line) + 1]; stralloc woof = {0}; stralloc tofrom = {0}; stralloc text = {0}; void doit(s,n) char *s; int n; { if (!stralloc_catb(&text,s,n)) _exit(0); if (text.len > 78) text.len = 78; } void dobody(h) stralloc *h; { doit(h->s,h->len); } void doheader(h) stralloc *h; { int i; if (hfield_known(h->s,h->len) == H_SUBJECT) { i = hfield_skipname(h->s,h->len); doit(h->s + i,h->len - i); } } void finishheader() { ; } void main() { char *user; char *sender; char *userext; struct stat st; int i; if (chdir("/dev") == -1) _exit(0); if (!(user = env_get("USER"))) _exit(0); if (!(sender = env_get("SENDER"))) _exit(0); if (!(userext = env_get("LOCAL"))) _exit(0); if (str_len(user) > sizeof(ut.ut_name)) _exit(0); if (!stralloc_copys(&tofrom,"*** TO <")) _exit(0); if (!stralloc_cats(&tofrom,userext)) _exit(0); if (!stralloc_cats(&tofrom,"> FROM <")) _exit(0); if (!stralloc_cats(&tofrom,sender)) _exit(0); if (!stralloc_cats(&tofrom,">")) _exit(0); for (i = 0;i < tofrom.len;++i) if ((tofrom.s[i] < 32) || (tofrom.s[i] > 126)) tofrom.s[i] = '_'; if (!stralloc_copys(&text," ")) _exit(0); if (headerbody(subfdin,doheader,finishheader,dobody) == -1) _exit(0); for (i = 0;i < text.len;++i) if ((text.s[i] < 32) || (text.s[i] > 126)) text.s[i] = '/'; if (!stralloc_copys(&woof,"\015\n\007")) _exit(0); if (!stralloc_cat(&woof,&tofrom)) _exit(0); if (!stralloc_cats(&woof,"\015\n")) _exit(0); if (!stralloc_cat(&woof,&text)) _exit(0); if (!stralloc_cats(&woof,"\015\n")) _exit(0); fdutmp = open_read(UTMP_FILE); if (fdutmp == -1) _exit(0); substdio_fdbuf(&ssutmp,read,fdutmp,bufutmp,sizeof(bufutmp)); while (substdio_get(&ssutmp,&ut,sizeof(ut)) == sizeof(ut)) if (!str_diffn(ut.ut_name,user,sizeof(ut.ut_name))) { byte_copy(line,sizeof(ut.ut_line),ut.ut_line); line[sizeof(ut.ut_line)] = 0; if (line[0] == '/') continue; if (!line[0]) continue; if (line[str_chr(line,'.')]) continue; fdtty = open_append(line); if (fdtty == -1) continue; if (fstat(fdtty,&st) == -1) { close(fdtty); continue; } if (!(st.st_mode & 0100)) { close(fdtty); continue; } if (st.st_uid != getuid()) { close(fdtty); continue; } substdio_fdbuf(&sstty,write,fdtty,buftty,sizeof(buftty)); substdio_putflush(&sstty,woof.s,woof.len); close(fdtty); } _exit(0); } netqmail-1.06/dnsdoe.c0000644000076400007640000000056206541176434014275 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "exit.h" #include "dns.h" #include "dnsdoe.h" void dnsdoe(r) int r; { switch (r) { case DNS_HARD: substdio_putsflush(subfderr,"hard error\n"); _exit(100); case DNS_SOFT: substdio_putsflush(subfderr,"soft error\n"); _exit(111); case DNS_MEM: substdio_putsflush(subfderr,"out of memory\n"); _exit(111); } } netqmail-1.06/INSTALL.mbox0000644000076400007640000000456406541176434014660 0ustar nelsonnelsonThe qmail package includes a local delivery agent, qmail-local, which provides user-controlled mailing lists, cross-host alias loop detection, and many other important qmail features. There's one important difference between qmail-local and binmail: qmail-local delivers mail by default into ~user/Mailbox, rather than /var/spool/mail/user. It uses mbox format, with lockf locking on systems that don't have flock (HP/UX, Solaris), and flock locking otherwise. This file explains how to switch your system to ~user/Mailbox. You aren't required to do this; for further discussion of /var/spool/mail, and an explanation of how to continue using binmail for local deliveries, see INSTALL.vsm. The basic procedure for switching to ~user/Mailbox is simple: * Move each /var/spool/mail/user to ~user/Mailbox. For safety, do this in single-user mode. * As root, set up a symbolic link from /var/spool/mail/user to ~user/Mailbox for each user. /var/spool/mail should be mode 1777, so users will not be able to accidentally remove these links. A few mail programs are unable to handle symbolic links, so you will have to configure them to look at ~user/Mailbox directly: * procmail: Change SYSTEM_MBOX in config.h and recompile; or, with recent versions, define MAILSPOOLHOME in src/authenticate.c. An alternative to symbolic links is hlfsd. Consult the documentation for hlfsd if it is included in your operating system. If /var/spool/mail is large, you can gain extra speed by configuring all your mail software to look at ~user/Mailbox directly: * Most MUAs: Put ``setenv MAIL $HOME/Mailbox'' in your system-wide .cshrc and ``MAIL=$HOME/Mailbox; export MAIL'' in your system-wide .profile. * elm: Change "mailbox" to "Mailbox" around line 388 of newmbox.c and recompile. (elm looks at $MAIL, but without this change elm will fail if two users try to read mail simultaneously.) * pine: Put ``inbox-path=Mailbox'' in your system-wide pine.conf. (For pine versions more recent than 3.91, see also FAQ 6.2.) * qpopper 2.2: Change /.mail to /Mailbox in pop_dropcopy.c and recompile with -DHOMEDIRMAIL in CFLAGS. Some vendors, in a misguided attempt to solve the security problems of /var/spool/mail, have made all their mail software setgid mail. After you move the mailboxes, you can---and, for security, should---remove those setgid-mail bits. netqmail-1.06/tcp-environ.50000644000076400007640000000237206541176434015210 0ustar nelsonnelson.TH tcp-environ 5 .SH NAME tcp-environ \- TCP-related environment variables .SH DESCRIPTION The following environment variables describe a TCP connection. They are set up by .BR tcp-env , .BR tcpclient , and .BR tcpserver . Note that .BR TCPLOCALHOST , .BR TCPREMOTEHOST , and .B TCPREMOTEINFO can contain arbitrary characters. .TP 5 PROTO The string .BR TCP . .TP 5 TCPLOCALHOST The domain name of the local host, with uppercase letters converted to lowercase. If there is no currently available domain name for the local IP address, .B TCPLOCALHOST is not set. .TP 5 TCPLOCALIP The IP address of the local host, in dotted-decimal form. .TP 5 TCPLOCALPORT The local TCP port number, in decimal. .TP 5 TCPREMOTEHOST The domain name of the remote host, with uppercase letters converted to lowercase. If there is no currently available domain name for the remote IP address, .B TCPREMOTEHOST is not set. .TP 5 TCPREMOTEINFO A connection-specific string, perhaps a username, supplied by the remote host via 931/1413/IDENT/TAP. If the remote host did not supply connection information, .B TCPREMOTEINFO is not set. .TP 5 TCPREMOTEIP The IP address of the remote host. .TP 5 TCPREMOTEPORT The remote TCP port number. .SH "SEE ALSO" tcpclient(1), tcpserver(1), tcp-env(1), tcp(4) netqmail-1.06/INSTALL.ctl0000644000076400007640000000314606541176434014470 0ustar nelsonnelsonAs you've seen, qmail has essentially no pre-compilation configuration. You should never have to recompile it unless you want to change the qmail home directory, usernames, or uids. qmail does allow quite a bit of easy post-installation configuration. If you care how your machine greets other machines via SMTP, for example, you can put an appropriate line into /var/qmail/control/smtpgreeting. But this is all optional---if control/smtpgreeting doesn't exist, qmail will do something reasonable by default. You shouldn't worry much about configuration right now. You can always come back and tune things later. There's one big exception. You MUST tell qmail your hostname. Just run the config-fast script: # ./config-fast your.full.host.name config-fast puts your.full.host.name into control/me. It also puts it into control/locals and control/rcpthosts, so that qmail will accept mail for your.full.host.name. You can instead use the config script, which looks up your host name in DNS: # ./config config also looks up your local IP addresses in DNS to decide which hosts to accept mail for. (Why doesn't qmail do these lookups on the fly? This was a deliberate design decision. qmail does all its local functions---header rewriting, checking if a recipient is local, etc.---without talking to the network. The point is that qmail can continue accepting and delivering local mail even if your network connection goes down.) Next, read through FAQ for information on setting up optional features like masquerading. If you really want to learn right now what all the configuration possibilities are, see qmail-control.0. netqmail-1.06/dns.h0000644000076400007640000000026006541176434013605 0ustar nelsonnelson#ifndef DNS_H #define DNS_H #define DNS_SOFT -1 #define DNS_HARD -2 #define DNS_MEM -3 void dns_init(); int dns_cname(); int dns_mxip(); int dns_ip(); int dns_ptr(); #endif netqmail-1.06/myctime.h0000644000076400007640000000010506541176434014466 0ustar nelsonnelson#ifndef MYCTIME_H #define MYCTIME_H extern char *myctime(); #endif netqmail-1.06/quote.c0000644000076400007640000000336206541176434014157 0ustar nelsonnelson#include "stralloc.h" #include "str.h" #include "quote.h" /* quote() encodes a box as per rfc 821 and rfc 822, while trying to do as little quoting as possible. no, 821 and 822 don't have the same encoding. they're not even close. no special encoding here for bytes above 127. */ static char ok[128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 ,0,7,0,7,7,7,7,7,0,0,7,7,0,7,7,7 ,7,7,7,7,7,7,7,7,7,7,0,0,0,7,0,7 ,0,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 ,7,7,7,7,7,7,7,7,7,7,7,0,0,0,7,7 ,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 ,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,0 } ; static int doit(saout,sain) stralloc *saout; stralloc *sain; { char ch; int i; int j; if (!stralloc_ready(saout,sain->len * 2 + 2)) return 0; j = 0; saout->s[j++] = '"'; for (i = 0;i < sain->len;++i) { ch = sain->s[i]; if ((ch == '\r') || (ch == '\n') || (ch == '"') || (ch == '\\')) saout->s[j++] = '\\'; saout->s[j++] = ch; } saout->s[j++] = '"'; saout->len = j; return 1; } int quote_need(s,n) char *s; unsigned int n; { unsigned char uch; int i; if (!n) return 1; for (i = 0;i < n;++i) { uch = s[i]; if (uch >= 128) return 1; if (!ok[uch]) return 1; } if (s[0] == '.') return 1; if (s[n - 1] == '.') return 1; for (i = 0;i < n - 1;++i) if (s[i] == '.') if (s[i + 1] == '.') return 1; return 0; } int quote(saout,sain) stralloc *saout; stralloc *sain; { if (quote_need(sain->s,sain->len)) return doit(saout,sain); return stralloc_copy(saout,sain); } static stralloc foo = {0}; int quote2(sa,s) stralloc *sa; char *s; { int j; if (!*s) return stralloc_copys(sa,s); j = str_rchr(s,'@'); if (!stralloc_copys(&foo,s)) return 0; if (!s[j]) return quote(sa,&foo); foo.len = j; if (!quote(sa,&foo)) return 0; return stralloc_cats(sa,s + j); } netqmail-1.06/stralloc_copy.c0000644000076400007640000000024306541176434015672 0ustar nelsonnelson#include "byte.h" #include "stralloc.h" int stralloc_copy(sato,safrom) stralloc *sato; stralloc *safrom; { return stralloc_copyb(sato,safrom->s,safrom->len); } netqmail-1.06/idedit.c0000644000076400007640000000603306541176434014262 0ustar nelsonnelson#include #include #include #include "readwrite.h" #include "exit.h" #include "scan.h" #include "fmt.h" #include "strerr.h" #include "open.h" #include "seek.h" #include "fork.h" #define FATAL "idedit: fatal: " #define WARNING "idedit: warning: " int fd; void byte(pos,value) char *pos; unsigned int value; { unsigned long u; unsigned char ch; if (pos[scan_ulong(pos,&u)]) return; if (seek_set(fd,(seek_pos) u) == -1) strerr_die2sys(111,FATAL,"unable to seek: "); ch = value; if (write(fd,&ch,1) != 1) strerr_die2sys(111,FATAL,"unable to write: "); } char *args[10]; void run() { int pid; int wstat; pid = fork(); if (pid == -1) strerr_die2sys(111,FATAL,"unable to fork: "); if (pid == 0) { execv(*args,args); strerr_die4sys(111,WARNING,"unable to run ",*args,": "); } if (wait_pid(&wstat,pid) != pid) strerr_die2sys(111,FATAL,"waitpid surprise"); } void u(account,group,home,pos0,pos1,pos2,pos3) char *account; char *group; char *home; char *pos0; char *pos1; char *pos2; char *pos3; { struct passwd *pw; unsigned int value; pw = getpwnam(account); if (!pw && group) { args[0] = "add-account"; args[1] = account; args[2] = group; args[3] = home; args[4] = 0; run(); pw = getpwnam(account); } if (!pw) strerr_die3x(111,FATAL,"unable to find uid for ",account); value = pw->pw_uid; byte(pos0,value); value >>= 8; byte(pos1,value); value >>= 8; byte(pos2,value); value >>= 8; byte(pos3,value); value >>= 8; if (value) strerr_die3x(111,FATAL,"excessively large uid for ",account); } void g(group,pos0,pos1,pos2,pos3) char *group; char *pos0; char *pos1; char *pos2; char *pos3; { struct group *gr; unsigned int value; gr = getgrnam(group); if (!gr) { args[0] = "add-group"; args[1] = group; args[2] = 0; run(); gr = getgrnam(group); } if (!gr) strerr_die3x(111,FATAL,"unable to find gid for ",group); value = gr->gr_gid; byte(pos0,value); value >>= 8; byte(pos1,value); value >>= 8; byte(pos2,value); value >>= 8; byte(pos3,value); value >>= 8; if (value) strerr_die3x(111,FATAL,"excessively large gid for ",group); } void main(argc,argv) int argc; char **argv; { if (argc < 42) _exit(100); fd = open_write(argv[1]); if (fd == -1) strerr_die4sys(111,FATAL,"unable to open ",argv[1],": "); g("qmail",argv[34],argv[35],argv[36],argv[37]); g("nofiles",argv[38],argv[39],argv[40],argv[41]); u("root",(char *) 0,"/",argv[14],argv[15],argv[16],argv[17]); u("qmaild","nofiles","/var/qmail",argv[6],argv[7],argv[8],argv[9]); u("qmaill","nofiles","/var/qmail",argv[10],argv[11],argv[12],argv[13]); u("qmailp","nofiles","/var/qmail",argv[18],argv[19],argv[20],argv[21]); u("alias","nofiles","/var/qmail/alias",argv[2],argv[3],argv[4],argv[5]); u("qmailq","qmail","/var/qmail",argv[22],argv[23],argv[24],argv[25]); u("qmailr","qmail","/var/qmail",argv[26],argv[27],argv[28],argv[29]); u("qmails","qmail","/var/qmail",argv[30],argv[31],argv[32],argv[33]); _exit(0); } netqmail-1.06/seek_cur.c0000644000076400007640000000020606541176434014614 0ustar nelsonnelson#include #include "seek.h" #define CUR 1 /* sigh */ seek_pos seek_cur(fd) int fd; { return lseek(fd,(off_t) 0,CUR); } netqmail-1.06/qmail-send.c0000644000076400007640000011435406541176434015060 0ustar nelsonnelson#include #include #include "readwrite.h" #include "sig.h" #include "direntry.h" #include "control.h" #include "select.h" #include "open.h" #include "seek.h" #include "exit.h" #include "lock.h" #include "ndelay.h" #include "now.h" #include "getln.h" #include "substdio.h" #include "alloc.h" #include "error.h" #include "stralloc.h" #include "str.h" #include "byte.h" #include "fmt.h" #include "scan.h" #include "case.h" #include "auto_qmail.h" #include "trigger.h" #include "newfield.h" #include "quote.h" #include "qmail.h" #include "qsutil.h" #include "prioq.h" #include "constmap.h" #include "fmtqfn.h" #include "readsubdir.h" /* critical timing feature #1: if not triggered, do not busy-loop */ /* critical timing feature #2: if triggered, respond within fixed time */ /* important timing feature: when triggered, respond instantly */ #define SLEEP_TODO 1500 /* check todo/ every 25 minutes in any case */ #define SLEEP_FUZZ 1 /* slop a bit on sleeps to avoid zeno effect */ #define SLEEP_FOREVER 86400 /* absolute maximum time spent in select() */ #define SLEEP_CLEANUP 76431 /* time between cleanups */ #define SLEEP_SYSFAIL 123 #define OSSIFIED 129600 /* 36 hours; _must_ exceed q-q's DEATH (24 hours) */ int lifetime = 604800; stralloc percenthack = {0}; struct constmap mappercenthack; stralloc locals = {0}; struct constmap maplocals; stralloc vdoms = {0}; struct constmap mapvdoms; stralloc envnoathost = {0}; stralloc bouncefrom = {0}; stralloc bouncehost = {0}; stralloc doublebounceto = {0}; stralloc doublebouncehost = {0}; char strnum2[FMT_ULONG]; char strnum3[FMT_ULONG]; #define CHANNELS 2 char *chanaddr[CHANNELS] = { "local/", "remote/" }; char *chanstatusmsg[CHANNELS] = { " local ", " remote " }; char *tochan[CHANNELS] = { " to local ", " to remote " }; int chanfdout[CHANNELS] = { 1, 3 }; int chanfdin[CHANNELS] = { 2, 4 }; int chanskip[CHANNELS] = { 10, 20 }; int flagexitasap = 0; void sigterm() { flagexitasap = 1; } int flagrunasap = 0; void sigalrm() { flagrunasap = 1; } int flagreadasap = 0; void sighup() { flagreadasap = 1; } void cleandied() { log1("alert: oh no! lost qmail-clean connection! dying...\n"); flagexitasap = 1; } int flagspawnalive[CHANNELS]; void spawndied(c) int c; { log1("alert: oh no! lost spawn connection! dying...\n"); flagspawnalive[c] = 0; flagexitasap = 1; } #define REPORTMAX 10000 datetime_sec recent; /* this file is too long ----------------------------------------- FILENAMES */ stralloc fn = {0}; stralloc fn2 = {0}; char fnmake_strnum[FMT_ULONG]; void fnmake_init() { while (!stralloc_ready(&fn,FMTQFN)) nomem(); while (!stralloc_ready(&fn2,FMTQFN)) nomem(); } void fnmake_info(id) unsigned long id; { fn.len = fmtqfn(fn.s,"info/",id,1); } void fnmake_todo(id) unsigned long id; { fn.len = fmtqfn(fn.s,"todo/",id,0); } void fnmake_mess(id) unsigned long id; { fn.len = fmtqfn(fn.s,"mess/",id,1); } void fnmake_foop(id) unsigned long id; { fn.len = fmtqfn(fn.s,"foop/",id,0); } void fnmake_split(id) unsigned long id; { fn.len = fmtqfn(fn.s,"",id,1); } void fnmake2_bounce(id) unsigned long id; { fn2.len = fmtqfn(fn2.s,"bounce/",id,0); } void fnmake_chanaddr(id,c) unsigned long id; int c; { fn.len = fmtqfn(fn.s,chanaddr[c],id,1); } /* this file is too long ----------------------------------------- REWRITING */ stralloc rwline = {0}; /* 1 if by land, 2 if by sea, 0 if out of memory. not allowed to barf. */ /* may trash recip. must set up rwline, between a T and a \0. */ int rewrite(recip) char *recip; { int i; int j; char *x; static stralloc addr = {0}; int at; if (!stralloc_copys(&rwline,"T")) return 0; if (!stralloc_copys(&addr,recip)) return 0; i = byte_rchr(addr.s,addr.len,'@'); if (i == addr.len) { if (!stralloc_cats(&addr,"@")) return 0; if (!stralloc_cat(&addr,&envnoathost)) return 0; } while (constmap(&mappercenthack,addr.s + i + 1,addr.len - i - 1)) { j = byte_rchr(addr.s,i,'%'); if (j == i) break; addr.len = i; i = j; addr.s[i] = '@'; } at = byte_rchr(addr.s,addr.len,'@'); if (constmap(&maplocals,addr.s + at + 1,addr.len - at - 1)) { if (!stralloc_cat(&rwline,&addr)) return 0; if (!stralloc_0(&rwline)) return 0; return 1; } 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 0; if (!stralloc_cats(&rwline,"-")) return 0; if (!stralloc_cat(&rwline,&addr)) return 0; if (!stralloc_0(&rwline)) return 0; return 1; } if (!stralloc_cat(&rwline,&addr)) return 0; if (!stralloc_0(&rwline)) return 0; return 2; } void senderadd(sa,sender,recip) stralloc *sa; char *sender; char *recip; { int i; int j; int k; i = str_len(sender); if (i >= 4) if (str_equal(sender + i - 4,"-@[]")) { j = byte_rchr(sender,i - 4,'@'); k = str_rchr(recip,'@'); if (recip[k] && (j + 5 <= i)) { /* owner-@host-@[] -> owner-recipbox=reciphost@host */ while (!stralloc_catb(sa,sender,j)) nomem(); while (!stralloc_catb(sa,recip,k)) nomem(); while (!stralloc_cats(sa,"=")) nomem(); while (!stralloc_cats(sa,recip + k + 1)) nomem(); while (!stralloc_cats(sa,"@")) nomem(); while (!stralloc_catb(sa,sender + j + 1,i - 5 - j)) nomem(); return; } } while (!stralloc_cats(sa,sender)) nomem(); } /* this file is too long ---------------------------------------------- INFO */ int getinfo(sa,dt,id) stralloc *sa; datetime_sec *dt; unsigned long id; { int fdinfo; struct stat st; static stralloc line = {0}; int match; substdio ss; char buf[128]; fnmake_info(id); fdinfo = open_read(fn.s); if (fdinfo == -1) return 0; if (fstat(fdinfo,&st) == -1) { close(fdinfo); return 0; } substdio_fdbuf(&ss,read,fdinfo,buf,sizeof(buf)); if (getln(&ss,&line,&match,'\0') == -1) { close(fdinfo); return 0; } close(fdinfo); if (!match) return 0; if (line.s[0] != 'F') return 0; *dt = st.st_mtime; while (!stralloc_copys(sa,line.s + 1)) nomem(); while (!stralloc_0(sa)) nomem(); return 1; } /* this file is too long ------------------------------------- COMMUNICATION */ substdio sstoqc; char sstoqcbuf[1024]; substdio ssfromqc; char ssfromqcbuf[1024]; stralloc comm_buf[CHANNELS] = { {0}, {0} }; int comm_pos[CHANNELS]; void comm_init() { int c; substdio_fdbuf(&sstoqc,write,5,sstoqcbuf,sizeof(sstoqcbuf)); substdio_fdbuf(&ssfromqc,read,6,ssfromqcbuf,sizeof(ssfromqcbuf)); for (c = 0;c < CHANNELS;++c) if (ndelay_on(chanfdout[c]) == -1) /* this is so stupid: NDELAY semantics should be default on write */ spawndied(c); /* drastic, but better than risking deadlock */ } int comm_canwrite(c) int c; { /* XXX: could allow a bigger buffer; say 10 recipients */ if (comm_buf[c].s && comm_buf[c].len) return 0; return 1; } void comm_write(c,delnum,id,sender,recip) int c; int delnum; unsigned long id; char *sender; char *recip; { char ch; if (comm_buf[c].s && comm_buf[c].len) return; while (!stralloc_copys(&comm_buf[c],"")) nomem(); ch = delnum; while (!stralloc_append(&comm_buf[c],&ch)) nomem(); fnmake_split(id); while (!stralloc_cats(&comm_buf[c],fn.s)) nomem(); while (!stralloc_0(&comm_buf[c])) nomem(); senderadd(&comm_buf[c],sender,recip); while (!stralloc_0(&comm_buf[c])) nomem(); while (!stralloc_cats(&comm_buf[c],recip)) nomem(); while (!stralloc_0(&comm_buf[c])) nomem(); comm_pos[c] = 0; } void comm_selprep(nfds,wfds) int *nfds; fd_set *wfds; { int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) if (comm_buf[c].s && comm_buf[c].len) { FD_SET(chanfdout[c],wfds); if (*nfds <= chanfdout[c]) *nfds = chanfdout[c] + 1; } } void comm_do(wfds) fd_set *wfds; { int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) if (comm_buf[c].s && comm_buf[c].len) if (FD_ISSET(chanfdout[c],wfds)) { int w; int len; len = comm_buf[c].len; w = write(chanfdout[c],comm_buf[c].s + comm_pos[c],len - comm_pos[c]); if (w <= 0) { if ((w == -1) && (errno == error_pipe)) spawndied(c); else continue; /* kernel select() bug; can't avoid busy-looping */ } else { comm_pos[c] += w; if (comm_pos[c] == len) comm_buf[c].len = 0; } } } /* this file is too long ------------------------------------------ CLEANUPS */ int flagcleanup; /* if 1, cleanupdir is initialized and ready */ readsubdir cleanupdir; datetime_sec cleanuptime; void cleanup_init() { flagcleanup = 0; cleanuptime = now(); } void cleanup_selprep(wakeup) datetime_sec *wakeup; { if (flagcleanup) *wakeup = 0; if (*wakeup > cleanuptime) *wakeup = cleanuptime; } void cleanup_do() { char ch; struct stat st; unsigned long id; if (!flagcleanup) { if (recent < cleanuptime) return; readsubdir_init(&cleanupdir,"mess",pausedir); flagcleanup = 1; } switch(readsubdir_next(&cleanupdir,&id)) { case 1: break; case 0: flagcleanup = 0; cleanuptime = recent + SLEEP_CLEANUP; default: return; } fnmake_mess(id); if (stat(fn.s,&st) == -1) return; /* probably qmail-queue deleted it */ if (recent <= st.st_atime + OSSIFIED) return; fnmake_info(id); if (stat(fn.s,&st) == 0) return; if (errno != error_noent) return; fnmake_todo(id); if (stat(fn.s,&st) == 0) return; if (errno != error_noent) return; fnmake_foop(id); if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; } if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; } if (ch != '+') log3("warning: qmail-clean unable to clean up ",fn.s,"\n"); } /* this file is too long ----------------------------------- PRIORITY QUEUES */ prioq pqdone = {0}; /* -todo +info; HOPEFULLY -local -remote */ prioq pqchan[CHANNELS] = { {0}, {0} }; /* pqchan 0: -todo +info +local ?remote */ /* pqchan 1: -todo +info ?local +remote */ prioq pqfail = {0}; /* stat() failure; has to be pqadded again */ void pqadd(id) unsigned long id; { struct prioq_elt pe; struct prioq_elt pechan[CHANNELS]; int flagchan[CHANNELS]; struct stat st; int c; #define CHECKSTAT if (errno != error_noent) goto fail; fnmake_info(id); if (stat(fn.s,&st) == -1) { CHECKSTAT return; /* someone yanking our chain */ } fnmake_todo(id); if (stat(fn.s,&st) != -1) return; /* look, ma, dad crashed writing info! */ CHECKSTAT for (c = 0;c < CHANNELS;++c) { fnmake_chanaddr(id,c); if (stat(fn.s,&st) == -1) { flagchan[c] = 0; CHECKSTAT } else { flagchan[c] = 1; pechan[c].id = id; pechan[c].dt = st.st_mtime; } } for (c = 0;c < CHANNELS;++c) if (flagchan[c]) while (!prioq_insert(&pqchan[c],&pechan[c])) nomem(); for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break; if (c == CHANNELS) { pe.id = id; pe.dt = now(); while (!prioq_insert(&pqdone,&pe)) nomem(); } return; fail: log3("warning: unable to stat ",fn.s,"; will try again later\n"); pe.id = id; pe.dt = now() + SLEEP_SYSFAIL; while (!prioq_insert(&pqfail,&pe)) nomem(); } void pqstart() { readsubdir rs; int x; unsigned long id; readsubdir_init(&rs,"info",pausedir); while (x = readsubdir_next(&rs,&id)) if (x > 0) pqadd(id); } void pqfinish() { int c; struct prioq_elt pe; time_t ut[2]; /* XXX: more portable than utimbuf, but still worrisome */ for (c = 0;c < CHANNELS;++c) while (prioq_min(&pqchan[c],&pe)) { prioq_delmin(&pqchan[c]); fnmake_chanaddr(pe.id,c); ut[0] = ut[1] = pe.dt; if (utime(fn.s,ut) == -1) log3("warning: unable to utime ",fn.s,"; message will be retried too soon\n"); } } void pqrun() { int c; int i; for (c = 0;c < CHANNELS;++c) if (pqchan[c].p) if (pqchan[c].len) for (i = 0;i < pqchan[c].len;++i) pqchan[c].p[i].dt = recent; } /* this file is too long ---------------------------------------------- JOBS */ struct job { int refs; /* if 0, this struct is unused */ unsigned long id; int channel; datetime_sec retry; stralloc sender; int numtodo; int flaghiteof; int flagdying; } ; int numjobs; struct job *jo; void job_init() { int j; while (!(jo = (struct job *) alloc(numjobs * sizeof(struct job)))) nomem(); for (j = 0;j < numjobs;++j) { jo[j].refs = 0; jo[j].sender.s = 0; } } int job_avail() { int j; for (j = 0;j < numjobs;++j) if (!jo[j].refs) return 1; return 0; } int job_open(id,channel) unsigned long id; int channel; { int j; for (j = 0;j < numjobs;++j) if (!jo[j].refs) break; if (j == numjobs) return -1; jo[j].refs = 1; jo[j].id = id; jo[j].channel = channel; jo[j].numtodo = 0; jo[j].flaghiteof = 0; return j; } void job_close(j) int j; { struct prioq_elt pe; struct stat st; if (0 < --jo[j].refs) return; 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); if (unlink(fn.s) == -1) { log3("warning: unable to unlink ",fn.s,"; will try again later\n"); pe.dt = now() + SLEEP_SYSFAIL; } else { int c; for (c = 0;c < CHANNELS;++c) if (c != jo[j].channel) { fnmake_chanaddr(jo[j].id,c); if (stat(fn.s,&st) == 0) return; /* more channels going */ if (errno != error_noent) { log3("warning: unable to stat ",fn.s,"\n"); break; /* this is the only reason for HOPEFULLY */ } } pe.dt = now(); while (!prioq_insert(&pqdone,&pe)) nomem(); return; } } while (!prioq_insert(&pqchan[jo[j].channel],&pe)) nomem(); } /* this file is too long ------------------------------------------- BOUNCES */ char *stripvdomprepend(recip) char *recip; { int i; char *domain; int domainlen; char *prepend; i = str_rchr(recip,'@'); if (!recip[i]) return recip; domain = recip + i + 1; domainlen = str_len(domain); for (i = 0;i <= domainlen;++i) if ((i == 0) || (i == domainlen) || (domain[i] == '.')) if (prepend = constmap(&mapvdoms,domain + i,domainlen - i)) { if (!*prepend) break; i = str_len(prepend); if (str_diffn(recip,prepend,i)) break; if (recip[i] != '-') break; return recip + i + 1; } return recip; } stralloc bouncetext = {0}; void addbounce(id,recip,report) unsigned long id; char *recip; char *report; { int fd; int pos; int w; while (!stralloc_copys(&bouncetext,"<")) nomem(); while (!stralloc_cats(&bouncetext,stripvdomprepend(recip))) nomem(); for (pos = 0;pos < bouncetext.len;++pos) if (bouncetext.s[pos] == '\n') bouncetext.s[pos] = '_'; while (!stralloc_cats(&bouncetext,">:\n")) nomem(); while (!stralloc_cats(&bouncetext,report)) nomem(); if (report[0]) if (report[str_len(report) - 1] != '\n') while (!stralloc_cats(&bouncetext,"\n")) nomem(); for (pos = bouncetext.len - 2;pos > 0;--pos) if (bouncetext.s[pos] == '\n') if (bouncetext.s[pos - 1] == '\n') bouncetext.s[pos] = '/'; while (!stralloc_cats(&bouncetext,"\n")) nomem(); fnmake2_bounce(id); for (;;) { fd = open_append(fn2.s); if (fd != -1) break; log1("alert: unable to append to bounce message; HELP! sleeping...\n"); sleep(10); } pos = 0; while (pos < bouncetext.len) { w = write(fd,bouncetext.s + pos,bouncetext.len - pos); if (w <= 0) { log1("alert: unable to append to bounce message; HELP! sleeping...\n"); sleep(10); } else pos += w; } close(fd); } int injectbounce(id) unsigned long id; { struct qmail qqt; struct stat st; char *bouncesender; char *bouncerecip; int r; int fd; substdio ssread; char buf[128]; char inbuf[128]; static stralloc sender = {0}; static stralloc quoted = {0}; datetime_sec birth; unsigned long qp; if (!getinfo(&sender,&birth,id)) return 0; /* XXX: print warning */ /* owner-@host-@[] -> owner-@host */ if (sender.len >= 5) if (str_equal(sender.s + sender.len - 5,"-@[]")) { sender.len -= 4; sender.s[sender.len - 1] = 0; } fnmake2_bounce(id); fnmake_mess(id); if (stat(fn2.s,&st) == -1) { if (errno == error_noent) return 1; log3("warning: unable to stat ",fn2.s,"\n"); return 0; } if (str_equal(sender.s,"#@[]")) log3("triple bounce: discarding ",fn2.s,"\n"); else { if (qmail_open(&qqt) == -1) { log1("warning: unable to start qmail-queue, will try later\n"); return 0; } qp = qmail_qp(&qqt); if (*sender.s) { bouncesender = ""; bouncerecip = sender.s; } else { bouncesender = "#@[]"; bouncerecip = doublebounceto.s; } while (!newfield_datemake(now())) nomem(); qmail_put(&qqt,newfield_date.s,newfield_date.len); qmail_puts(&qqt,"From: "); while (!quote("ed,&bouncefrom)) nomem(); qmail_put(&qqt,quoted.s,quoted.len); qmail_puts(&qqt,"@"); qmail_put(&qqt,bouncehost.s,bouncehost.len); qmail_puts(&qqt,"\nTo: "); while (!quote2("ed,bouncerecip)) nomem(); qmail_put(&qqt,quoted.s,quoted.len); qmail_puts(&qqt,"\n\ Subject: failure notice\n\ \n\ Hi. This is the qmail-send program at "); qmail_put(&qqt,bouncehost.s,bouncehost.len); qmail_puts(&qqt,*sender.s ? ".\n\ I'm afraid I wasn't able to deliver your message to the following addresses.\n\ This is a permanent error; I've given up. Sorry it didn't work out.\n\ \n\ " : ".\n\ I tried to deliver a bounce message to this address, but the bounce bounced!\n\ \n\ "); fd = open_read(fn2.s); if (fd == -1) qmail_fail(&qqt); else { substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf)); while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0) qmail_put(&qqt,buf,r); close(fd); if (r == -1) qmail_fail(&qqt); } 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"); qmail_puts(&qqt,"Return-Path: <"); while (!quote2("ed,sender.s)) nomem(); qmail_put(&qqt,quoted.s,quoted.len); qmail_puts(&qqt,">\n"); fd = open_read(fn.s); if (fd == -1) qmail_fail(&qqt); else { substdio_fdbuf(&ssread,read,fd,inbuf,sizeof(inbuf)); while ((r = substdio_get(&ssread,buf,sizeof(buf))) > 0) qmail_put(&qqt,buf,r); close(fd); if (r == -1) qmail_fail(&qqt); } qmail_from(&qqt,bouncesender); qmail_to(&qqt,bouncerecip); if (*qmail_close(&qqt)) { log1("warning: trouble injecting bounce message, will try later\n"); return 0; } strnum2[fmt_ulong(strnum2,id)] = 0; log2("bounce msg ",strnum2); strnum2[fmt_ulong(strnum2,qp)] = 0; log3(" qp ",strnum2,"\n"); } if (unlink(fn2.s) == -1) { log3("warning: unable to unlink ",fn2.s,"\n"); return 0; } return 1; } /* this file is too long ---------------------------------------- DELIVERIES */ struct del { int used; int j; unsigned long delid; seek_pos mpos; stralloc recip; } ; unsigned long masterdelid = 1; unsigned int concurrency[CHANNELS] = { 10, 20 }; unsigned int concurrencyused[CHANNELS] = { 0, 0 }; struct del *d[CHANNELS]; stralloc dline[CHANNELS]; char delbuf[2048]; void del_status() { int c; log1("status:"); for (c = 0;c < CHANNELS;++c) { strnum2[fmt_ulong(strnum2,(unsigned long) concurrencyused[c])] = 0; strnum3[fmt_ulong(strnum3,(unsigned long) concurrency[c])] = 0; log2(chanstatusmsg[c],strnum2); log2("/",strnum3); } if (flagexitasap) log1(" exitasap"); log1("\n"); } void del_init() { int c; int i; for (c = 0;c < CHANNELS;++c) { flagspawnalive[c] = 1; while (!(d[c] = (struct del *) alloc(concurrency[c] * sizeof(struct del)))) nomem(); for (i = 0;i < concurrency[c];++i) { d[c][i].used = 0; d[c][i].recip.s = 0; } dline[c].s = 0; while (!stralloc_copys(&dline[c],"")) nomem(); } del_status(); } int del_canexit() { int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) /* if dead, nothing we can do about its jobs */ if (concurrencyused[c]) return 0; return 1; } int del_avail(c) int c; { return flagspawnalive[c] && comm_canwrite(c) && (concurrencyused[c] < concurrency[c]); } void del_start(j,mpos,recip) int j; seek_pos mpos; char *recip; { int i; int c; c = jo[j].channel; if (!flagspawnalive[c]) return; if (!comm_canwrite(c)) return; for (i = 0;i < concurrency[c];++i) if (!d[c][i].used) break; if (i == concurrency[c]) return; if (!stralloc_copys(&d[c][i].recip,recip)) { nomem(); return; } if (!stralloc_0(&d[c][i].recip)) { nomem(); return; } d[c][i].j = j; ++jo[j].refs; d[c][i].delid = masterdelid++; d[c][i].mpos = mpos; d[c][i].used = 1; ++concurrencyused[c]; comm_write(c,i,jo[j].id,jo[j].sender.s,recip); strnum2[fmt_ulong(strnum2,d[c][i].delid)] = 0; strnum3[fmt_ulong(strnum3,jo[j].id)] = 0; log2("starting delivery ",strnum2); log3(": msg ",strnum3,tochan[c]); logsafe(recip); log1("\n"); del_status(); } void markdone(c,id,pos) int c; unsigned long id; seek_pos pos; { struct stat st; int fd; fnmake_chanaddr(id,c); for (;;) { fd = open_write(fn.s); if (fd == -1) break; if (fstat(fd,&st) == -1) { close(fd); break; } if (seek_set(fd,pos) == -1) { close(fd); break; } if (write(fd,"D",1) != 1) { close(fd); break; } /* further errors -> double delivery without us knowing about it, oh well */ close(fd); return; } log3("warning: trouble marking ",fn.s,"; message will be delivered twice!\n"); } void del_dochan(c) int c; { int r; char ch; int i; int delnum; r = read(chanfdin[c],delbuf,sizeof(delbuf)); if (r == -1) return; if (r == 0) { spawndied(c); return; } for (i = 0;i < r;++i) { ch = delbuf[i]; while (!stralloc_append(&dline[c],&ch)) nomem(); if (dline[c].len > REPORTMAX) dline[c].len = REPORTMAX; /* qmail-lspawn and qmail-rspawn are responsible for keeping it short */ /* but from a security point of view, we don't trust rspawn */ if (!ch && (dline[c].len > 1)) { delnum = (unsigned int) (unsigned char) dline[c].s[0]; if ((delnum < 0) || (delnum >= concurrency[c]) || !d[c][delnum].used) log1("warning: internal error: delivery report out of range\n"); else { strnum3[fmt_ulong(strnum3,d[c][delnum].delid)] = 0; if (dline[c].s[1] == 'Z') if (jo[d[c][delnum].j].flagdying) { dline[c].s[1] = 'D'; --dline[c].len; while (!stralloc_cats(&dline[c],"I'm not going to try again; this message has been in the queue too long.\n")) nomem(); while (!stralloc_0(&dline[c])) nomem(); } switch(dline[c].s[1]) { case 'K': log3("delivery ",strnum3,": success: "); logsafe(dline[c].s + 2); log1("\n"); markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos); --jo[d[c][delnum].j].numtodo; break; case 'Z': log3("delivery ",strnum3,": deferral: "); logsafe(dline[c].s + 2); log1("\n"); break; case 'D': log3("delivery ",strnum3,": failure: "); logsafe(dline[c].s + 2); log1("\n"); addbounce(jo[d[c][delnum].j].id,d[c][delnum].recip.s,dline[c].s + 2); markdone(c,jo[d[c][delnum].j].id,d[c][delnum].mpos); --jo[d[c][delnum].j].numtodo; break; default: log3("delivery ",strnum3,": report mangled, will defer\n"); } job_close(d[c][delnum].j); d[c][delnum].used = 0; --concurrencyused[c]; del_status(); } dline[c].len = 0; } } } void del_selprep(nfds,rfds) int *nfds; fd_set *rfds; { int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) { FD_SET(chanfdin[c],rfds); if (*nfds <= chanfdin[c]) *nfds = chanfdin[c] + 1; } } void del_do(rfds) fd_set *rfds; { int c; for (c = 0;c < CHANNELS;++c) if (flagspawnalive[c]) if (FD_ISSET(chanfdin[c],rfds)) del_dochan(c); } /* this file is too long -------------------------------------------- PASSES */ struct { unsigned long id; /* if 0, need a new pass */ int j; /* defined if id; job number */ int fd; /* defined if id; reading from {local,remote} */ seek_pos mpos; /* defined if id; mark position */ substdio ss; char buf[128]; } pass[CHANNELS]; void pass_init() { int c; for (c = 0;c < CHANNELS;++c) pass[c].id = 0; } void pass_selprep(wakeup) datetime_sec *wakeup; { int c; struct prioq_elt pe; if (flagexitasap) return; for (c = 0;c < CHANNELS;++c) if (pass[c].id) if (del_avail(c)) { *wakeup = 0; return; } if (job_avail()) for (c = 0;c < CHANNELS;++c) if (!pass[c].id) if (prioq_min(&pqchan[c],&pe)) if (*wakeup > pe.dt) *wakeup = pe.dt; if (prioq_min(&pqfail,&pe)) if (*wakeup > pe.dt) *wakeup = pe.dt; if (prioq_min(&pqdone,&pe)) if (*wakeup > pe.dt) *wakeup = pe.dt; } static datetime_sec squareroot(x) /* result^2 <= x < (result + 1)^2 */ datetime_sec x; /* assuming: >= 0 */ { datetime_sec y; datetime_sec yy; datetime_sec y21; int j; y = 0; yy = 0; for (j = 15;j >= 0;--j) { y21 = (y << (j + 1)) + (1 << (j + j)); if (y21 <= x - yy) { y += (1 << j); yy += y21; } } return y; } datetime_sec nextretry(birth,c) datetime_sec birth; int c; { int n; if (birth > recent) n = 0; else n = squareroot(recent - birth); /* no need to add fuzz to recent */ n += chanskip[c]; return birth + n * n; } void pass_dochan(c) int c; { datetime_sec birth; struct prioq_elt pe; static stralloc line = {0}; int match; if (flagexitasap) return; if (!pass[c].id) { if (!job_avail()) return; if (!prioq_min(&pqchan[c],&pe)) return; if (pe.dt > recent) return; fnmake_chanaddr(pe.id,c); prioq_delmin(&pqchan[c]); pass[c].mpos = 0; pass[c].fd = open_read(fn.s); if (pass[c].fd == -1) goto trouble; if (!getinfo(&line,&birth,pe.id)) { close(pass[c].fd); goto trouble; } pass[c].id = pe.id; substdio_fdbuf(&pass[c].ss,read,pass[c].fd,pass[c].buf,sizeof(pass[c].buf)); pass[c].j = job_open(pe.id,c); jo[pass[c].j].retry = nextretry(birth,c); jo[pass[c].j].flagdying = (recent > birth + lifetime); while (!stralloc_copy(&jo[pass[c].j].sender,&line)) nomem(); } if (!del_avail(c)) return; if (getln(&pass[c].ss,&line,&match,'\0') == -1) { fnmake_chanaddr(pass[c].id,c); log3("warning: trouble reading ",fn.s,"; will try again later\n"); close(pass[c].fd); job_close(pass[c].j); pass[c].id = 0; return; } if (!match) { close(pass[c].fd); jo[pass[c].j].flaghiteof = 1; job_close(pass[c].j); pass[c].id = 0; return; } switch(line.s[0]) { case 'T': ++jo[pass[c].j].numtodo; del_start(pass[c].j,pass[c].mpos,line.s + 1); break; case 'D': break; default: fnmake_chanaddr(pass[c].id,c); log3("warning: unknown record type in ",fn.s,"!\n"); close(pass[c].fd); job_close(pass[c].j); pass[c].id = 0; return; } pass[c].mpos += line.len; return; trouble: log3("warning: trouble opening ",fn.s,"; will try again later\n"); pe.dt = recent + SLEEP_SYSFAIL; while (!prioq_insert(&pqchan[c],&pe)) nomem(); } void messdone(id) unsigned long id; { char ch; int c; struct prioq_elt pe; struct stat st; for (c = 0;c < CHANNELS;++c) { fnmake_chanaddr(id,c); if (stat(fn.s,&st) == 0) return; /* false alarm; consequence of HOPEFULLY */ if (errno != error_noent) { log3("warning: unable to stat ",fn.s,"; will try again later\n"); goto fail; } } fnmake_todo(id); if (stat(fn.s,&st) == 0) return; if (errno != error_noent) { log3("warning: unable to stat ",fn.s,"; will try again later\n"); goto fail; } fnmake_info(id); if (stat(fn.s,&st) == -1) { if (errno == error_noent) return; log3("warning: unable to stat ",fn.s,"; will try again later\n"); goto fail; } /* -todo +info -local -remote ?bounce */ if (!injectbounce(id)) goto fail; /* injectbounce() produced error message */ strnum3[fmt_ulong(strnum3,id)] = 0; log3("end msg ",strnum3,"\n"); /* -todo +info -local -remote -bounce */ fnmake_info(id); 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); if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; } if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; } if (ch != '+') log3("warning: qmail-clean unable to clean up ",fn.s,"\n"); return; fail: pe.id = id; pe.dt = now() + SLEEP_SYSFAIL; while (!prioq_insert(&pqdone,&pe)) nomem(); } void pass_do() { int c; struct prioq_elt pe; for (c = 0;c < CHANNELS;++c) pass_dochan(c); if (prioq_min(&pqfail,&pe)) if (pe.dt <= recent) { prioq_delmin(&pqfail); pqadd(pe.id); } if (prioq_min(&pqdone,&pe)) if (pe.dt <= recent) { prioq_delmin(&pqdone); messdone(pe.id); } } /* this file is too long ---------------------------------------------- TODO */ datetime_sec nexttodorun; DIR *tododir; /* if 0, have to opendir again */ stralloc todoline = {0}; char todobuf[SUBSTDIO_INSIZE]; char todobufinfo[512]; char todobufchan[CHANNELS][1024]; void todo_init() { tododir = 0; nexttodorun = now(); trigger_set(); } void todo_selprep(nfds,rfds,wakeup) int *nfds; fd_set *rfds; datetime_sec *wakeup; { if (flagexitasap) return; trigger_selprep(nfds,rfds); if (tododir) *wakeup = 0; if (*wakeup > nexttodorun) *wakeup = nexttodorun; } void todo_do(rfds) fd_set *rfds; { struct stat st; substdio ss; int fd; substdio ssinfo; int fdinfo; substdio sschan[CHANNELS]; int fdchan[CHANNELS]; int flagchan[CHANNELS]; struct prioq_elt pe; char ch; int match; unsigned long id; unsigned int len; direntry *d; int c; unsigned long uid; unsigned long pid; fd = -1; fdinfo = -1; for (c = 0;c < CHANNELS;++c) fdchan[c] = -1; if (flagexitasap) return; if (!tododir) { if (!trigger_pulled(rfds)) if (recent < nexttodorun) return; trigger_set(); tododir = opendir("todo"); if (!tododir) { pausedir("todo"); return; } nexttodorun = recent + SLEEP_TODO; } d = readdir(tododir); if (!d) { closedir(tododir); tododir = 0; return; } if (str_equal(d->d_name,".")) return; if (str_equal(d->d_name,"..")) return; len = scan_ulong(d->d_name,&id); if (!len || d->d_name[len]) return; fnmake_todo(id); fd = open_read(fn.s); if (fd == -1) { log3("warning: unable to open ",fn.s,"\n"); return; } fnmake_mess(id); /* just for the statistics */ if (stat(fn.s,&st) == -1) { log3("warning: unable to stat ",fn.s,"\n"); goto fail; } for (c = 0;c < CHANNELS;++c) { fnmake_chanaddr(id,c); if (unlink(fn.s) == -1) if (errno != error_noent) { log3("warning: unable to unlink ",fn.s,"\n"); goto fail; } } fnmake_info(id); if (unlink(fn.s) == -1) if (errno != error_noent) { log3("warning: unable to unlink ",fn.s,"\n"); goto fail; } fdinfo = open_excl(fn.s); if (fdinfo == -1) { log3("warning: unable to create ",fn.s,"\n"); goto fail; } strnum3[fmt_ulong(strnum3,id)] = 0; log3("new msg ",strnum3,"\n"); for (c = 0;c < CHANNELS;++c) flagchan[c] = 0; substdio_fdbuf(&ss,read,fd,todobuf,sizeof(todobuf)); substdio_fdbuf(&ssinfo,write,fdinfo,todobufinfo,sizeof(todobufinfo)); uid = 0; pid = 0; for (;;) { if (getln(&ss,&todoline,&match,'\0') == -1) { /* perhaps we're out of memory, perhaps an I/O error */ fnmake_todo(id); log3("warning: trouble reading ",fn.s,"\n"); goto fail; } if (!match) break; switch(todoline.s[0]) { case 'u': scan_ulong(todoline.s + 1,&uid); break; case 'p': scan_ulong(todoline.s + 1,&pid); break; case 'F': if (substdio_putflush(&ssinfo,todoline.s,todoline.len) == -1) { fnmake_info(id); log3("warning: trouble writing to ",fn.s,"\n"); goto fail; } log2("info msg ",strnum3); strnum2[fmt_ulong(strnum2,(unsigned long) st.st_size)] = 0; log2(": bytes ",strnum2); log1(" from <"); logsafe(todoline.s + 1); strnum2[fmt_ulong(strnum2,pid)] = 0; log2("> qp ",strnum2); strnum2[fmt_ulong(strnum2,uid)] = 0; log2(" uid ",strnum2); log1("\n"); break; case 'T': switch(rewrite(todoline.s + 1)) { case 0: nomem(); goto fail; case 2: c = 1; break; default: c = 0; break; } if (fdchan[c] == -1) { fnmake_chanaddr(id,c); fdchan[c] = open_excl(fn.s); if (fdchan[c] == -1) { log3("warning: unable to create ",fn.s,"\n"); goto fail; } substdio_fdbuf(&sschan[c] ,write,fdchan[c],todobufchan[c],sizeof(todobufchan[c])); flagchan[c] = 1; } if (substdio_bput(&sschan[c],rwline.s,rwline.len) == -1) { fnmake_chanaddr(id,c); log3("warning: trouble writing to ",fn.s,"\n"); goto fail; } break; default: fnmake_todo(id); log3("warning: unknown record type in ",fn.s,"\n"); goto fail; } } close(fd); fd = -1; fnmake_info(id); if (substdio_flush(&ssinfo) == -1) { log3("warning: trouble writing to ",fn.s,"\n"); goto fail; } if (fsync(fdinfo) == -1) { log3("warning: trouble fsyncing ",fn.s,"\n"); goto fail; } close(fdinfo); fdinfo = -1; for (c = 0;c < CHANNELS;++c) if (fdchan[c] != -1) { fnmake_chanaddr(id,c); if (substdio_flush(&sschan[c]) == -1) { log3("warning: trouble writing to ",fn.s,"\n"); goto fail; } if (fsync(fdchan[c]) == -1) { log3("warning: trouble fsyncing ",fn.s,"\n"); goto fail; } close(fdchan[c]); fdchan[c] = -1; } fnmake_todo(id); if (substdio_putflush(&sstoqc,fn.s,fn.len) == -1) { cleandied(); return; } if (substdio_get(&ssfromqc,&ch,1) != 1) { cleandied(); return; } if (ch != '+') { log3("warning: qmail-clean unable to clean up ",fn.s,"\n"); return; } pe.id = id; pe.dt = now(); for (c = 0;c < CHANNELS;++c) if (flagchan[c]) while (!prioq_insert(&pqchan[c],&pe)) nomem(); for (c = 0;c < CHANNELS;++c) if (flagchan[c]) break; if (c == CHANNELS) while (!prioq_insert(&pqdone,&pe)) nomem(); return; fail: if (fd != -1) close(fd); if (fdinfo != -1) close(fdinfo); for (c = 0;c < CHANNELS;++c) if (fdchan[c] != -1) close(fdchan[c]); } /* this file is too long ---------------------------------------------- MAIN */ int getcontrols() { if (control_init() == -1) return 0; if (control_readint(&lifetime,"control/queuelifetime") == -1) return 0; if (control_readint(&concurrency[0],"control/concurrencylocal") == -1) return 0; if (control_readint(&concurrency[1],"control/concurrencyremote") == -1) return 0; if (control_rldef(&envnoathost,"control/envnoathost",1,"envnoathost") != 1) return 0; if (control_rldef(&bouncefrom,"control/bouncefrom",0,"MAILER-DAEMON") != 1) return 0; if (control_rldef(&bouncehost,"control/bouncehost",1,"bouncehost") != 1) return 0; if (control_rldef(&doublebouncehost,"control/doublebouncehost",1,"doublebouncehost") != 1) return 0; if (control_rldef(&doublebounceto,"control/doublebounceto",0,"postmaster") != 1) return 0; if (!stralloc_cats(&doublebounceto,"@")) return 0; if (!stralloc_cat(&doublebounceto,&doublebouncehost)) return 0; if (!stralloc_0(&doublebounceto)) return 0; if (control_readfile(&locals,"control/locals",1) != 1) return 0; if (!constmap_init(&maplocals,locals.s,locals.len,0)) return 0; switch(control_readfile(&percenthack,"control/percenthack",0)) { case -1: return 0; case 0: if (!constmap_init(&mappercenthack,"",0,0)) return 0; break; case 1: if (!constmap_init(&mappercenthack,percenthack.s,percenthack.len,0)) return 0; break; } switch(control_readfile(&vdoms,"control/virtualdomains",0)) { case -1: return 0; case 0: if (!constmap_init(&mapvdoms,"",0,1)) return 0; break; case 1: if (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) return 0; break; } return 1; } stralloc newlocals = {0}; stralloc newvdoms = {0}; void regetcontrols() { int r; if (control_readfile(&newlocals,"control/locals",1) != 1) { log1("alert: unable to reread control/locals\n"); return; } r = control_readfile(&newvdoms,"control/virtualdomains",0); if (r == -1) { log1("alert: unable to reread control/virtualdomains\n"); return; } constmap_free(&maplocals); constmap_free(&mapvdoms); while (!stralloc_copy(&locals,&newlocals)) nomem(); while (!constmap_init(&maplocals,locals.s,locals.len,0)) nomem(); if (r) { while (!stralloc_copy(&vdoms,&newvdoms)) nomem(); while (!constmap_init(&mapvdoms,vdoms.s,vdoms.len,1)) nomem(); } else while (!constmap_init(&mapvdoms,"",0,1)) nomem(); } void reread() { if (chdir(auto_qmail) == -1) { log1("alert: unable to reread controls: unable to switch to home directory\n"); return; } regetcontrols(); while (chdir("queue") == -1) { log1("alert: unable to switch back to queue directory; HELP! sleeping...\n"); sleep(10); } } void main() { int fd; datetime_sec wakeup; fd_set rfds; fd_set wfds; int nfds; struct timeval tv; int c; if (chdir(auto_qmail) == -1) { log1("alert: cannot start: unable to switch to home directory\n"); _exit(111); } if (!getcontrols()) { log1("alert: cannot start: unable to read controls\n"); _exit(111); } if (chdir("queue") == -1) { log1("alert: cannot start: unable to switch to queue directory\n"); _exit(111); } sig_pipeignore(); sig_termcatch(sigterm); sig_alarmcatch(sigalrm); sig_hangupcatch(sighup); sig_childdefault(); umask(077); fd = open_write("lock/sendmutex"); if (fd == -1) { log1("alert: cannot start: unable to open mutex\n"); _exit(111); } if (lock_exnb(fd) == -1) { log1("alert: cannot start: qmail-send is already running\n"); _exit(111); } numjobs = 0; for (c = 0;c < CHANNELS;++c) { char ch; int u; int r; do r = read(chanfdin[c],&ch,1); while ((r == -1) && (errno == error_intr)); if (r < 1) { log1("alert: cannot start: hath the daemon spawn no fire?\n"); _exit(111); } u = (unsigned int) (unsigned char) ch; if (concurrency[c] > u) concurrency[c] = u; numjobs += concurrency[c]; } fnmake_init(); comm_init(); pqstart(); job_init(); del_init(); pass_init(); todo_init(); cleanup_init(); while (!flagexitasap || !del_canexit()) { recent = now(); if (flagrunasap) { flagrunasap = 0; pqrun(); } if (flagreadasap) { flagreadasap = 0; reread(); } wakeup = recent + SLEEP_FOREVER; FD_ZERO(&rfds); FD_ZERO(&wfds); nfds = 1; comm_selprep(&nfds,&wfds); del_selprep(&nfds,&rfds); pass_selprep(&wakeup); todo_selprep(&nfds,&rfds,&wakeup); cleanup_selprep(&wakeup); if (wakeup <= recent) tv.tv_sec = 0; else tv.tv_sec = wakeup - recent + SLEEP_FUZZ; tv.tv_usec = 0; if (select(nfds,&rfds,&wfds,(fd_set *) 0,&tv) == -1) if (errno == error_intr) ; else log1("warning: trouble in select\n"); else { recent = now(); comm_do(&wfds); del_do(&rfds); todo_do(&rfds); pass_do(); cleanup_do(); } } pqfinish(); log1("status: exiting\n"); _exit(0); } netqmail-1.06/subfd.h0000644000076400007640000000040706541176434014127 0ustar nelsonnelson#ifndef SUBFD_H #define SUBFD_H #include "substdio.h" extern substdio *subfdin; extern substdio *subfdinsmall; extern substdio *subfdout; extern substdio *subfdoutsmall; extern substdio *subfderr; extern int subfd_read(); extern int subfd_readsmall(); #endif netqmail-1.06/conf-split0000644000076400007640000000005206541176434014650 0ustar nelsonnelson23 This is the queue subdirectory split. netqmail-1.06/sig_pipe.c0000644000076400007640000000022306541176434014612 0ustar nelsonnelson#include #include "sig.h" void sig_pipeignore() { sig_catch(SIGPIPE,SIG_IGN); } void sig_pipedefault() { sig_catch(SIGPIPE,SIG_DFL); } netqmail-1.06/maildir2mbox.10000644000076400007640000000161106541176434015324 0ustar nelsonnelson.TH maildir2mbox 1 .SH NAME maildir2mbox \- move mail from a maildir to an mbox .SH SYNOPSIS .B maildir2mbox .SH DESCRIPTION .B maildir2mbox moves mail from a .IR maildir -format directory to an .IR mbox -format file. You must supply three environment variables to .BR maildir2mbox : .B MAILDIR is the name of your .I maildir directory; .B MAIL is the name of your .I mbox file; and .B MAILTMP is a temporary file that .B maildir2mbox can overwrite. .B MAILTMP and .B MAIL must be on the same filesystem. .B maildir2mbox is reliable: it will not remove messages from .B MAILDIR until the messages have been successfully appended to .BR MAIL . .B maildir2mbox locks .B MAIL to protect against simultaneous access by a mail reader. This locking system does not protect against simultaneous access by another .BR maildir2mbox ; you should run only one .B maildir2mbox at a time. .SH "SEE ALSO" maildir(5) netqmail-1.06/str_rchr.c0000644000076400007640000000061506541176434014646 0ustar nelsonnelson#include "str.h" unsigned int str_rchr(s,c) register char *s; int c; { register char ch; register char *t; register char *u; ch = c; t = s; u = 0; for (;;) { if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; if (!*t) break; if (*t == ch) u = t; ++t; } if (!u) u = t; return u - s; } netqmail-1.06/open.h0000644000076400007640000000024306541176434013763 0ustar nelsonnelson#ifndef OPEN_H #define OPEN_H extern int open_read(); extern int open_excl(); extern int open_append(); extern int open_trunc(); extern int open_write(); #endif netqmail-1.06/readsubdir.c0000644000076400007640000000202706541176434015143 0ustar nelsonnelson#include "readsubdir.h" #include "fmt.h" #include "scan.h" #include "str.h" #include "auto_split.h" void readsubdir_init(rs,name,pause) readsubdir *rs; char *name; void (*pause)(); { rs->name = name; rs->pause = pause; rs->dir = 0; rs->pos = 0; } static char namepos[FMT_ULONG + 4 + READSUBDIR_NAMELEN]; int readsubdir_next(rs,id) readsubdir *rs; unsigned long *id; { direntry *d; unsigned int len; if (!rs->dir) { if (rs->pos >= auto_split) return 0; if (str_len(rs->name) > READSUBDIR_NAMELEN) { rs->pos++; return -1; } len = 0; len += fmt_str(namepos + len,rs->name); namepos[len++] = '/'; len += fmt_ulong(namepos + len,(unsigned long) rs->pos); namepos[len] = 0; while (!(rs->dir = opendir(namepos))) rs->pause(namepos); rs->pos++; return -1; } d = readdir(rs->dir); if (!d) { closedir(rs->dir); rs->dir = 0; return -1; } if (str_equal(d->d_name,".")) return -1; if (str_equal(d->d_name,"..")) return -1; len = scan_ulong(d->d_name,id); if (!len || d->d_name[len]) return -2; return 1; } netqmail-1.06/triggerpull.h0000644000076400007640000000012006541176434015354 0ustar nelsonnelson#ifndef TRIGGERPULL_H #define TRIGGERPULL_H extern void triggerpull(); #endif netqmail-1.06/dnsip.c0000644000076400007640000000110706541176434014132 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "stralloc.h" #include "dns.h" #include "dnsdoe.h" #include "ip.h" #include "ipalloc.h" #include "exit.h" char temp[IPFMT]; stralloc sa = {0}; ipalloc ia = {0}; void main(argc,argv) int argc; char **argv; { int j; if (!argv[1]) _exit(100); if (!stralloc_copys(&sa,argv[1])) { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); } dns_init(0); dnsdoe(dns_ip(&ia,&sa)); for (j = 0;j < ia.len;++j) { substdio_put(subfdout,temp,ip_fmt(temp,&ia.ix[j].ip)); substdio_putsflush(subfdout,"\n"); } _exit(0); } netqmail-1.06/SYSDEPS0000644000076400007640000000025206541176434013726 0ustar nelsonnelsonVERSION systype hasshsgr.h hasnpbg1.h select.h hasflock.h hassalen.h fork.h hassgact.h direntry.h hassgprm.h haswaitp.h hasmkffo.h uint32.h dns.lib socket.lib syslog.lib netqmail-1.06/str_diffn.c0000644000076400007640000000104606541176434014775 0ustar nelsonnelson#include "str.h" int str_diffn(s,t,len) register char *s; register char *t; unsigned int len; { register char x; for (;;) { if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; if (!len--) return 0; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; } return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } netqmail-1.06/qmail-remote.c0000644000076400007640000002530306541176434015415 0ustar nelsonnelson#include #include #include #include #include "sig.h" #include "stralloc.h" #include "substdio.h" #include "subfd.h" #include "scan.h" #include "case.h" #include "error.h" #include "auto_qmail.h" #include "control.h" #include "dns.h" #include "alloc.h" #include "quote.h" #include "ip.h" #include "ipalloc.h" #include "ipme.h" #include "gen_alloc.h" #include "gen_allocdefs.h" #include "str.h" #include "now.h" #include "exit.h" #include "constmap.h" #include "tcpto.h" #include "readwrite.h" #include "timeoutconn.h" #include "timeoutread.h" #include "timeoutwrite.h" #define HUGESMTPTEXT 5000 #define PORT_SMTP 25 /* silly rabbit, /etc/services is for users */ unsigned long port = PORT_SMTP; GEN_ALLOC_typedef(saa,stralloc,sa,len,a) GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) static stralloc sauninit = {0}; stralloc helohost = {0}; stralloc routes = {0}; struct constmap maproutes; stralloc host = {0}; stralloc sender = {0}; saa reciplist = {0}; struct ip_address partner; void out(s) char *s; { if (substdio_puts(subfdoutsmall,s) == -1) _exit(0); } void zero() { if (substdio_put(subfdoutsmall,"\0",1) == -1) _exit(0); } void zerodie() { zero(); substdio_flush(subfdoutsmall); _exit(0); } void outsafe(sa) stralloc *sa; { int i; char ch; for (i = 0;i < sa->len;++i) { ch = sa->s[i]; if (ch < 33) ch = '?'; if (ch > 126) ch = '?'; if (substdio_put(subfdoutsmall,&ch,1) == -1) _exit(0); } } void temp_nomem() { out("ZOut of memory. (#4.3.0)\n"); zerodie(); } void temp_oserr() { out("Z\ System resources temporarily unavailable. (#4.3.0)\n"); zerodie(); } void temp_noconn() { out("Z\ Sorry, I wasn't able to establish an SMTP connection. (#4.4.1)\n"); zerodie(); } void temp_read() { out("ZUnable to read message. (#4.3.0)\n"); zerodie(); } void temp_dnscanon() { out("Z\ CNAME lookup failed temporarily. (#4.4.3)\n"); zerodie(); } void temp_dns() { out("Z\ Sorry, I couldn't find any host by that name. (#4.1.2)\n"); zerodie(); } void temp_chdir() { out("Z\ Unable to switch to home directory. (#4.3.0)\n"); zerodie(); } void temp_control() { out("Z\ Unable to read control files. (#4.3.0)\n"); zerodie(); } void perm_partialline() { out("D\ SMTP cannot transfer messages with partial final lines. (#5.6.2)\n"); zerodie(); } void perm_usage() { out("D\ I (qmail-remote) was invoked improperly. (#5.3.5)\n"); zerodie(); } void perm_dns() { out("D\ Sorry, I couldn't find any host named "); outsafe(&host); out(". (#5.1.2)\n"); zerodie(); } void perm_nomx() { out("D\ Sorry, I couldn't find a mail exchanger or IP address. (#5.4.4)\n"); zerodie(); } void perm_ambigmx() { out("D\ Sorry. Although I'm listed as a best-preference MX or A for that host,\n\ it isn't in my control/locals file, so I don't treat it as local. (#5.4.6)\n"); zerodie(); } void outhost() { char x[IPFMT]; if (substdio_put(subfdoutsmall,x,ip_fmt(x,&partner)) == -1) _exit(0); } int flagcritical = 0; void dropped() { out("ZConnected to "); outhost(); out(" but connection died. "); if (flagcritical) out("Possible duplicate! "); out("(#4.4.2)\n"); zerodie(); } int timeoutconnect = 60; int smtpfd; int timeout = 1200; int saferead(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutread(timeout,smtpfd,buf,len); if (r <= 0) dropped(); return r; } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = timeoutwrite(timeout,smtpfd,buf,len); if (r <= 0) dropped(); return r; } char inbuf[1024]; substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); char smtptobuf[1024]; substdio smtpto = SUBSTDIO_FDBUF(safewrite,-1,smtptobuf,sizeof smtptobuf); char smtpfrombuf[128]; substdio smtpfrom = SUBSTDIO_FDBUF(saferead,-1,smtpfrombuf,sizeof smtpfrombuf); stralloc smtptext = {0}; void get(ch) char *ch; { substdio_get(&smtpfrom,ch,1); if (*ch != '\r') if (smtptext.len < HUGESMTPTEXT) if (!stralloc_append(&smtptext,ch)) temp_nomem(); } unsigned long smtpcode() { unsigned char ch; unsigned long code; if (!stralloc_copys(&smtptext,"")) temp_nomem(); get(&ch); code = ch - '0'; get(&ch); code = code * 10 + (ch - '0'); get(&ch); code = code * 10 + (ch - '0'); for (;;) { get(&ch); if (ch != '-') break; while (ch != '\n') get(&ch); get(&ch); get(&ch); get(&ch); } while (ch != '\n') get(&ch); return code; } void outsmtptext() { int i; if (smtptext.s) if (smtptext.len) { out("Remote host said: "); for (i = 0;i < smtptext.len;++i) if (!smtptext.s[i]) smtptext.s[i] = '?'; if (substdio_put(subfdoutsmall,smtptext.s,smtptext.len) == -1) _exit(0); smtptext.len = 0; } } void quit(prepend,append) char *prepend; char *append; { substdio_putsflush(&smtpto,"QUIT\r\n"); /* waiting for remote side is just too ridiculous */ out(prepend); outhost(); out(append); out(".\n"); outsmtptext(); zerodie(); } void blast() { int r; char ch; for (;;) { r = substdio_get(&ssin,&ch,1); if (r == 0) break; if (r == -1) temp_read(); if (ch == '.') substdio_put(&smtpto,".",1); while (ch != '\n') { substdio_put(&smtpto,&ch,1); r = substdio_get(&ssin,&ch,1); if (r == 0) perm_partialline(); if (r == -1) temp_read(); } substdio_put(&smtpto,"\r\n",2); } flagcritical = 1; substdio_put(&smtpto,".\r\n",3); substdio_flush(&smtpto); } stralloc recip = {0}; void smtp() { unsigned long code; int flagbother; int i; if (smtpcode() != 220) quit("ZConnected to "," but greeting failed"); substdio_puts(&smtpto,"HELO "); substdio_put(&smtpto,helohost.s,helohost.len); substdio_puts(&smtpto,"\r\n"); substdio_flush(&smtpto); if (smtpcode() != 250) quit("ZConnected to "," but my name was rejected"); substdio_puts(&smtpto,"MAIL FROM:<"); substdio_put(&smtpto,sender.s,sender.len); substdio_puts(&smtpto,">\r\n"); substdio_flush(&smtpto); code = smtpcode(); if (code >= 500) quit("DConnected to "," but sender was rejected"); if (code >= 400) quit("ZConnected to "," but sender was rejected"); flagbother = 0; for (i = 0;i < reciplist.len;++i) { substdio_puts(&smtpto,"RCPT TO:<"); substdio_put(&smtpto,reciplist.sa[i].s,reciplist.sa[i].len); substdio_puts(&smtpto,">\r\n"); substdio_flush(&smtpto); code = smtpcode(); if (code >= 500) { out("h"); outhost(); out(" does not like recipient.\n"); outsmtptext(); zero(); } else if (code >= 400) { out("s"); outhost(); out(" does not like recipient.\n"); outsmtptext(); zero(); } else { out("r"); zero(); flagbother = 1; } } if (!flagbother) quit("DGiving up on ",""); substdio_putsflush(&smtpto,"DATA\r\n"); code = smtpcode(); if (code >= 500) quit("D"," failed on DATA command"); if (code >= 400) quit("Z"," failed on DATA command"); blast(); code = smtpcode(); flagcritical = 0; if (code >= 500) quit("D"," failed after I sent the message"); if (code >= 400) quit("Z"," failed after I sent the message"); quit("K"," accepted message"); } stralloc canonhost = {0}; stralloc canonbox = {0}; void addrmangle(saout,s,flagalias,flagcname) stralloc *saout; /* host has to be canonical, box has to be quoted */ char *s; int *flagalias; int flagcname; { int j; *flagalias = flagcname; j = str_rchr(s,'@'); if (!s[j]) { if (!stralloc_copys(saout,s)) temp_nomem(); return; } if (!stralloc_copys(&canonbox,s)) temp_nomem(); canonbox.len = j; if (!quote(saout,&canonbox)) temp_nomem(); if (!stralloc_cats(saout,"@")) temp_nomem(); if (!stralloc_copys(&canonhost,s + j + 1)) temp_nomem(); if (flagcname) switch(dns_cname(&canonhost)) { case 0: *flagalias = 0; break; case DNS_MEM: temp_nomem(); case DNS_SOFT: temp_dnscanon(); case DNS_HARD: ; /* alias loop, not our problem */ } if (!stralloc_cat(saout,&canonhost)) temp_nomem(); } void getcontrols() { if (control_init() == -1) temp_control(); if (control_readint(&timeout,"control/timeoutremote") == -1) temp_control(); if (control_readint(&timeoutconnect,"control/timeoutconnect") == -1) temp_control(); if (control_rldef(&helohost,"control/helohost",1,(char *) 0) != 1) temp_control(); switch(control_readfile(&routes,"control/smtproutes",0)) { case -1: temp_control(); case 0: if (!constmap_init(&maproutes,"",0,1)) temp_nomem(); break; case 1: if (!constmap_init(&maproutes,routes.s,routes.len,1)) temp_nomem(); break; } } void main(argc,argv) int argc; char **argv; { static ipalloc ip = {0}; int i; unsigned long random; char **recips; unsigned long prefme; int flagallaliases; int flagalias; char *relayhost; sig_pipeignore(); if (argc < 4) perm_usage(); if (chdir(auto_qmail) == -1) temp_chdir(); getcontrols(); if (!stralloc_copys(&host,argv[1])) temp_nomem(); relayhost = 0; for (i = 0;i <= host.len;++i) if ((i == 0) || (i == host.len) || (host.s[i] == '.')) if (relayhost = constmap(&maproutes,host.s + i,host.len - i)) break; if (relayhost && !*relayhost) relayhost = 0; if (relayhost) { i = str_chr(relayhost,':'); if (relayhost[i]) { scan_ulong(relayhost + i + 1,&port); relayhost[i] = 0; } if (!stralloc_copys(&host,relayhost)) temp_nomem(); } addrmangle(&sender,argv[2],&flagalias,0); if (!saa_readyplus(&reciplist,0)) temp_nomem(); if (ipme_init() != 1) temp_oserr(); flagallaliases = 1; recips = argv + 3; while (*recips) { if (!saa_readyplus(&reciplist,1)) temp_nomem(); reciplist.sa[reciplist.len] = sauninit; addrmangle(reciplist.sa + reciplist.len,*recips,&flagalias,!relayhost); if (!flagalias) flagallaliases = 0; ++reciplist.len; ++recips; } random = now() + (getpid() << 16); switch (relayhost ? dns_ip(&ip,&host) : dns_mxip(&ip,&host,random)) { case DNS_MEM: temp_nomem(); case DNS_SOFT: temp_dns(); case DNS_HARD: perm_dns(); case 1: if (ip.len <= 0) temp_dns(); } if (ip.len <= 0) perm_nomx(); prefme = 100000; for (i = 0;i < ip.len;++i) if (ipme_is(&ip.ix[i].ip)) if (ip.ix[i].pref < prefme) prefme = ip.ix[i].pref; if (relayhost) prefme = 300000; if (flagallaliases) prefme = 500000; for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) break; if (i >= ip.len) perm_ambigmx(); for (i = 0;i < ip.len;++i) if (ip.ix[i].pref < prefme) { if (tcpto(&ip.ix[i].ip)) continue; smtpfd = socket(AF_INET,SOCK_STREAM,0); if (smtpfd == -1) temp_oserr(); if (timeoutconn(smtpfd,&ip.ix[i].ip,(unsigned int) port,timeoutconnect) == 0) { tcpto_err(&ip.ix[i].ip,0); partner = ip.ix[i].ip; smtp(); /* does not return */ } tcpto_err(&ip.ix[i].ip,errno == error_timeout); close(smtpfd); } temp_noconn(); } netqmail-1.06/now.h0000644000076400007640000000012706541176434013626 0ustar nelsonnelson#ifndef NOW_H #define NOW_H #include "datetime.h" extern datetime_sec now(); #endif netqmail-1.06/qmail-clean.80000644000076400007640000000042106541176434015123 0ustar nelsonnelson.TH qmail-clean 8 .SH NAME qmail-clean \- clean up the queue directory .SH SYNOPSIS .B qmail-clean .SH DESCRIPTION .B qmail-clean reads a cleanup command from descriptor 0, performs the cleanup, prints the results to descriptor 1, and repeats. .SH "SEE ALSO" qmail-send(8) netqmail-1.06/qmail-limits.90000644000076400007640000000144306541176434015350 0ustar nelsonnelson.TH qmail-limits 7 .SH "NAME" qmail-limits \- artificial limits in the qmail system .SH "DESCRIPTION" The .B qmail system is able to handle messages of any size, addresses of any size, mailing lists of any size, and so on, except as limited by the available memory and disk space. However, it imposes certain artificial limits: .TP 5 1. .B qmail-lspawn silently limits the number of simultaneous local deliveries to SPAWN. .B qmail-rspawn silently limits the number of simultaneous remote deliveries to SPAWN. .TP 5 2. .B qmail-queue rejects any message with an envelope address longer than 1000 characters. .TP 5 3. .B qmail-lspawn truncates any overly long error report from a delivery program. It appends a note saying that it did so. .SH "SEE ALSO" qmail-lspawn(8), qmail-queue(8), qmail-rspawn(8) netqmail-1.06/str_chr.c0000644000076400007640000000053606541176434014466 0ustar nelsonnelson#include "str.h" unsigned int str_chr(s,c) register char *s; int c; { register char ch; register char *t; ch = c; t = s; for (;;) { if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; if (!*t) break; if (*t == ch) break; ++t; } return t - s; } netqmail-1.06/remoteinfo.c0000644000076400007640000000346606541176434015176 0ustar nelsonnelson#include #include #include #include #include "byte.h" #include "substdio.h" #include "ip.h" #include "fmt.h" #include "timeoutconn.h" #include "timeoutread.h" #include "timeoutwrite.h" #include "remoteinfo.h" static char line[999]; static int t; static int mywrite(fd,buf,len) int fd; char *buf; int len; { return timeoutwrite(t,fd,buf,len); } static int myread(fd,buf,len) int fd; char *buf; int len; { return timeoutread(t,fd,buf,len); } char *remoteinfo_get(ipr,rp,ipl,lp,timeout) struct ip_address *ipr; unsigned long rp; struct ip_address *ipl; unsigned long lp; int timeout; { char *x; int s; struct sockaddr_in sin; substdio ss; char buf[32]; unsigned int len; int numcolons; char ch; t = timeout; s = socket(AF_INET,SOCK_STREAM,0); if (s == -1) return 0; byte_zero(&sin,sizeof(sin)); sin.sin_family = AF_INET; byte_copy(&sin.sin_addr,4,ipl); sin.sin_port = 0; if (bind(s,(struct sockaddr *) &sin,sizeof(sin)) == -1) { close(s); return 0; } if (timeoutconn(s,ipr,113,timeout) == -1) { close(s); return 0; } fcntl(s,F_SETFL,fcntl(s,F_GETFL,0) & ~O_NDELAY); len = 0; len += fmt_ulong(line + len,rp); len += fmt_str(line + len," , "); len += fmt_ulong(line + len,lp); len += fmt_str(line + len,"\r\n"); substdio_fdbuf(&ss,mywrite,s,buf,sizeof buf); if (substdio_putflush(&ss,line,len) == -1) { close(s); return 0; } substdio_fdbuf(&ss,myread,s,buf,sizeof buf); x = line; numcolons = 0; for (;;) { if (substdio_get(&ss,&ch,1) != 1) { close(s); return 0; } if ((ch == ' ') || (ch == '\t') || (ch == '\r')) continue; if (ch == '\n') break; if (numcolons < 3) { if (ch == ':') ++numcolons; } else { *x++ = ch; if (x == line + sizeof(line) - 1) break; } } *x = 0; close(s); return line; } netqmail-1.06/auto_usera.h0000644000076400007640000000011506541176434015167 0ustar nelsonnelson#ifndef AUTO_USERA_H #define AUTO_USERA_H extern char auto_usera[]; #endif netqmail-1.06/myctime.c0000644000076400007640000000155006541176434014466 0ustar nelsonnelson#include "datetime.h" #include "fmt.h" #include "myctime.h" static char *daytab[7] = { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" }; static char *montab[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; static char result[30]; char *myctime(t) datetime_sec t; { struct datetime dt; unsigned int len; datetime_tai(&dt,t); len = 0; len += fmt_str(result + len,daytab[dt.wday]); result[len++] = ' '; len += fmt_str(result + len,montab[dt.mon]); result[len++] = ' '; len += fmt_uint0(result + len,dt.mday,2); result[len++] = ' '; len += fmt_uint0(result + len,dt.hour,2); result[len++] = ':'; len += fmt_uint0(result + len,dt.min,2); result[len++] = ':'; len += fmt_uint0(result + len,dt.sec,2); result[len++] = ' '; len += fmt_uint(result + len,1900 + dt.year); result[len++] = '\n'; result[len++] = 0; return result; } netqmail-1.06/make-makelib.sh0000644000076400007640000000032206541176434015522 0ustar nelsonnelsonecho 'main="$1"; shift' echo 'rm -f "$main"' echo 'ar cr "$main" ${1+"$@"}' case "$1" in sunos-5.*) ;; unix_sv*) ;; irix64-*) ;; irix-*) ;; dgux-*) ;; hp-ux-*) ;; sco*) ;; *) echo 'ranlib "$main"' ;; esac netqmail-1.06/forgeries.70000644000076400007640000000561606541176434014737 0ustar nelsonnelson.TH forgeries 7 .SH "NAME" forgeries \- how easy it is to forge mail .SH "SUMMARY" An electronic mail message can easily be forged. Almost everything in it, including the return address, is completely under the control of the sender. An electronic mail message can be manually traced to its origin if (1) all system administrators of intermediate machines are both cooperative and competent, (2) the sender did not break low-level TCP/IP security, and (3) all intermediate machines are secure. Users of .I cryptography can automatically ensure the integrity and secrecy of their mail messages, as long as the sending and receiving machines are secure. .SH "FORGERIES" Like postal mail, electronic mail can be created entirely at the whim of the sender. .BR From , .BR Sender , .BR Return-Path , and .BR Message-ID can all contain whatever information the sender wants. For example, if you inject a message through .B sendmail or .B qmail-inject or .BR SMTP , you can simply type in a .B From field. In fact, .B qmail-inject lets you set up .BR MAILUSER , .BR MAILHOST , and .B MAILNAME environment variables to produce your desired .B From field on every message. .SH "TRACING FORGERIES" Like postal mail, electronic mail is postmarked when it is sent. Each machine that receives an electronic mail message adds a .B Received line to the top. A modern .B Received line contains quite a bit of information. In conjunction with the machine's logs, it lets a competent system administrator determine where the machine received the message from, as long as the sender did not break low-level TCP/IP security or security on that machine. Large multi-user machines often come with inadequate logging software. Fortunately, a system administrator can easily obtain a copy of a 931/1413/Ident/TAP server, such as .BR pidentd . Unfortunately, some system administrators fail to do this, and are thus unable to figure out which local user was responsible for generating a message. If all intermediate system administrators are competent, and the sender did not break machine security or low-level TCP/IP security, it is possible to trace a message backwards. Unfortunately, some traces are stymied by intermediate system administrators who are uncooperative or untrustworthy. .SH "CRYPTOGRAPHY" The sender of a mail message may place his message into a .I cryptographic envelope stamped with his seal. Strong cryptography guarantees that any two messages with the same seal were sent by the same cryptographic entity: perhaps a single person, perhaps a group of cooperating people, but in any case somebody who knows a secret originally held only by the creator of the seal. The seal is called a .I public key\fR. Unfortunately, the creator of the seal is often an insecure machine, or an untrustworthy central agency, but most of the time seals are kept secure. One popular cryptographic program is .BR pgp . .SH "SEE ALSO" pgp(1), identd(8), qmail-header(8) netqmail-1.06/select.h10000644000076400007640000000015506541176434014364 0ustar nelsonnelson#ifndef SELECT_H #define SELECT_H #include #include extern int select(); #endif netqmail-1.06/cdb_seek.c0000644000076400007640000000334310724070436014551 0ustar nelsonnelson#include #include #include "cdb.h" #ifndef SEEK_SET #define SEEK_SET 0 #endif int cdb_bread(fd,buf,len) int fd; char *buf; int len; { int r; while (len > 0) { do r = read(fd,buf,len); while ((r == -1) && (errno == EINTR)); if (r == -1) return -1; if (r == 0) { errno = EIO; return -1; } buf += r; len -= r; } return 0; } static int match(fd,key,len) int fd; char *key; unsigned int len; { char buf[32]; int n; int i; while (len > 0) { n = sizeof(buf); if (n > len) n = len; if (cdb_bread(fd,buf,n) == -1) return -1; for (i = 0;i < n;++i) if (buf[i] != key[i]) return 0; key += n; len -= n; } return 1; } int cdb_seek(fd,key,len,dlen) int fd; char *key; unsigned int len; uint32 *dlen; { char packbuf[8]; uint32 pos; uint32 h; uint32 lenhash; uint32 h2; uint32 loop; uint32 poskd; h = cdb_hash(key,len); pos = 8 * (h & 255); if (lseek(fd,(off_t) pos,SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; pos = cdb_unpack(packbuf); lenhash = cdb_unpack(packbuf + 4); if (!lenhash) return 0; h2 = (h >> 8) % lenhash; for (loop = 0;loop < lenhash;++loop) { if (lseek(fd,(off_t) (pos + 8 * h2),SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; poskd = cdb_unpack(packbuf + 4); if (!poskd) return 0; if (cdb_unpack(packbuf) == h) { if (lseek(fd,(off_t) poskd,SEEK_SET) == -1) return -1; if (cdb_bread(fd,packbuf,8) == -1) return -1; if (cdb_unpack(packbuf) == len) switch(match(fd,key,len)) { case -1: return -1; case 1: *dlen = cdb_unpack(packbuf + 4); return 1; } } if (++h2 == lenhash) h2 = 0; } return 0; } netqmail-1.06/getln2.c0000644000076400007640000000126006541176434014210 0ustar nelsonnelson#include "substdio.h" #include "stralloc.h" #include "byte.h" #include "getln.h" int getln2(ss,sa,cont,clen,sep) register substdio *ss; register stralloc *sa; /*@out@*/char **cont; /*@out@*/unsigned int *clen; int sep; { register char *x; register unsigned int i; int n; if (!stralloc_ready(sa,0)) return -1; sa->len = 0; for (;;) { n = substdio_feed(ss); if (n < 0) return -1; if (n == 0) { *clen = 0; return 0; } x = substdio_PEEK(ss); i = byte_chr(x,n,sep); if (i < n) { substdio_SEEK(ss,*clen = i + 1); *cont = x; return 0; } if (!stralloc_readyplus(sa,n)) return -1; i = sa->len; sa->len = i + substdio_get(ss,sa->s + i,n); } } netqmail-1.06/stralloc_cat.c0000644000076400007640000000024106541176434015465 0ustar nelsonnelson#include "byte.h" #include "stralloc.h" int stralloc_cat(sato,safrom) stralloc *sato; stralloc *safrom; { return stralloc_catb(sato,safrom->s,safrom->len); } netqmail-1.06/scan.h0000644000076400007640000000126606541176434013754 0ustar nelsonnelson#ifndef SCAN_H #define SCAN_H extern unsigned int scan_uint(); extern unsigned int scan_xint(); extern unsigned int scan_nbbint(); extern unsigned int scan_ushort(); extern unsigned int scan_xshort(); extern unsigned int scan_nbbshort(); extern unsigned int scan_ulong(); extern unsigned int scan_xlong(); extern unsigned int scan_nbblong(); extern unsigned int scan_plusminus(); extern unsigned int scan_0x(); extern unsigned int scan_whitenskip(); extern unsigned int scan_nonwhitenskip(); extern unsigned int scan_charsetnskip(); extern unsigned int scan_noncharsetnskip(); extern unsigned int scan_strncmp(); extern unsigned int scan_memcmp(); extern unsigned int scan_long(); #endif netqmail-1.06/qmail-pw2u.90000644000076400007640000000642106541176434014745 0ustar nelsonnelson.TH qmail-pw2u 8 .SH NAME qmail-pw2u \- build address assignments from a passwd file .SH SYNOPSIS .B qmail-pw2u [ .B \-/ohHuUC ] [ .B \-c\fIchar ] .SH DESCRIPTION .B qmail-pw2u reads a V7-format passwd file from standard input and prints a .BR qmail-users -format assignment file. A V7-format passwd file is a series of lines. Each line has the format .EX user:password:uid:gid:gecos:home:shell .EE where .I user is an account name, .I uid and .I gid are the user id and group id of that account, and .I home is the account's home directory. .IR password , .IR gecos , and .I shell are ignored by .BR qmail-pw2u . If you put the output of .B qmail-pw2u into .BR QMAILHOME/users/assign , and then run .BR qmail-newu , .B qmail-lspawn will obey the assignments printed by .BR qmail-pw2u . .B WARNING: After changing any users, uids, gids, or home directories in your passwd file, you must run .B qmail-pw2u and .B qmail-newu again if you want .B qmail-lspawn to see the changes. .SH RULES By default, .B qmail-pw2u follows the same rules as .BR qmail-getpw . It skips .I user if (1) .I uid is zero, (2) .I home does not exist, (3) .I user does not own .IR home , or (4) .I user contains uppercase letters. It then gives each remaining .I user control over the basic .I user address and all addresses of the form .IR user\fBBREAK\fIanything . A catch-all user, .BR alias , controls all other addresses. You may change these rules by setting up files in .BR QMAILHOME/users : .TP .B include Allowed users, one per line. If .B include exists, and .I user is not listed in .BR include , .I user is ignored. .TP .B exclude Ignored users, one per line. If .B exclude exists, and .I user is listed in .BR exclude , .I user is ignored. .TP .B mailnames Replacement names for users. Each line has the form .EX user:mailname1:mailname2:... .EE The addresses .I mailname1 and .I mailname1\fBBREAK\fIext and .I mailname2 and so on will be delivered to .IR user . .B WARNING: The addresses .I user and .I user\fBBREAK\fIext will not be delivered to .I user unless .I user is listed as one of the .IR mailname s. A line in .B mailnames is silently ignored if the user does not exist. .TP .B subusers Extra addresses. Each line has the form .EX sub:user:pre: .EE .I sub will be handled by .IR home\fB/.qmail\-\fIpre , where .I home is .IR user 's home directory; .I sub\fBBREAK\fIext will be handled by .IR home\fB/.qmail\-\fIpre\fB\-\fIext . .TP .B append Extra assignments, printed at the end of .BR qmail-pw2u 's output. .SH OPTIONS .TP .B \-o (Default.) Skip .I user if .I home does not exist (or is not visible to .BR qmail-pw2u ). Skip .I user if .I home is not owned by .IR user . .TP .B \-h Stop if .I home does not exist. This is appropriate if every user is supposed to have a home directory. Skip .I user if .I home is not owned by .IR user . .TP .B \-H Do not check the existence or ownership of .IR home . .TP .B \-U (Default.) Skip .I user if there are any uppercase letters in .IR user . .TP .B \-u Allow uppercase letters in .IR user . .TP .B \-c\fIchar Use .I char as the user-extension delimiter in place of .BR BREAK . .TP .B \-C Disable the user-extension mechanism. .TP .B \-/ Use .IR home\fB/.qmail\-/ ... instead of .IR home\fB/.qmail\- ... .SH "SEE ALSO" qmail-users(5), qmail-lspawn(8), qmail-newu(8), qmail-getpw(8) netqmail-1.06/maildir2mbox.c0000644000076400007640000001070706541176434015414 0ustar nelsonnelson#include "readwrite.h" #include "prioq.h" #include "env.h" #include "stralloc.h" #include "subfd.h" #include "substdio.h" #include "getln.h" #include "error.h" #include "open.h" #include "lock.h" #include "gfrom.h" #include "str.h" #include "exit.h" #include "myctime.h" #include "maildir.h" char *mbox; char *mboxtmp; stralloc filenames = {0}; prioq pq = {0}; prioq pq2 = {0}; stralloc line = {0}; stralloc ufline = {0}; char inbuf[SUBSTDIO_INSIZE]; char outbuf[SUBSTDIO_OUTSIZE]; #define FATAL "maildir2mbox: fatal: " #define WARNING "maildir2mbox: warning: " void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); } void main() { substdio ssin; substdio ssout; struct prioq_elt pe; int fdoldmbox; int fdnewmbox; int fd; int match; int fdlock; umask(077); mbox = env_get("MAIL"); if (!mbox) strerr_die2x(111,FATAL,"MAIL not set"); mboxtmp = env_get("MAILTMP"); if (!mboxtmp) strerr_die2x(111,FATAL,"MAILTMP not set"); if (maildir_chdir() == -1) strerr_die1(111,FATAL,&maildir_chdir_err); maildir_clean(&filenames); if (maildir_scan(&pq,&filenames,1,1) == -1) strerr_die1(111,FATAL,&maildir_scan_err); if (!prioq_min(&pq,&pe)) _exit(0); /* nothing new */ fdlock = open_append(mbox); if (fdlock == -1) strerr_die4sys(111,FATAL,"unable to lock ",mbox,": "); if (lock_ex(fdlock) == -1) strerr_die4sys(111,FATAL,"unable to lock ",mbox,": "); fdoldmbox = open_read(mbox); if (fdoldmbox == -1) strerr_die4sys(111,FATAL,"unable to read ",mbox,": "); fdnewmbox = open_trunc(mboxtmp); if (fdnewmbox == -1) strerr_die4sys(111,FATAL,"unable to create ",mboxtmp,": "); substdio_fdbuf(&ssin,read,fdoldmbox,inbuf,sizeof(inbuf)); substdio_fdbuf(&ssout,write,fdnewmbox,outbuf,sizeof(outbuf)); switch(substdio_copy(&ssout,&ssin)) { case -2: strerr_die4sys(111,FATAL,"unable to read ",mbox,": "); case -3: strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); } while (prioq_min(&pq,&pe)) { prioq_delmin(&pq); if (!prioq_insert(&pq2,&pe)) die_nomem(); fd = open_read(filenames.s + pe.id); if (fd == -1) strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": "); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); if (getln(&ssin,&line,&match,'\n') != 0) strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": "); if (!stralloc_copys(&ufline,"From XXX ")) die_nomem(); if (match) if (stralloc_starts(&line,"Return-Path: <")) { if (line.s[14] == '>') { if (!stralloc_copys(&ufline,"From MAILER-DAEMON ")) die_nomem(); } else { int i; if (!stralloc_ready(&ufline,line.len)) die_nomem(); if (!stralloc_copys(&ufline,"From ")) die_nomem(); for (i = 14;i < line.len - 2;++i) if ((line.s[i] == ' ') || (line.s[i] == '\t')) ufline.s[ufline.len++] = '-'; else ufline.s[ufline.len++] = line.s[i]; if (!stralloc_cats(&ufline," ")) die_nomem(); } } if (!stralloc_cats(&ufline,myctime(pe.dt))) die_nomem(); if (substdio_put(&ssout,ufline.s,ufline.len) == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); while (match && line.len) { if (gfrom(line.s,line.len)) if (substdio_puts(&ssout,">") == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); if (substdio_put(&ssout,line.s,line.len) == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); if (!match) { if (substdio_puts(&ssout,"\n") == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); break; } if (getln(&ssin,&line,&match,'\n') != 0) strerr_die4sys(111,FATAL,"unable to read $MAILDIR/",filenames.s + pe.id,": "); } if (substdio_puts(&ssout,"\n")) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); close(fd); } if (substdio_flush(&ssout) == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); if (fsync(fdnewmbox) == -1) strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); if (close(fdnewmbox) == -1) /* NFS dorks */ strerr_die4sys(111,FATAL,"unable to write to ",mboxtmp,": "); if (rename(mboxtmp,mbox) == -1) strerr_die6(111,FATAL,"unable to move ",mboxtmp," to ",mbox,": ",&strerr_sys); while (prioq_min(&pq2,&pe)) { prioq_delmin(&pq2); if (unlink(filenames.s + pe.id) == -1) strerr_warn4(WARNING,"$MAILDIR/",filenames.s + pe.id," will be delivered twice; unable to unlink: ",&strerr_sys); } _exit(0); } netqmail-1.06/datetime.c0000644000076400007640000000216006541176434014611 0ustar nelsonnelson/* 19950925 */ #include "datetime.h" void datetime_tai(dt,t) struct datetime *dt; datetime_sec t; { int day; int tod; int year; int yday; int wday; int mon; tod = t % 86400; day = t / 86400; if (tod < 0) { tod += 86400; --day; } dt->hour = tod / 3600; tod %= 3600; dt->min = tod / 60; dt->sec = tod % 60; wday = (day + 4) % 7; if (wday < 0) wday += 7; dt->wday = wday; day -= 11017; /* day 0 is march 1, 2000 */ year = 5 + day / 146097; day = day % 146097; if (day < 0) { day += 146097; --year; } /* from now on, day is nonnegative */ year *= 4; if (day == 146096) { year += 3; day = 36524; } else { year += day / 36524; day %= 36524; } year *= 25; year += day / 1461; day %= 1461; year *= 4; yday = (day < 306); if (day == 1460) { year += 3; day = 365; } else { year += day / 365; day %= 365; } yday += day; day *= 10; mon = (day + 5) / 306; day = day + 5 - 306 * mon; day /= 10; if (mon >= 10) { yday -= 306; ++year; mon -= 10; } else { yday += 59; mon += 2; } dt->yday = yday; dt->year = year - 1900; dt->mon = mon; dt->mday = day + 1; } netqmail-1.06/tryvfork.c0000644000076400007640000000003306541176434014700 0ustar nelsonnelsonvoid main() { vfork(); } netqmail-1.06/slurpclose.h0000644000076400007640000000011406541176434015212 0ustar nelsonnelson#ifndef SLURPCLOSE_H #define SLURPCLOSE_H extern int slurpclose(); #endif netqmail-1.06/byte_copy.c0000644000076400007640000000045306541176434015015 0ustar nelsonnelson#include "byte.h" void byte_copy(to,n,from) register char *to; register unsigned int n; register char *from; { for (;;) { if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; if (!n) return; *to++ = *from++; --n; } } netqmail-1.06/maildir.50000644000076400007640000001207706541176434014370 0ustar nelsonnelson.TH maildir 5 .SH "NAME" maildir \- directory for incoming mail messages .SH "INTRODUCTION" .I maildir is a structure for directories of incoming mail messages. It solves the reliability problems that plague .I mbox files and .I mh folders. .SH "RELIABILITY ISSUES" A machine may crash while it is delivering a message. For both .I mbox files and .I mh folders this means that the message will be silently truncated. Even worse: for .I mbox format, if the message is truncated in the middle of a line, it will be silently joined to the next message. The mail transport agent will try again later to deliver the message, but it is unacceptable that a corrupted message should show up at all. In .IR maildir , every message is guaranteed complete upon delivery. A machine may have two programs simultaneously delivering mail to the same user. The .I mbox and .I mh formats require the programs to update a single central file. If the programs do not use some locking mechanism, the central file will be corrupted. There are several .I mbox and .I mh locking mechanisms, none of which work portably and reliably. In contrast, in .IR maildir , no locks are ever necessary. Different delivery processes never touch the same file. A user may try to delete messages from his mailbox at the same moment that the machine delivers a new message. For .I mbox and .I mh formats, the user's mail-reading program must know what locking mechanism the mail-delivery programs use. In contrast, in .IR maildir , any delivered message can be safely updated or deleted by a mail-reading program. Many sites use Sun's .B Network F\fPa\fBil\fPur\fBe System (NFS), presumably because the operating system vendor does not offer anything else. NFS exacerbates all of the above problems. Some NFS implementations don't provide .B any reliable locking mechanism. With .I mbox and .I mh formats, if two machines deliver mail to the same user, or if a user reads mail anywhere except the delivery machine, the user's mail is at risk. .I maildir works without trouble over NFS. .SH "THE MAILDIR STRUCTURE" A directory in .I maildir format has three subdirectories, all on the same filesystem: .BR tmp , .BR new , and .BR cur . Each file in .B new is a newly delivered mail message. The modification time of the file is the delivery date of the message. The message is delivered .I without an extra UUCP-style .B From_ line, .I without any .B >From quoting, and .I without an extra blank line at the end. The message is normally in RFC 822 format, starting with a .B Return-Path line and a .B Delivered-To line, but it could contain arbitrary binary data. It might not even end with a newline. Files in .B cur are just like files in .BR new . The big difference is that files in .B cur are no longer new mail: they have been seen by the user's mail-reading program. .SH "HOW A MESSAGE IS DELIVERED" The .B tmp directory is used to ensure reliable delivery, as discussed here. A program delivers a mail message in six steps. First, it .B chdir()\fPs to the .I maildir directory. Second, it .B stat()s the name .BR tmp/\fItime.pid.host , where .I time is the number of seconds since the beginning of 1970 GMT, .I pid is the program's process ID, and .I host is the host name. Third, if .B stat() returned anything other than ENOENT, the program sleeps for two seconds, updates .IR time , and tries the .B stat() again, a limited number of times. Fourth, the program creates .BR tmp/\fItime.pid.host . Fifth, the program .I NFS-writes the message to the file. Sixth, the program .BR link() s the file to .BR new/\fItime.pid.host . At that instant the message has been successfully delivered. The delivery program is required to start a 24-hour timer before creating .BR tmp/\fItime.pid.host , and to abort the delivery if the timer expires. Upon error, timeout, or normal completion, the delivery program may attempt to .B unlink() .BR tmp/\fItime.pid.host . .I NFS-writing means (1) as usual, checking the number of bytes returned from each .B write() call; (2) calling .B fsync() and checking its return value; (3) calling .B close() and checking its return value. (Standard NFS implementations handle .B fsync() incorrectly but make up for it by abusing .BR close() .) .SH "HOW A MESSAGE IS READ" A mail reader operates as follows. It looks through the .B new directory for new messages. Say there is a new message, .BR new/\fIunique . The reader may freely display the contents of .BR new/\fIunique , delete .BR new/\fIunique , or rename .B new/\fIunique as .BR cur/\fIunique:info . See .B http://pobox.com/~djb/proto/maildir.html for the meaning of .IR info . The reader is also expected to look through the .B tmp directory and to clean up any old files found there. A file in .B tmp may be safely removed if it has not been accessed in 36 hours. It is a good idea for readers to skip all filenames in .B new and .B cur starting with a dot. Other than this, readers should not attempt to parse filenames. .SH "ENVIRONMENT VARIABLES" Mail readers supporting .I maildir use the .B MAILDIR environment variable as the name of the user's primary mail directory. .SH "SEE ALSO" mbox(5), qmail-local(8) netqmail-1.06/rcpthosts.c0000644000076400007640000000227406541176434015054 0ustar nelsonnelson#include "cdb.h" #include "byte.h" #include "open.h" #include "error.h" #include "control.h" #include "constmap.h" #include "stralloc.h" #include "rcpthosts.h" static int flagrh = 0; static stralloc rh = {0}; static struct constmap maprh; static int fdmrh; int rcpthosts_init() { flagrh = control_readfile(&rh,"control/rcpthosts",0); if (flagrh != 1) return flagrh; if (!constmap_init(&maprh,rh.s,rh.len,0)) return flagrh = -1; fdmrh = open_read("control/morercpthosts.cdb"); if (fdmrh == -1) if (errno != error_noent) return flagrh = -1; return 0; } static stralloc host = {0}; int rcpthosts(buf,len) char *buf; int len; { int j; if (flagrh != 1) return 1; j = byte_rchr(buf,len,'@'); if (j >= len) return 1; /* presumably envnoathost is acceptable */ ++j; buf += j; len -= j; if (!stralloc_copyb(&host,buf,len)) return -1; buf = host.s; case_lowerb(buf,len); for (j = 0;j < len;++j) if (!j || (buf[j] == '.')) if (constmap(&maprh,buf + j,len - j)) return 1; if (fdmrh != -1) { uint32 dlen; int r; for (j = 0;j < len;++j) if (!j || (buf[j] == '.')) { r = cdb_seek(fdmrh,buf + j,len - j,&dlen); if (r) return r; } } return 0; } netqmail-1.06/fmt_uint.c0000644000076400007640000000022606541176434014643 0ustar nelsonnelson#include "fmt.h" unsigned int fmt_uint(s,u) register char *s; register unsigned int u; { register unsigned long l; l = u; return fmt_ulong(s,l); } netqmail-1.06/wait.h0000644000076400007640000000044706541176434013774 0ustar nelsonnelson#ifndef WAIT_H #define WAIT_H extern int wait_pid(); extern int wait_nohang(); extern int wait_stop(); extern int wait_stopnohang(); #define wait_crashed(w) ((w) & 127) #define wait_exitcode(w) ((w) >> 8) #define wait_stopsig(w) ((w) >> 8) #define wait_stopped(w) (((w) & 127) == 127) #endif netqmail-1.06/config.sh0000644000076400007640000000401306541176434014451 0ustar nelsonnelson./hostname | tr '[A-Z]' '[a-z]' | ( if read host then echo Your hostname is "$host". ./dnsfq "$host" | tr '[A-Z]' '[a-z]' | ( if read fqdn then echo Your host\'s fully qualified name in DNS is "$fqdn". echo Putting "$fqdn" into control/me... echo "$fqdn" > QMAIL/control/me chmod 644 QMAIL/control/me ( echo "$fqdn" | sed 's/^\([^\.]*\)\.\([^\.]*\)\./\2\./' | ( read ddom echo Putting "$ddom" into control/defaultdomain... echo "$ddom" > QMAIL/control/defaultdomain chmod 644 QMAIL/control/defaultdomain ) ) ( echo "$fqdn" | sed 's/^.*\.\([^\.]*\)\.\([^\.]*\)$/\1.\2/' | ( read pdom echo Putting "$pdom" into control/plusdomain... echo "$pdom" > QMAIL/control/plusdomain chmod 644 QMAIL/control/plusdomain ) ) echo ' ' echo Checking local IP addresses: : > QMAIL/control/locals chmod 644 QMAIL/control/locals ( ./dnsip "$fqdn" ./ipmeprint ) | sort -u | \ ( while read localip do echo "$localip: " | tr -d '\012' ./dnsptr "$localip" 2>/dev/null | ( if read local then echo Adding "$local" to control/locals... echo "$local" >> QMAIL/control/locals else echo PTR lookup failed. I assume this address has no DNS name. fi ) done ) echo ' ' echo If there are any other domain names that point to you, echo you will have to add them to QMAIL/control/locals. echo You don\'t have to worry about aliases, i.e., domains with CNAME records. echo ' ' echo Copying QMAIL/control/locals to QMAIL/control/rcpthosts... cp QMAIL/control/locals QMAIL/control/rcpthosts chmod 644 QMAIL/control/rcpthosts echo 'Now qmail will refuse to accept SMTP messages except to those hosts.' echo 'Make sure to change rcpthosts if you add hosts to locals or virtualdomains!' else echo Sorry, I couldn\'t find your host\'s canonical name in DNS. echo You will have to set up control/me yourself. fi ) else echo Sorry, I couldn\'t find your hostname. echo You will have to set up control/me yourself. fi ) netqmail-1.06/INSTALL.vsm0000644000076400007640000000347106541176434014514 0ustar nelsonnelsonUNIX has traditionally delivered mail into a central spool directory, /var/spool/mail. (The original name was /usr/spool/mail; some systems now use /var/mail.) There are two basic problems with /var/spool/mail: * It's slow. On systems with thousands of users, /var/spool/mail has thousands of entries. A few UNIX systems support fast operations on large directories, but most don't. * It's insecure. Writing code that works safely in a world-writable directory is not easy. See, for example, CERT advisory 95:02. These may not be problems at your site, so you may want to leave your mailboxes in /var/spool/mail. This file explains several ways that you can configure qmail to use existing /var/spool/mail delivery tools. Please note that I do not vouch for the security or reliability of any of those tools. 1. What to configure The qmail system is started from /var/qmail/rc with qmail-start ./Mailbox splogger qmail The first argument to qmail-start, ./Mailbox, is the default delivery instruction. You can change it to run a program such as binmail or procmail. (See dot-qmail.0 for the format of delivery instructions.) 2. Using procmail You may already have installed procmail for mail filtering. procmail delivers to /var/spool/mail by default. To set up qmail to use procmail, simply copy /var/qmail/boot/proc to /var/qmail/rc. Note that procmail must be in your system's boot PATH; if it isn't, you will have edit /var/qmail/rc to include the full path. 3. Using sendmail's delivery agent sendmail uses binmail to deliver to /var/spool/mail. binmail is shipped with the operating system as /bin/mail or /usr/libexec/mail.local. There is some variation in binmail syntax among systems. The most common interfaces are shown in /var/qmail/boot/binm1, /var/qmail/boot/binm2, and /var/qmail/boot/binm3. netqmail-1.06/qmail-tcpto.c0000644000076400007640000000405406541176434015253 0ustar nelsonnelson/* XXX: this program knows quite a bit about tcpto's internals */ #include "substdio.h" #include "subfd.h" #include "auto_qmail.h" #include "fmt.h" #include "ip.h" #include "lock.h" #include "error.h" #include "exit.h" #include "datetime.h" #include "now.h" void die(n) int n; { substdio_flush(subfdout); _exit(n); } void warn(s) char *s; { char *x; x = error_str(errno); substdio_puts(subfdout,s); substdio_puts(subfdout,": "); substdio_puts(subfdout,x); substdio_puts(subfdout,"\n"); } void die_chdir() { warn("fatal: unable to chdir"); die(111); } void die_open() { warn("fatal: unable to open tcpto"); die(111); } void die_lock() { warn("fatal: unable to lock tcpto"); die(111); } void die_read() { warn("fatal: unable to read tcpto"); die(111); } char tcpto_buf[1024]; char tmp[FMT_ULONG + IPFMT]; void main() { int fdlock; int fd; int r; int i; char *record; struct ip_address ip; datetime_sec when; datetime_sec start; if (chdir(auto_qmail) == -1) die_chdir(); if (chdir("queue/lock") == -1) die_chdir(); fdlock = open_write("tcpto"); if (fdlock == -1) die_open(); fd = open_read("tcpto"); if (fd == -1) die_open(); if (lock_ex(fdlock) == -1) die_lock(); r = read(fd,tcpto_buf,sizeof(tcpto_buf)); close(fd); close(fdlock); if (r == -1) die_read(); r >>= 4; start = now(); record = tcpto_buf; for (i = 0;i < r;++i) { if (record[4] >= 1) { byte_copy(&ip,4,record); when = (unsigned long) (unsigned char) record[11]; when = (when << 8) + (unsigned long) (unsigned char) record[10]; when = (when << 8) + (unsigned long) (unsigned char) record[9]; when = (when << 8) + (unsigned long) (unsigned char) record[8]; substdio_put(subfdout,tmp,ip_fmt(tmp,&ip)); substdio_puts(subfdout," timed out "); substdio_put(subfdout,tmp,fmt_ulong(tmp,(unsigned long) (start - when))); substdio_puts(subfdout," seconds ago; # recent timeouts: "); substdio_put(subfdout,tmp,fmt_ulong(tmp,(unsigned long) (unsigned char) record[4])); substdio_puts(subfdout,"\n"); } record += 16; } die(0); } netqmail-1.06/fmtqfn.c0000644000076400007640000000074606541176434014320 0ustar nelsonnelson#include "fmtqfn.h" #include "fmt.h" #include "auto_split.h" unsigned int fmtqfn(s,dirslash,id,flagsplit) char *s; char *dirslash; unsigned long id; int flagsplit; { unsigned int len; unsigned int i; len = 0; i = fmt_str(s,dirslash); len += i; if (s) s += i; if (flagsplit) { i = fmt_ulong(s,id % auto_split); len += i; if (s) s += i; i = fmt_str(s,"/"); len += i; if (s) s += i; } i = fmt_ulong(s,id); len += i; if (s) s += i; if (s) *s++ = 0; ++len; return len; } netqmail-1.06/cdbmake.h0000644000076400007640000000126106541176434014411 0ustar nelsonnelson#ifndef CDBMAKE_H #define CDBMAKE_H #include "uint32.h" #define CDBMAKE_HPLIST 1000 struct cdbmake_hp { uint32 h; uint32 p; } ; struct cdbmake_hplist { struct cdbmake_hp hp[CDBMAKE_HPLIST]; struct cdbmake_hplist *next; int num; } ; struct cdbmake { char final[2048]; uint32 count[256]; uint32 start[256]; struct cdbmake_hplist *head; struct cdbmake_hp *split; /* includes space for hash */ struct cdbmake_hp *hash; uint32 numentries; } ; extern void cdbmake_pack(); #define CDBMAKE_HASHSTART ((uint32) 5381) extern uint32 cdbmake_hashadd(); extern void cdbmake_init(); extern int cdbmake_add(); extern int cdbmake_split(); extern uint32 cdbmake_throw(); #endif netqmail-1.06/auto_uids.h0000644000076400007640000000041606541176434015020 0ustar nelsonnelson#ifndef AUTO_UIDS_H #define AUTO_UIDS_H extern int auto_uida; extern int auto_uidd; extern int auto_uidl; extern int auto_uido; extern int auto_uidp; extern int auto_uidq; extern int auto_uidr; extern int auto_uids; extern int auto_gidn; extern int auto_gidq; #endif netqmail-1.06/trylsock.c0000644000076400007640000000001706541176434014666 0ustar nelsonnelsonmain() { ; } netqmail-1.06/hostname.c0000644000076400007640000000047606541176434014643 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "readwrite.h" #include "exit.h" char host[256]; void main() { host[0] = 0; /* sigh */ gethostname(host,sizeof(host)); host[sizeof(host) - 1] = 0; substdio_puts(subfdoutsmall,host); substdio_puts(subfdoutsmall,"\n"); substdio_flush(subfdoutsmall); _exit(0); } netqmail-1.06/ip.c0000644000076400007640000000254706541176434013436 0ustar nelsonnelson#include "fmt.h" #include "scan.h" #include "ip.h" unsigned int ip_fmt(s,ip) char *s; struct ip_address *ip; { unsigned int len; unsigned int i; len = 0; i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; return len; } unsigned int ip_scan(s,ip) char *s; struct ip_address *ip; { unsigned int i; unsigned int len; unsigned long u; len = 0; i = scan_ulong(s,&u); if (!i) return 0; ip->d[0] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip->d[1] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip->d[2] = u; s += i; len += i; if (*s != '.') return 0; ++s; ++len; i = scan_ulong(s,&u); if (!i) return 0; ip->d[3] = u; s += i; len += i; return len; } unsigned int ip_scanbracket(s,ip) char *s; struct ip_address *ip; { unsigned int len; if (*s != '[') return 0; len = ip_scan(s + 1,ip); if (!len) return 0; if (s[len + 1] != ']') return 0; return len + 2; } netqmail-1.06/stralloc_opyb.c0000644000076400007640000000037706541176434015701 0ustar nelsonnelson#include "stralloc.h" #include "byte.h" int stralloc_copyb(sa,s,n) stralloc *sa; char *s; unsigned int n; { if (!stralloc_ready(sa,n + 1)) return 0; byte_copy(sa->s,n,s); sa->len = n; sa->s[n] = 'Z'; /* ``offensive programming'' */ return 1; } netqmail-1.06/PIC.local2alias0000644000076400007640000000237006541176434015377 0ustar nelsonnelson Original message: To: help Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to help@heaven.af.mil | From: joe@heaven.af.mil | To: help@heaven.af.mil | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, help@heaven.af.mil. | Is heaven.af.mil in locals? Yes. | Deliver locally to help@heaven.af.mil. V qmail-lspawn ./Mailbox | Look at mailbox name, help. | Is help listed in qmail-users? No. | Is there a help account? No. | Give control of the message to alias. | Run qmail-local. V qmail-local alias ~alias help - help heaven.af.mil joe@heaven.af.mil ./Mailbox Does ~alias/.qmail-help exist? Yes: "john". Forward message to john. netqmail-1.06/sig_catch.c0000644000076400007640000000053506541176434014745 0ustar nelsonnelson#include #include "sig.h" #include "hassgact.h" void sig_catch(sig,f) int sig; void (*f)(); { #ifdef HASSIGACTION struct sigaction sa; sa.sa_handler = f; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(sig,&sa,(struct sigaction *) 0); #else signal(sig,f); /* won't work under System V, even nowadays---dorks */ #endif } netqmail-1.06/qmail-command.80000644000076400007640000000525406541176434015470 0ustar nelsonnelson.TH qmail-command 8 .SH NAME qmail-command \- user-specified mail delivery program .SH SYNOPSIS in .BR .qmail\fIext : .B |\fIcommand .SH DESCRIPTION .B qmail-local will, upon your request, feed each incoming mail message through a program of your choice. When a mail message arrives, .B qmail-local runs .B sh -c \fIcommand in your home directory. It makes the message available on .IR command 's standard input. .B WARNING: The mail message does not begin with .BR qmail-local 's usual .B Return-Path and .B Delivered-To lines. Note that .B qmail-local uses the same file descriptor for every delivery in your .B .qmail file, so it is not safe for .I command to fork a child that reads the message in the background while the parent exits. .SH "EXIT CODES" .IR command 's exit codes are interpreted as follows: 0 means that the delivery was successful; 99 means that the delivery was successful, but that .B qmail-local should ignore all further delivery instructions; 100 means that the delivery failed permanently (hard error); 111 means that the delivery failed but should be tried again in a little while (soft error). Currently 64, 65, 70, 76, 77, 78, and 112 are considered hard errors, and all other codes are considered soft errors, but .I command should avoid relying on this. .SH "ENVIRONMENT VARIABLES" .B qmail-local supplies several useful environment variables to .IR command . .B WARNING: These environment variables are not quoted. They may contain special characters. They are under the control of a possibly malicious remote user. .B SENDER is the envelope sender address. .B NEWSENDER is the forwarding envelope sender address, as described in .BR dot-qmail(5) . .B RECIPIENT is the envelope recipient address, .IR local@domain . .B USER is .IR user . .B HOME is your home directory, .IR homedir . .B HOST is the .I domain part of the recipient address. .B LOCAL is the .I local part. .B EXT is the address extension, .IR ext . .B HOST2 is the portion of .B HOST preceding the last dot; .B HOST3 is the portion of .B HOST preceding the second-to-last dot; .B HOST4 is the portion of .B HOST preceding the third-to-last dot. .B EXT2 is the portion of .B EXT following the first dash; .B EXT3 is the portion following the second dash; .B EXT4 is the portion following the third dash. .B DEFAULT is the portion corresponding to the .B default part of the .BR .qmail\- ... file name; .B DEFAULT is not set if the file name does not end with .BR default . .B DTLINE and .B RPLINE are the usual .B Delivered-To and .B Return-Path lines, including newlines. .B UFLINE is the UUCP-style .B From_ line that .B qmail-local adds to .IR mbox -format files. .SH "SEE ALSO" dot-qmail(5), envelopes(5), qmail-local(8) netqmail-1.06/datetime.h0000644000076400007640000000040106541176434014612 0ustar nelsonnelson#ifndef DATETIME_H #define DATETIME_H struct datetime { int hour; int min; int sec; int wday; int mday; int yday; int mon; int year; } ; typedef long datetime_sec; extern void datetime_tai(); extern datetime_sec datetime_untai(); #endif netqmail-1.06/stralloc_opys.c0000644000076400007640000000023006541176434015706 0ustar nelsonnelson#include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_copys(sa,s) stralloc *sa; char *s; { return stralloc_copyb(sa,s,str_len(s)); } netqmail-1.06/seek.h0000644000076400007640000000034306541176434013752 0ustar nelsonnelson#ifndef SEEK_H #define SEEK_H typedef unsigned long seek_pos; extern seek_pos seek_cur(); extern int seek_set(); extern int seek_end(); extern int seek_trunc(); #define seek_begin(fd) (seek_set((fd),(seek_pos) 0)) #endif netqmail-1.06/dnsfq.c0000644000076400007640000000116406541176434014133 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "stralloc.h" #include "dns.h" #include "dnsdoe.h" #include "ip.h" #include "ipalloc.h" #include "exit.h" stralloc sa = {0}; ipalloc ia = {0}; void main(argc,argv) int argc; char **argv; { if (!argv[1]) _exit(100); if (!stralloc_copys(&sa,argv[1])) { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); } dns_init(1); dnsdoe(dns_ip(&ia,&sa)); if (ia.len <= 0) { substdio_putsflush(subfderr,"no IP addresses\n"); _exit(100); } dnsdoe(dns_ptr(&sa,&ia.ix[0].ip)); substdio_putflush(subfdout,sa.s,sa.len); substdio_putsflush(subfdout,"\n"); _exit(0); } netqmail-1.06/timeoutwrite.c0000644000076400007640000000066506541176434015566 0ustar nelsonnelson#include "timeoutwrite.h" #include "select.h" #include "error.h" #include "readwrite.h" int timeoutwrite(t,fd,buf,len) int t; int fd; char *buf; int len; { fd_set wfds; struct timeval tv; tv.tv_sec = t; tv.tv_usec = 0; FD_ZERO(&wfds); FD_SET(fd,&wfds); if (select(fd + 1,(fd_set *) 0,&wfds,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(fd,&wfds)) return write(fd,buf,len); errno = error_timeout; return -1; } netqmail-1.06/readwrite.h0000644000076400007640000000013006541176434015003 0ustar nelsonnelson#ifndef READWRITE_H #define READWRITE_H extern int read(); extern int write(); #endif netqmail-1.06/headerbody.h0000644000076400007640000000011406541176434015125 0ustar nelsonnelson#ifndef HEADERBODY_H #define HEADERBODY_H extern int headerbody(); #endif netqmail-1.06/tryulong32.c0000644000076400007640000000052406541176434015047 0ustar nelsonnelsonvoid main() { unsigned long u; u = 1; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; u += u; if (!u) _exit(0); _exit(1); } netqmail-1.06/subfdouts.c0000644000076400007640000000030106541176434015026 0ustar nelsonnelson#include "readwrite.h" #include "substdio.h" #include "subfd.h" char subfd_outbufsmall[256]; static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbufsmall,256); substdio *subfdoutsmall = ⁢ netqmail-1.06/REMOVE.binmail0000644000076400007640000000105006541176434015200 0ustar nelsonnelsonHere's how to remove binmail from your system. Don't do this if you have configured qmail to use binmail for local delivery. 1. Find the binmail binary on your system: /usr/libexec/mail.local if that exists, otherwise /bin/mail. 2. Remove permissions from the binmail binary: # chmod 0 /usr/libexec/mail.local 3. If the binmail binary was /bin/mail, make sure that ``mail'' still invokes a usable mailer. Under SVR4 you may want to link mail to mailx. 4. Comment out the comsat line in /etc/inetd.conf, and kill -HUP your inetd. netqmail-1.06/control.c0000644000076400007640000000435006541176434014500 0ustar nelsonnelson#include "readwrite.h" #include "open.h" #include "getln.h" #include "stralloc.h" #include "substdio.h" #include "error.h" #include "control.h" #include "alloc.h" #include "scan.h" static char inbuf[64]; static stralloc line = {0}; static stralloc me = {0}; static int meok = 0; static void striptrailingwhitespace(sa) stralloc *sa; { while (sa->len > 0) switch(sa->s[sa->len - 1]) { case '\n': case ' ': case '\t': --sa->len; break; default: return; } } int control_init() { int r; r = control_readline(&me,"control/me"); if (r == 1) meok = 1; return r; } int control_rldef(sa,fn,flagme,def) stralloc *sa; char *fn; int flagme; char *def; { int r; r = control_readline(sa,fn); if (r) return r; if (flagme) if (meok) return stralloc_copy(sa,&me) ? 1 : -1; if (def) return stralloc_copys(sa,def) ? 1 : -1; return r; } int control_readline(sa,fn) stralloc *sa; char *fn; { substdio ss; int fd; int match; fd = open_read(fn); if (fd == -1) { if (errno == error_noent) return 0; return -1; } substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); if (getln(&ss,sa,&match,'\n') == -1) { close(fd); return -1; } striptrailingwhitespace(sa); close(fd); return 1; } int control_readint(i,fn) int *i; char *fn; { unsigned long u; switch(control_readline(&line,fn)) { case 0: return 0; case -1: return -1; } if (!stralloc_0(&line)) return -1; if (!scan_ulong(line.s,&u)) return 0; *i = u; return 1; } int control_readfile(sa,fn,flagme) stralloc *sa; char *fn; int flagme; { substdio ss; int fd; int match; if (!stralloc_copys(sa,"")) return -1; fd = open_read(fn); if (fd == -1) { if (errno == error_noent) { if (flagme && meok) { if (!stralloc_copy(sa,&me)) return -1; if (!stralloc_0(sa)) return -1; return 1; } return 0; } return -1; } substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); for (;;) { if (getln(&ss,&line,&match,'\n') == -1) break; if (!match && !line.len) { close(fd); return 1; } striptrailingwhitespace(&line); if (!stralloc_0(&line)) break; if (line.s[0]) if (line.s[0] != '#') if (!stralloc_cat(sa,&line)) break; if (!match) { close(fd); return 1; } } close(fd); return -1; } netqmail-1.06/bouncesaying.10000644000076400007640000000200406541176434015416 0ustar nelsonnelson.TH bouncesaying 1 .SH NAME bouncesaying \- perhaps bounce each incoming message .SH SYNOPSIS in .BR .qmail : .B |bouncesaying .I error [ .I program [ .I arg ... ] ] .SH DESCRIPTION .B bouncesaying feeds each new mail message to .I program with the given arguments. If .I program exits 0, .B bouncesaying prints .I error and bounces the message. If .I program exits 111, .B bouncesaying exits 111, so delivery will be retried later. If .I program exits anything else (or does not exist), .B bouncesaying exits 0, so the rest of .B .qmail will be processed as usual. Note that it is not safe for .I program to fork a child that reads the message in the background. If .I program is not supplied, .B bouncesaying always bounces the message: .EX |bouncesaying 'This address no longer accepts mail.' .EE .B WARNING: If you create a .B .qmail file to enable .BR bouncesaying , make sure to also add a line specifying delivery to your normal mailbox. .SH "SEE ALSO" condredirect(1), except(1), dot-qmail(5), qmail-command(8) netqmail-1.06/auto-str.c0000644000076400007640000000135206541176434014575 0ustar nelsonnelson#include "substdio.h" #include "readwrite.h" #include "exit.h" char buf1[256]; substdio ss1 = SUBSTDIO_FDBUF(write,1,buf1,sizeof(buf1)); void puts(s) char *s; { if (substdio_puts(&ss1,s) == -1) _exit(111); } void main(argc,argv) int argc; char **argv; { char *name; char *value; unsigned char ch; char octal[4]; name = argv[1]; if (!name) _exit(100); value = argv[2]; if (!value) _exit(100); puts("char "); puts(name); puts("[] = \"\\\n"); while (ch = *value++) { puts("\\"); octal[3] = 0; octal[2] = '0' + (ch & 7); ch >>= 3; octal[1] = '0' + (ch & 7); ch >>= 3; octal[0] = '0' + (ch & 7); puts(octal); } puts("\\\n\";\n"); if (substdio_flush(&ss1) == -1) _exit(111); _exit(0); } netqmail-1.06/wait_nohang.c0000644000076400007640000000034106541176434015312 0ustar nelsonnelson#include #include #include "haswaitp.h" int wait_nohang(wstat) int *wstat; { #ifdef HASWAITPID return waitpid(-1,wstat,WNOHANG); #else return wait3(wstat,WNOHANG,(struct rusage *) 0); #endif } netqmail-1.06/BLURB40000644000076400007640000000514406541176434013533 0ustar nelsonnelsonqmail's modular, lightweight design and sensible queue management make it the fastest available message transfer agent. Here's how it stacks up against the competition in five different speed measurements. * Scheduling: I sent a message to 8192 ``trash'' recipients on my home machine. All the deliveries were done in a mere 78 seconds---a rate of over 9 million deliveries a day! Compare this to the speed advertised for Zmailer's scheduling: 1.1 million deliveries a day on a SparcStation-10/50. (My home machine is a 16MB Pentium-100 under BSD/OS, with the default qmail configuration. qmail's logs were piped through accustamp and written to disk as usual.) * Local mailing lists: When qmail is delivering a message to a mailbox, it physically writes the message to disk before it announces success--- that way, mail doesn't get lost if the power goes out. I tried sending a message to 1024 local mailboxes on the same disk on my home machine; all the deliveries were done in 25.5 seconds. That's more than 3.4 million deliveries a day! Sending 1024 copies to a _single_ mailbox was just as fast. Compare these figures to Zmailer's advertised rate for throwing recipients away without even delivering the message---only 0.48 million per day on the SparcStation. * Mailing lists with remote recipients: qmail uses the same delivery strategy that makes LSOFT's LSMTP so fast for outgoing mailing lists--- you choose how many parallel SMTP connections you want to run, and qmail runs exactly that many. Of course, performance varies depending on how far away your recipients are. The advantage of qmail over other packages is its smallness: for example, one Linux user is running 60 simultaneous connections, without swapping, on a machine with just 16MB of memory! * Separate local messages: What LSOFT doesn't tell you about LSMTP is how many _separate_ messages it can handle in a day. Does it get bogged down as the queue fills up? On my home machine, I disabled qmail's deliveries and then sent 5000 separate messages to one recipient. The messages were all safely written to the queue disk in 23 minutes, with no slowdown as the queue filled up. After I reenabled deliveries, all the messages were delivered to the recipient's mailbox in under 12 minutes. End-to-end rate: more than 200000 individual messages a day! * Overall performance: What really matters is how well qmail performs with your mail load. Red Hat Software found one day that their mail hub, a 48MB Pentium running sendmail 8.7, was running out of steam at 70000 messages a day. They shifted the load to qmail---on a _smaller_ machine, a 16MB 486/66---and now they're doing fine. netqmail-1.06/THOUGHTS0000644000076400007640000004547306541176434014057 0ustar nelsonnelsonPlease note that this file is not called ``Internet Mail For Dummies.'' It _records_ my thoughts on various issues. It does not _explain_ them. Paragraphs are not organized except by section. The required background varies wildly from one paragraph to the next. In this file, ``sendmail'' means Allman's creation; ``sendmail-clone'' means the program in this package. 1. Security There are lots of interesting remote denial-of-service attacks on any mail system. A long-term solution is to insist on prepayment for unauthorized resource use. The tricky technical problem is to make the prepayment enforcement mechanism cheaper than the expected cost of the attacks. (For local denial-of-service attacks it's enough to be able to figure out which user is responsible.) qmail-send's log was originally designed for profiling. It subsequently sprouted some tracing features. However, there's no way to verify securely that a particular message came from a particular local user; how do you know the recipient is telling you the truth about the contents of the message? With QUEUE_EXTRA it'd be possible to record a one-way hash of each outgoing message, but a user who wants to send ``bad'' mail can avoid qmail entirely. I originally decided on security grounds not to put qmail advertisements into SMTP responses: advertisements often act as version identifiers. But this problem went away when I found a stable qmail URL. As qmail grows in popularity, the mere knowledge that rcpthosts is so easily available will deter people from setting up unauthorized MXs. (I've never seen an unauthorized MX, but I can imagine that it would be rather annoying.) Note that, unlike the bat book checkcompat() kludge, rcpthosts doesn't interfere with mailing lists. qmail-start doesn't bother with tty dissociation. On some old machines this means that random people can send tty signals to the qmail daemons. That's a security flaw in the job control subsystem, not in qmail. The resolver library isn't too bloated (before 4.9.4, at least), but it uses stdio, which _is_ bloated. Reading /etc/resolv.conf costs lots of memory in each qmail-remote process. So it's tempting to incorporate a smaller resolver library into qmail. (Bonus: I'd avoid system-specific problems with old resolvers.) The problem is that I'd then be writing a fundamentally insecure library. I'd no longer be able to blame the BIND authors and vendors for the fact that attackers can easily use DNS to steal mail. Solution: insist that the resolver run on the same host; the kernel can guarantee the security of low-numbered 127.0.0.1 UDP ports. NFS is the primary enemy of security partitioning under UNIX. Here's the story. Sun knew from the start that NFS was completely insecure. It tried to hide that fact by disallowing root access over NFS. Intruders nevertheless broke into system after system, first obtaining bin access and then obtaining root access. Various people thus decided to compound Sun's error and build a wall between root and all other users: if all system files are owned by root, and if there are no security holes other than NFS, someone who breaks in via NFS won't be able to wipe out the operating system---he'll merely be able to wipe out all user files. This clueless policy means that, for example, all the qmail users have to be replaced by root. See what I mean by ``enemy''? ... Basic NFS comments: Aside from the cryptographic problem of having hosts communicate securely, it's obvious that there's an administrative problem of mapping client uids to server uids. If a host is secure and under your control, you shouldn't have to map anything. If a host is under someone else's control, you'll want to map his uids to one local account; it's his client's job to decide which of his users get to talk NFS in the first place. Sun's original map---root to nobody, everyone else left alone--- is, as far as I can tell, always wrong. 2. Injecting mail locally (qmail-inject, sendmail-clone) RFC 822 section 3.4.9 prohibits certain visual effects in headers, and the 822bis draft prohibits even more. qmail-inject could enforce these absurd restrictions, but why waste the time? If you will suffer from someone sending you ``flash mail,'' go find a better mail reader. qmail-inject's ``Cc: recipient list not shown: ;'' successfully stops sendmail from adding Apparently-To. Unfortunately, old versions of sendmail will append a host name. This wasn't fixed until sendmail 8.7. How many years has it been since RFC 822 came out? sendmail discards duplicate addresses. This has probably resulted in more lost and stolen mail over the years than the entire Chicago branch of the United States Postal Service. The qmail system delivers messages exactly as it's told to do. Along the same lines: qmail-inject is both unable and unwilling to support anything like sendmail's (default) nometoo option. Of course, a list manager could support nometoo. There should be a mechanism in qmail-inject that does for envelope recipients what Return-Path does for the envelope sender. Then qmail-inject -n could print the recipients. Should qmail-inject bounce messages with no recipients? Should there be an option for this? If it stays as is (accept the message), qmail-inject could at least avoid invoking qmail-queue. It is possible to extract non-unique Message-IDs out of qmail-inject. Here's how: stop qmail-inject before it gets to the third line of main(), then wait until the pids wrap around, then restart qmail-inject and blast the message through, then start another qmail-inject with the same pid in the same second. I'm not sure how to fix this without system-supplied sequence numbers. (Of course, the user could just type in his own non-unique Message-IDs.) The bat book says: ``Rules that hide hosts in a domain should be applied only to sender addresses.'' Recipient masquerading works fine with qmail. None of sendmail's pitfalls apply, basically because qmail has a straight paper path. I predicted that I would receive some pressure to make up for the failings of MUA writers who don't understand the concept of reliability. (``Like, duh, you mean I'm supposed to check the sendmail exit code?'') I was right. 3. Receiving mail from the network (tcp-env, qmail-smtpd) qmail-smtpd doesn't allow privacy-invading commands like VRFY and EXPN. If you really want to publish such information, use a mechanism that legitimate users actually know about, such as fingerd or httpd. RFC 1123 says that VRFY and EXPN are important to track down cross-host mailing list loops. With Delivered-To, mailing list loops do no damage, _and_ one of the list administrators gets a bounce message that shows exactly how the loop occurred. Solve the problem, not the symptom. Should dns.c make special allowances for 127.0.0.1/localhost? badmailfrom (like 8BITMIME) is a waste of code space. In theory a MAIL or RCPT argument can contain unquoted LFs. In practice there are a huge number of clients that terminate commands with just LF, even if they use CR properly inside DATA. 4. Adding messages to the queue (qmail-queue) Should qmail-queue try to make sure enough disk space is free in advance? When qmail-queue is invoked by qmail-local or (with ESMTP) qmail-smtpd or qmail-qmtpd or qmail-qmqpd, it could be told a size in advance. I wish UNIX had an atomic allocate-disk-space routine... The qmail.h interface (reflecting the qmail-queue interface, which in turn reflects the current queue file structure) is constitutionally incapable of handling an address that contains a 0 byte. I can't imagine that this will be a problem. Should qmail-queue not bother queueing a message with no recipients? 5. Handling queued mail (qmail-send, qmail-clean) The queue directory must be local. Mounting it over NFS is extremely dangerous---not that this stops people from running sendmail that way! Diskless hosts should use mini-qmail instead. Queue reliability demands that single-byte writes be atomic. This is true for a fixed-block filesystem such as UFS, and for a logging filesystem such as LFS. qmail-send uses 8 bytes of memory per queued message. Double that for reallocation. (Fix: use a small forest of heaps; i.e., keep several prioqs.) Double again for buddy malloc()s. (Fix: be clever about the heap sizes.) 32 bytes is worrisome, but not devastating. Even on my disk-heavy memory-light machine, I'd run out of inodes long before running out of memory. Some mail systems organize the queue by host. This is pointless as a means of splitting up the queue directory. The real issue is what to do when you suddenly find out that a host is up. For local SLIP/PPP links you know in advance which hosts need this treatment, so you can handle them with virtualdomains and serialmail. For the old queue structure I implemented recipient list compression: if mail goes out to a giant mailing list, and most of the recipients are delivered, make a new, compressed, todo list. But this really isn't worth the effort: it saves only a tiny bit of CPU time. qmail-send doesn't have any notions of precedence, priority, fairness, importance, etc. It handles the queue in first-seen-first-served order. One could put a lot of work into doing something different, but that work would be a waste: given the triggering mechanism and qmail's deferral strategy, it is exceedingly rare for the queue to contain more than one deliverable message at any given moment. Exception: Even with all the concurrency tricks, qmail-send can end up spending a few minutes on a mailing list with thousands of remote entries. A user might send a new message to a remote address in the meantime. The simplest way to handle this would be to put big messages on a separate channel. qmail-send will never start a pass for a job that it already has. This means that, if one delivery takes longer than the retry interval, the next pass will be delayed. I implemented the opposite strategy for the old queue structure. Some hassles: mark() had to understand how job input was buffered; every new delivery had to check whether the same mpos in the same message was already being done. Some things that qmail-send does synchronously: queueing a bounce message; doing a cleanup via qmail-clean; classifying and rewriting all the addresses in a new message. As usual, making these asynchronous would require some housekeeping, but could speed things up a bit. (I'm willing to assume POSIX waitpid() for asynchronous bounces; putting an unbounded buffer into wait_pid() for the sake of NeXTSTEP 3 is not worthwhile.) Disk I/O is a bottleneck; UFS is reliable but it isn't fast. A good logging filesystem offers much better performance, but logging filesystems aren't widely available. Solution: Keep a journal, separate from the queue, adequate to rebuild the queue (with at worst some duplicate deliveries). Compress the journal. This would dramatically reduce total disk I/O. Bounce aggregation is a dubious feature. Bounce records aren't crashproof; there can be a huge delay between a failure and a bounce; the resulting bounce format is unnecessarily complicated. I'm tempted to scrap the bounce directory and send one bounce for each failing recipient, with appropriate modifications in the accompanying text. qmail-stop implementation: setuid to UID_SEND; kill -TERM -1. Or run qmail-start under an external service controller, such as supervise; that's why it runs in the foreground. The readdir() interface hides I/O errors. Lower-level interfaces would lead me into a thicket of portability problems. I'm really not sure what to do about this. Of course, a hard I/O error means that mail is toast, but a soft I/O error shouldn't cause any trouble. job_open() or pass_dochan() could be paranoid about the same id,channel already being open; but, since messdone() is so paranoid, the worst possible effect of a bug along these lines would be double delivery. Mathematical amusement: The optimal retry schedule is essentially, though not exactly, independent of the actual distribution of message delay times. What really matters is how much cost you assign to retries and to particular increases in latency. qmail's current quadratic retry schedule says that an hour-long delay in a day-old message is worth the same as a ten-minute delay in an hour-old message; this doesn't seem so unreasonable. Insider information: AOL retries their messages every five minutes for three days straight. Hmmm. 6. Sending mail through the network (qmail-rspawn, qmail-remote) Are there any hosts, anywhere, whose mailers are bogged down by huge messages to multiple recipients at a single host? For typical hosts, multiple RCPTs per SMTP aren't an ``efficiency feature''; they're a _slowness_ feature. Separate SMTP transactions have much lower latency. I've heard three complaints about bandwidth use from masochists sending messages through a modem through a smarthost to thousands of users--- without sublists! They can get much better performance with QMQP. In the opposite direction: It's tempting to remove the @host part of the qmail-remote recip argument. Or at least avoid double-dns_cname. There are lots of reasons that qmail-rspawn should take a more active role in qmail-remote's activities. It should call separate programs to do (1) MX lookups, (2) SMTP connections, (3) QMTP connections. (But this wouldn't be so important if the DNS library didn't burn so much memory.) I bounce ambiguous MXs. (An ``ambiguous MX'' is a best-preference MX record sending me mail for a host that I don't recognize as local.) Automatically treating ambiguous MXs as local is incompatible with my design decision to keep local delivery working when the network goes down. It puts more faith in DNS than DNS deserves. Much better: Have your MX records generated automatically from control/locals. If I successfully connect to an MX host but it temporarily refuses to accept the message, I give up and put the message back into the queue. But several documents seem to suggest that I should try further MX records. What are they thinking? My approach deals properly with downed hosts, hosts that are unreachable through a firewall, and load balancing; what else do people use multiple MX records for? Currently qmail-remote sends data in 1024-byte buffers. Perhaps it should try to take account of the MTU. Perhaps qmail-remote should allocate a fixed amount of DNS/connect() time across any number of MXs; this idea is due to Mark Delany. RFC 821 doesn't say what it means by ``text.'' qmail-remote assumes that the server's reply text doesn't contain bare LFs. RFC 821 and RFC 1123 prohibit host names in MAIL FROM and RCPT TO from being aliases. qmail-remote, like sendmail, rewrites aliases in RCPT; people who don't list aliases in control/locals or sendmail's Cw are implicitly relying on this conversion. It is course quite silly for an internal DNS detail to have such an effect on mail delivery, but that's how the Internet works. On the other hand, the compatibility arguments do not apply to MAIL FROM. qmail-remote no longer bothers with CNAME lookups for the envelope sender host. 7. Delivering mail locally (qmail-lspawn, qmail-local) qmail-local doesn't support comsat. comsat is a pointless abomination. Use qbiff if you want that kind of notification. The getpwnam() interface hides I/O errors. Solution: qmail-pw2u. 8. sendmail V8's new features sendmail-8.8.0/doc/op/op.me includes a list of big improvements of sendmail 8.8.0 over sendmail 5.67. Here's how qmail stacks up against each of those improvements. (Of course, qmail has its own improvements, but that's not the point of this list.) Connection caching, MX piggybacking: Nope. (Profile. Don't speculate.) Response to RCPT command is fast: Yup. IP addresses show up in Received lines: Yup. Self domain literal is properly handled: Yup. Different timeouts for QUIT, RCPT, etc.: No, just a single timeout. Proper <> handling, route-address pruning: Yes, but not configurable. ESMTP support: Yup. (Server-side, including PIPELINING.) 8-bit clean: Yup. (Including server-side 8BITMIME support; same as sendmail with the 8 option.) Configurable user database: Yup. BIND support: Yup. Keyed files: Yes, in fastforward. 931/1413/Ident/TAP: Yup. Correct 822 address list parsing: Yup. (Note that sendmail still has some major problems with quoting.) List-owner handling: Yup. Dynamic header allocation: Yup. Minimum number of disk blocks: Yes, via tunefs -m. (Or quotas; the right setup has qmailq with a small quota, qmails with a larger quota, so that qmail-send always has room to work.) Checkpointing: Yes, but not configurable---qmail always checkpoints. Error message configuration: Nope. GECOS matching: Not directly, but easy to hook in. Hop limit configuration: No. (qmail's limit is 100 hops. qmail offers automatic loop protection much more advanced than hop counting.) MIME error messages: No. (qmail uses QSBMF error messages, which are much easier to parse.) Forward file path: Yes, via /etc/passwd. Incoming SMTP configuration: Yes, via inetd or tcpserver. Privacy options: Yes, but they're not options. Best-MX mangling: Nope. See section 6 for further discussion. 7-bit mangling: Nope. qmail always uses 8 bits. Support for up to 20 MX records: Yes, and more. qmail has no limits other than memory. Correct quoting of name-and-address headers: Yup. VRFY and EXPN now different: Nope. qmail always hides this information. Multi-word classes, deferred macro expansion, separate envelope/header $g processing, separate per-mailer envelope and header processing, new command line flags, new configuration lines, new mailer flags, new macros: These are sendmail-specific; they wouldn't even make sense for qmail. For example, _of course_ qmail handles envelopes and headers separately; they're almost entirely different objects! 9. Miscellany sendmail-clone and qsmhook are too bletcherous to be documented. (The official replacement for qsmhook is preline, together with the qmail-command environment variables.) I've considered making install atomic, but this is very difficult to do right, and pointless if it isn't done right. RN suggests automatically putting together a reasonable set of lines for /etc/passwd. I perceive this as getting into the adduser business, which is worrisome: I'll be lynched the first time I screw up somebody's passwd file. This should be left to OS-specific installation scripts. The BSD 4.2 inetd didn't allow a username. I think I can safely forget about this. (DS notes that the username works under Ultrix even though it's undocumented.) I should clean up the bput/put choices. Some of the stralloc_0()s indicate that certain lower-level routines should grok stralloc. qmail assumes that all times are positive; that pid_t, time_t and ino_t fit into unsigned long; that gid_t fits into int; that the character set is ASCII; and that all pointers are interchangeable. Do I care? The bat book justifies sendmail's insane line-splitting mechanism by pointing out that it might be useful for ``a 40-character braille print-driving program.'' C'mon, guys, is that your best excuse? qmail's mascot is a dolphin. netqmail-1.06/sig_pause.c0000644000076400007640000000027106541176434014775 0ustar nelsonnelson#include #include "sig.h" #include "hassgprm.h" void sig_pause() { #ifdef HASSIGPROCMASK sigset_t ss; sigemptyset(&ss); sigsuspend(&ss); #else sigpause(0); #endif } netqmail-1.06/bouncesaying.c0000644000076400007640000000157706541176434015516 0ustar nelsonnelson#include "fork.h" #include "strerr.h" #include "error.h" #include "wait.h" #include "sig.h" #include "exit.h" #define FATAL "bouncesaying: fatal: " void main(argc,argv) int argc; char **argv; { int pid; int wstat; if (!argv[1]) strerr_die1x(100,"bouncesaying: usage: bouncesaying error [ program [ arg ... ] ]"); if (argv[2]) { pid = fork(); if (pid == -1) strerr_die2sys(111,FATAL,"unable to fork: "); if (pid == 0) { execvp(argv[2],argv + 2); if (error_temp(errno)) _exit(111); _exit(100); } if (wait_pid(&wstat,pid) == -1) strerr_die2x(111,FATAL,"wait failed"); if (wait_crashed(wstat)) strerr_die2x(111,FATAL,"child crashed"); switch(wait_exitcode(wstat)) { case 0: break; case 111: strerr_die2x(111,FATAL,"temporary child error"); default: _exit(0); } } strerr_die1x(100,argv[1]); } netqmail-1.06/ndelay.c0000644000076400007640000000032106541176434014266 0ustar nelsonnelson#include #include #include "ndelay.h" #ifndef O_NONBLOCK #define O_NONBLOCK O_NDELAY #endif int ndelay_on(fd) int fd; { return fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0) | O_NONBLOCK); } netqmail-1.06/open_excl.c0000644000076400007640000000021706541176434014772 0ustar nelsonnelson#include #include #include "open.h" int open_excl(fn) char *fn; { return open(fn,O_WRONLY | O_EXCL | O_CREAT,0644); } netqmail-1.06/except.10000644000076400007640000000057106541176434014227 0ustar nelsonnelson.TH except 1 .SH NAME except \- reverse the exit code of a program .SH SYNOPSIS .B except .I program [ .I arg ... ] .SH DESCRIPTION .B except runs .I program with the given arguments. If .I program exits 0, .B except exits 100. If .I program exits 111, .B except exits 111. If .I program exits anything else, .B except exits 0. .SH "SEE ALSO" bouncesaying(1), condredirect(1) netqmail-1.06/env.30000644000076400007640000000113006541176434013521 0ustar nelsonnelson.TH env 3 .SH NAME env \- manage the environment .SH SYNTAX .B #include char **\fBenviron\fP; char *\fBenv_get\fP(\fIname\fR); .br char *\fBenv_pick\fP(); char *\fIname\fR; .SH DESCRIPTION The environment, .BR environ , is a 0-terminated array of 0-terminated strings, called environment variables. Each environment variable is of the form .IR name\fB=\fIvalue . .B env_get returns the value of the first variable whose name is .IR name , or 0 if there is no such variable. .B env_pick returns any variable in the environment, or 0 if the environment is empty. .SH "SEE ALSO" environ(7) netqmail-1.06/scan_8long.c0000644000076400007640000000052606541176434015054 0ustar nelsonnelson#include "scan.h" unsigned int scan_8long(s,u) register char *s; register unsigned long *u; { register unsigned int pos; register unsigned long result; register unsigned long c; pos = 0; result = 0; while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 8) { result = result * 8 + c; ++pos; } *u = result; return pos; } netqmail-1.06/qmail-start.c0000644000076400007640000000524206541176434015257 0ustar nelsonnelson#include "fd.h" #include "prot.h" #include "exit.h" #include "fork.h" #include "auto_uids.h" char *(qsargs[]) = { "qmail-send", 0 }; char *(qcargs[]) = { "qmail-clean", 0 }; char *(qlargs[]) = { "qmail-lspawn", "./Mailbox", 0 }; char *(qrargs[]) = { "qmail-rspawn", 0 }; void die() { _exit(111); } int pi0[2]; int pi1[2]; int pi2[2]; int pi3[2]; int pi4[2]; int pi5[2]; int pi6[2]; void close23456() { close(2); close(3); close(4); close(5); close(6); } void closepipes() { close(pi1[0]); close(pi1[1]); close(pi2[0]); close(pi2[1]); close(pi3[0]); close(pi3[1]); close(pi4[0]); close(pi4[1]); close(pi5[0]); close(pi5[1]); close(pi6[0]); close(pi6[1]); } void main(argc,argv) int argc; char **argv; { if (chdir("/") == -1) die(); umask(077); if (prot_gid(auto_gidq) == -1) die(); if (fd_copy(2,0) == -1) die(); if (fd_copy(3,0) == -1) die(); if (fd_copy(4,0) == -1) die(); if (fd_copy(5,0) == -1) die(); if (fd_copy(6,0) == -1) die(); if (argv[1]) { qlargs[1] = argv[1]; ++argv; } if (argv[1]) { if (pipe(pi0) == -1) die(); switch(fork()) { case -1: die(); case 0: if (prot_gid(auto_gidn) == -1) die(); if (prot_uid(auto_uidl) == -1) die(); close(pi0[1]); if (fd_move(0,pi0[0]) == -1) die(); close23456(); execvp(argv[1],argv + 1); die(); } close(pi0[0]); if (fd_move(1,pi0[1]) == -1) die(); } if (pipe(pi1) == -1) die(); if (pipe(pi2) == -1) die(); if (pipe(pi3) == -1) die(); if (pipe(pi4) == -1) die(); if (pipe(pi5) == -1) die(); if (pipe(pi6) == -1) die(); switch(fork()) { case -1: die(); case 0: if (fd_copy(0,pi1[0]) == -1) die(); if (fd_copy(1,pi2[1]) == -1) die(); close23456(); closepipes(); execvp(*qlargs,qlargs); die(); } switch(fork()) { case -1: die(); case 0: if (prot_uid(auto_uidr) == -1) die(); if (fd_copy(0,pi3[0]) == -1) die(); if (fd_copy(1,pi4[1]) == -1) die(); close23456(); closepipes(); execvp(*qrargs,qrargs); die(); } switch(fork()) { case -1: die(); case 0: if (prot_uid(auto_uidq) == -1) die(); if (fd_copy(0,pi5[0]) == -1) die(); if (fd_copy(1,pi6[1]) == -1) die(); close23456(); closepipes(); execvp(*qcargs,qcargs); die(); } if (prot_uid(auto_uids) == -1) die(); if (fd_copy(0,1) == -1) die(); if (fd_copy(1,pi1[1]) == -1) die(); if (fd_copy(2,pi2[0]) == -1) die(); if (fd_copy(3,pi3[1]) == -1) die(); if (fd_copy(4,pi4[0]) == -1) die(); if (fd_copy(5,pi5[1]) == -1) die(); if (fd_copy(6,pi6[0]) == -1) die(); closepipes(); execvp(*qsargs,qsargs); die(); } netqmail-1.06/error.c0000644000076400007640000000157606541176434014160 0ustar nelsonnelson#include #include "error.h" /* warning: as coverage improves here, should update error_{str,temp} */ int error_intr = #ifdef EINTR EINTR; #else -1; #endif int error_nomem = #ifdef ENOMEM ENOMEM; #else -2; #endif int error_noent = #ifdef ENOENT ENOENT; #else -3; #endif int error_txtbsy = #ifdef ETXTBSY ETXTBSY; #else -4; #endif int error_io = #ifdef EIO EIO; #else -5; #endif int error_exist = #ifdef EEXIST EEXIST; #else -6; #endif int error_timeout = #ifdef ETIMEDOUT ETIMEDOUT; #else -7; #endif int error_inprogress = #ifdef EINPROGRESS EINPROGRESS; #else -8; #endif int error_wouldblock = #ifdef EWOULDBLOCK EWOULDBLOCK; #else -9; #endif int error_again = #ifdef EAGAIN EAGAIN; #else -10; #endif int error_pipe = #ifdef EPIPE EPIPE; #else -11; #endif int error_perm = #ifdef EPERM EPERM; #else -12; #endif int error_acces = #ifdef EACCES EACCES; #else -13; #endif netqmail-1.06/maildirwatch.c0000644000076400007640000000624006541176434015470 0ustar nelsonnelson#include "getln.h" #include "substdio.h" #include "subfd.h" #include "prioq.h" #include "stralloc.h" #include "str.h" #include "exit.h" #include "hfield.h" #include "readwrite.h" #include "open.h" #include "headerbody.h" #include "maildir.h" #define FATAL "maildirwatch: fatal: " void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); } stralloc recipient = {0}; stralloc sender = {0}; stralloc fromline = {0}; stralloc text = {0}; void addtext(s,n) char *s; int n; { if (!stralloc_catb(&text,s,n)) die_nomem(); if (text.len > 158) text.len = 158; } void dobody(h) stralloc *h; { addtext(h->s,h->len); } void doheader(h) stralloc *h; { int i; switch(hfield_known(h->s,h->len)) { case H_SUBJECT: i = hfield_skipname(h->s,h->len); addtext(h->s + i,h->len - i); break; case H_DELIVEREDTO: i = hfield_skipname(h->s,h->len); if (i < h->len) if (!stralloc_copyb(&recipient,h->s + i,h->len - i - 1)) die_nomem(); break; case H_RETURNPATH: i = hfield_skipname(h->s,h->len); if (i < h->len) if (!stralloc_copyb(&sender,h->s + i,h->len - i - 1)) die_nomem(); break; case H_FROM: if (!stralloc_copyb(&fromline,h->s,h->len - 1)) die_nomem(); break; } } void finishheader() { ; } stralloc filenames = {0}; prioq pq = {0}; char inbuf[SUBSTDIO_INSIZE]; substdio ssin; void main() { struct prioq_elt pe; int fd; int i; if (maildir_chdir() == -1) strerr_die1(111,FATAL,&maildir_chdir_err); for (;;) { maildir_clean(&filenames); if (maildir_scan(&pq,&filenames,1,0) == -1) strerr_die1(111,FATAL,&maildir_scan_err); substdio_putsflush(subfdout,"\033[;H\033[;J"); while (prioq_min(&pq,&pe)) { prioq_delmin(&pq); fd = open_read(filenames.s + pe.id); if (fd == -1) continue; substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); if (!stralloc_copys(&sender,"?")) die_nomem(); if (!stralloc_copys(&recipient,"?")) die_nomem(); if (!stralloc_copys(&fromline,"")) die_nomem(); if (!stralloc_copys(&text,"")) die_nomem(); if (headerbody(&ssin,doheader,finishheader,dobody) == -1) strerr_die2x(111,FATAL,"trouble reading new message"); for (i = 0;i < fromline.len;++i) if ((fromline.s[i] < 32) || (fromline.s[i] > 126)) fromline.s[i] = '/'; for (i = 0;i < sender.len;++i) if ((sender.s[i] < 32) || (sender.s[i] > 126)) sender.s[i] = '?'; for (i = 0;i < recipient.len;++i) if ((recipient.s[i] < 32) || (recipient.s[i] > 126)) recipient.s[i] = '?'; for (i = 0;i < text.len;++i) if ((text.s[i] < 32) || (text.s[i] > 126)) text.s[i] = '/'; substdio_puts(subfdout,"FROM "); substdio_put(subfdout,sender.s,sender.len); substdio_puts(subfdout," TO <"); substdio_put(subfdout,recipient.s,recipient.len); substdio_puts(subfdout,">\n"); if (fromline.len) { substdio_puts(subfdout,"\033[1m"); substdio_put(subfdout,fromline.s,fromline.len); substdio_puts(subfdout,"\033[0m\n"); } substdio_put(subfdout,text.s,text.len); substdio_puts(subfdout,"\n\n"); close(fd); } substdio_flush(subfdout); sleep(30); } } netqmail-1.06/hfield.c0000644000076400007640000000327106541176434014254 0ustar nelsonnelson#include "hfield.h" static char *(hname[]) = { "unknown-header" , "sender" , "from" , "reply-to" , "to" , "cc" , "bcc" , "date" , "message-id" , "subject" , "resent-sender" , "resent-from" , "resent-reply-to" , "resent-to" , "resent-cc" , "resent-bcc" , "resent-date" , "resent-message-id" , "return-receipt-to" , "errors-to" , "apparently-to" , "received" , "return-path" , "delivered-to" , "content-length" , "content-type" , "content-transfer-encoding" , "notice-requested-upon-delivery-to" , "mail-followup-to" , 0 }; static int hmatch(s,len,t) char *s; int len; char *t; { int i; char ch; for (i = 0;ch = t[i];++i) { if (i >= len) return 0; if (ch != s[i]) { if (ch == '-') return 0; if (ch - 32 != s[i]) return 0; } } for (;;) { if (i >= len) return 0; ch = s[i]; if (ch == ':') return 1; if ((ch != ' ') && (ch != '\t')) return 0; ++i; } } int hfield_known(s,len) char *s; int len; { int i; char *t; for (i = 1;t = hname[i];++i) if (hmatch(s,len,t)) return i; return 0; } int hfield_valid(s,len) char *s; int len; { int i; int j; char ch; for (j = 0;j < len;++j) if (s[j] == ':') break; if (j >= len) return 0; while (j) { ch = s[j - 1]; if ((ch != ' ') && (ch != '\t')) break; --j; } if (!j) return 0; for (i = 0;i < j;++i) { ch = s[i]; if (ch <= 32) return 0; if (ch >= 127) return 0; } return 1; } unsigned int hfield_skipname(s,len) char *s; int len; { int i; char ch; for (i = 0;i < len;++i) if (s[i] == ':') break; if (i < len) ++i; while (i < len) { ch = s[i]; if ((ch != '\t') && (ch != '\n') && (ch != '\r') && (ch != ' ')) break; ++i; } return i; } netqmail-1.06/qmail-qstat.sh0000644000076400007640000000045606541176434015450 0ustar nelsonnelsoncd QMAIL messdirs=`echo queue/mess/* | wc -w` messfiles=`find queue/mess/* -print | wc -w` tododirs=`echo queue/todo | wc -w` todofiles=`find queue/todo -print | wc -w` echo messages in queue: `expr $messfiles - $messdirs` echo messages in queue but not yet preprocessed: `expr $todofiles - $tododirs` netqmail-1.06/qmail-smtpd.80000644000076400007640000000673206541176434015203 0ustar nelsonnelson.TH qmail-smtpd 8 .SH NAME qmail-smtpd \- receive mail via SMTP .SH SYNOPSIS .B qmail-smtpd .SH DESCRIPTION .B qmail-smtpd receives mail messages via the Simple Mail Transfer Protocol (SMTP) and invokes .B qmail-queue to deposit them into the outgoing queue. .B qmail-smtpd must be supplied several environment variables; see .BR tcp-environ(5) . .B qmail-smtpd is responsible for counting hops. It rejects any message with 100 or more .B Received or .B Delivered-To header fields. .B qmail-smtpd supports ESMTP, including the 8BITMIME and PIPELINING options. .SH TRANSPARENCY .B qmail-smtpd converts the SMTP newline convention into the UNIX newline convention by converting CR LF into LF. It returns a temporary error and drops the connection on bare LFs; see .BR http://pobox.com/~djb/docs/smtplf.html . .B qmail-smtpd accepts messages that contain long lines or non-ASCII characters, even though such messages violate the SMTP protocol. .SH "CONTROL FILES" .TP 5 .I badmailfrom Unacceptable envelope sender addresses. .B qmail-smtpd will reject every recipient address for a message if the envelope sender address is listed in .IR badmailfrom . A line in .I badmailfrom may be of the form .BR @\fIhost , meaning every address at .IR host . .TP 5 .I databytes Maximum number of bytes allowed in a message, or 0 for no limit. Default: 0. If a message exceeds this limit, .B qmail-smtpd returns a permanent error code to the client; in contrast, if the disk is full or .B qmail-smtpd hits a resource limit, .B qmail-smtpd returns a temporary error code. .I databytes counts bytes as stored on disk, not as transmitted through the network. It does not count the .B qmail-smtpd Received line, the .B qmail-queue Received line, or the envelope. If the environment variable .B DATABYTES is set, it overrides .IR databytes . .TP 5 .I localiphost Replacement host name for local IP addresses. Default: .IR me , if that is supplied. .B qmail-smtpd is responsible for recognizing dotted-decimal addresses for the current host. When it sees a recipient address of the form .IR box@[d.d.d.d] , where .I d.d.d.d is a local IP address, it replaces .IR [d.d.d.d] with .IR localiphost . This is done before .IR rcpthosts . .TP 5 .I morercpthosts Extra allowed RCPT domains. If .I rcpthosts and .I morercpthosts both exist, .I morercpthosts is effectively appended to .IR rcpthosts . You must run .B qmail-newmrh whenever .I morercpthosts changes. Rule of thumb for large sites: Put your 50 most commonly used domains into .IR rcpthosts , and the rest into .IR morercpthosts . .TP 5 .I rcpthosts Allowed RCPT domains. If .I rcpthosts is supplied, .B qmail-smtpd will reject any envelope recipient address with a domain not listed in .IR rcpthosts . Exception: If the environment variable .B RELAYCLIENT is set, .B qmail-smtpd will ignore .IR rcpthosts , and will append the value of .B RELAYCLIENT to each incoming recipient address. .I rcpthosts may include wildcards: .EX heaven.af.mil .heaven.af.mil .EE Envelope recipient addresses without @ signs are always allowed through. .TP 5 .I smtpgreeting SMTP greeting message. Default: .IR me , if that is supplied; otherwise .B qmail-smtpd will refuse to run. The first word of .I smtpgreeting should be the current host's name. .TP 5 .I timeoutsmtpd Number of seconds .B qmail-smtpd will wait for each new buffer of data from the remote SMTP client. Default: 1200. .SH "SEE ALSO" tcp-env(1), tcp-environ(5), qmail-control(5), qmail-inject(8), qmail-newmrh(8), qmail-queue(8), qmail-remote(8) netqmail-1.06/COPYRIGHT0000644000076400007640000000235710724072214014141 0ustar nelsonnelsonnetqmail-1.04 ------------- No copyright is claimed by the distributors of netqmail for changes from qmail 1.03 to netqmail 1.04. NOTE: netqmail 1.04 is a community-assembled distribution of qmail from the official qmail-1.03.tar.gz and patches approved by the community. D. J. Bernstein did not participate in, nor has he been asked to approve of this distribution. netqmail-1.05 ------------- James Craig Burley claims copyright on the qmail-isoc patch. See the file old-patches/qmail-isoc.patch for details on James' copyright claim and distribution license. James' patch has been combined with the original netqmail-1.04 patch and the result incorporated into a unified netqmail-1.05 patch. Apart from James' copyrights, no other copyright is claimed by the distributors of netqmail for changes from qmail 1.03 to netqmail 1.05. NOTE: netqmail 1.05 is a community-assembled distribution of qmail from the official qmail-1.03.tar.gz and patches approved by the community. D. J. Bernstein did not participate in, nor has he been asked to approve of this distribution. netqmail-1.06 ------------- The same copyright information as netqmail-1.05 applies to netqmail-1.06 with the addition of D. J. Bernstein's dedication of qmail to the public domain. netqmail-1.06/INSTALL.maildir0000644000076400007640000000465306541176434015333 0ustar nelsonnelsonThis file points out some reasons that you might want to switch from mbox format to a new format, maildir. 1. The trouble with mbox The mbox format---the format of ~user/Mailbox, understood by BSD Mail and lots of other MUAs---is inherently unreliable. Think about it: what happens if the system crashes while a program is appending a new message to ~user/Mailbox? The message will be truncated. Even worse, if it was truncated in the middle of a line, it will end up being merged with the next message! Sure, the mailer understands that it wasn't successful, so it'll try delivering the message again later, but it can't fix your corrupted mbox. Other formats, such as mh folders, are just as unreliable. qmail supports maildir, a crashproof format for incoming mail messages. maildir is fast and easy for MUAs to use. Even better, maildir works wonders over NFS---see below. I don't want to cram maildir down people's throats, so it's not the default. Nevertheless, I encourage you to start asking for maildir versions of your favorite MUAs, and to switch over to maildir as soon as you can. 2. Sun's Network F_ail_u_re System Anyone who tells you that mail can be safely delivered in mbox format over NFS is pulling your leg---as explained above, mbox format is inherently unreliable even on a single machine. Anyway, NFS is the most unreliable computing environment ever invented, and qmail doesn't even pretend to support mbox over NFS. You should switch to maildir, which works fine over NFS without any locking. You can safely read your mail over NFS if it's in maildir format. Any number of machines can deliver mail to you at the same time. (On the other hand, for efficiency, it's better to get NFS out of the picture---your mail should be delivered on the server that contains your home directory.) Here's how to set up qmail to use maildir for your incoming mail: % maildirmake $HOME/Maildir % echo ./Maildir/ > ~/.qmail Make sure you include the trailing slash on Maildir/. The system administrator can set up Maildir as the default for everybody by creating a maildir in the new-user template directory and replacing ./Mailbox with ./Maildir/ in /var/qmail/rc. Until your MUA supports maildir, you'll probably want to convert maildir format to (gaaack) mbox format. I've supplied a maildir2mbox utility that does the trick, along with some tiny qail and elq and pinq wrappers that call maildir2mbox before calling Mail or elm or pine. netqmail-1.06/PIC.local2virt0000644000076400007640000000325506541176434015275 0ustar nelsonnelson Original message: To: dude@tommy.gov Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to dude@tommy.gov | From: joe@heaven.af.mil | To: dude@tommy.gov | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, dude@tommy.gov. | Is tommy.gov in locals? No. | Is dude@tommy.gov in virtualdomains? No. | Is tommy.gov in virtualdomains? Yes: "tommy.gov:fred". | Deliver locally to fred-dude@tommy.gov. V qmail-lspawn ./Mailbox | Look at mailbox name, fred-dude. | Is fred-dude listed in qmail-users? No. | Is there a fred-dude account? No. | Is there a fred account? Yes. | Is fred's uid nonzero? Yes. | Is ~fred visible to the qmailp user? Yes. | Is ~fred owned by fred? Yes. | Give control of the message to fred. | Run qmail-local. V qmail-local fred ~fred fred-dude - dude tommy.gov joe@heaven.af.mil ./Mailbox Does ~fred/.qmail-dude exist? No. Does ~fred/.qmail-default exist? Yes: "./Mail.tommy". Write message to ./Mail.tommy in mbox format. netqmail-1.06/qmail-qmqpd.80000644000076400007640000000105606541176434015170 0ustar nelsonnelson.TH qmail-qmqpd 8 .SH NAME qmail-qmqpd \- receive mail via QMQP .SH SYNOPSIS .B qmail-qmqpd .SH DESCRIPTION .B qmail-qmqpd receives mail messages via the Quick Mail Queueing Protocol (QMQP) and invokes .B qmail-queue to deposit them into the outgoing queue. .B qmail-qmqpd must be supplied several environment variables; see .BR tcp-environ(5) . .B qmail-qmqpd will relay messages to any destination. It should be invoked only for connections from preauthorized users. .SH "SEE ALSO" tcp-env(1), tcpserver(1), tcp-environ(5), qmail-qmqpc(8), qmail-queue(8) netqmail-1.06/condredirect.10000644000076400007640000000172206541176434015403 0ustar nelsonnelson.TH condredirect 1 .SH NAME condredirect \- perhaps redirect mail to another address .SH SYNOPSIS in .BR .qmail : .B |condredirect .I newaddress .I program [ .I arg ... ] .SH DESCRIPTION .B condredirect feeds each new mail message to .I program with the given arguments. If .I program exits 0, .B condredirect forwards the mail message to .IR newaddress , and then exits 99, so further commands in .B .qmail are ignored. If .I program exits 111, .B condredirect exits 111, so delivery will be retried later. If .I program exits anything else (or does not exist), .B condredirect exits 0, so the rest of .B .qmail will be processed as usual. Note that it is not safe for .I program to fork a child that reads the message in the background. .B WARNING: If you create a .B .qmail file to enable .BR condredirect , make sure to also add a line specifying delivery to your normal mailbox. .SH "SEE ALSO" bouncesaying(1), except(1), dot-qmail(5), qmail-command(8), qmail-queue(8) netqmail-1.06/qmail.70000644000076400007640000000245710724070436014046 0ustar nelsonnelson.TH qmail 7 .SH "NAME" qmail \- overview of qmail documentation .SH "INTRODUCTION" .B qmail is a secure, reliable, efficient, simple message transfer agent. Users who want to control incoming messages should read .BR dot-qmail (5). Available commands for the .B .qmail file include .BR qbiff (1), .BR qreceipt (1), .BR forward (1), .BR bouncesaying (1), and .BR condredirect (1). Other helpful commands include .BR maildirmake (1), .BR maildir2mbox (1), and .BR maildirwatch (1). System administrators who want to control the entire .B qmail system should start with .BR qmail-control (5) and .BR qmail-start (8). There are three queue-monitoring tools: .BR qmail-qread (8), .BR qmail-qstat (8), and .BR qmail-tcpto (8). Incoming SMTP connections are handled by .BR qmail-smtpd (8). .B qmail offers two command-line message-sending interfaces: .BR qmail-inject (8) and .BR mailsubj (1). For background information on Internet mail messages, see .BR addresses (5), .BR envelopes (5), .BR qmail-header (5), and .BR forgeries (7). Miscellaneous documentation includes .BR qmail-limits (7) and .BR qmail-pop3d (8). This documentation describes netqmail version 1.05 of .BR qmail . See .B http://pobox.com/~djb/qmail.html for other .BR qmail -related software, and .B http://qmail.org/ for other qmail community contributions. netqmail-1.06/dnsdoe.h0000644000076400007640000000010106541176434014267 0ustar nelsonnelson#ifndef DNSDOE_H #define DNSDOE_H extern void dnsdoe(); #endif netqmail-1.06/fmt_uint0.c0000644000076400007640000000034406541176434014724 0ustar nelsonnelson#include "fmt.h" unsigned int fmt_uint0(s,u,n) char *s; unsigned int u; unsigned int n; { unsigned int len; len = fmt_uint(FMT_LEN,u); while (len < n) { if (s) *s++ = '0'; ++len; } if (s) fmt_uint(s,u); return len; } netqmail-1.06/qmail-queue.80000644000076400007640000000621310724070436015163 0ustar nelsonnelson.TH qmail-queue 8 .SH NAME qmail-queue \- queue a mail message for delivery .SH SYNOPSIS .B qmail-queue .SH DESCRIPTION .B qmail-queue reads a mail message from descriptor 0. It then reads envelope information from descriptor 1. It places the message into the outgoing queue for future delivery by .BR qmail-send . The envelope information is an envelope sender address followed by a list of envelope recipient addresses. The sender address is preceded by the letter F and terminated by a 0 byte. Each recipient address is preceded by the letter T and terminated by a 0 byte. The list of recipient addresses is terminated by an extra 0 byte. If .B qmail-queue sees end-of-file before the extra 0 byte, it aborts without placing the message into the queue. Every envelope recipient address should contain a username, an @ sign, and a fully qualified domain name. .B qmail-queue always adds a .B Received line to the top of the message. Other than this, .B qmail-queue does not inspect the message and does not enforce any restrictions on its contents. However, the recipients probably expect to see a proper header, as described in .BR qmail-header(5) . Programs included with qmail which invoke .B qmail-queue will invoke the contents of .B $QMAILQUEUE instead, if that environment variable is set. .SH "FILESYSTEM RESTRICTIONS" .B qmail-queue imposes two constraints on the queue structure: each .B mess subdirectory must be in the same filesystem as the .B pid directory; and each .B todo subdirectory must be in the same filesystem as the .B intd directory. .SH "EXIT CODES" .B qmail-queue does not print diagnostics. It exits 0 if it has successfully queued the message. It exits between 1 and 99 if it has failed to queue the message. All .B qmail-queue error codes between 11 and 40 indicate permanent errors: .TP 5 .B 11 Address too long. .TP .B 31 Mail server permanently refuses to send the message to any recipients. (Not used by .BR qmail-queue , but can be used by programs offering the same interface.) .PP All other .B qmail-queue error codes indicate temporary errors: .TP 5 .B 51 Out of memory. .TP .B 52 Timeout. .TP .B 53 Write error; e.g., disk full. .TP .B 54 Unable to read the message or envelope. .TP .B 55 Unable to read a configuration file. (Not used by .BR qmail-queue .) .TP .B 56 Problem making a network connection from this host. (Not used by .BR qmail-queue .) .TP .B 61 Problem with the qmail home directory. .TP .B 62 Problem with the queue directory. .TP .B 63 Problem with queue/pid. .TP .B 64 Problem with queue/mess. .TP .B 65 Problem with queue/intd. .TP .B 66 Problem with queue/todo. .TP .B 71 Mail server temporarily refuses to send the message to any recipients. (Not used by .BR qmail-queue .) .TP .B 72 Connection to mail server timed out. (Not used by .BR qmail-queue .) .TP .B 73 Connection to mail server rejected. (Not used by .BR qmail-queue .) .TP .B 74 Connection to mail server succeeded, but communication failed. (Not used by .BR qmail-queue .) .TP .B 81 Internal bug; e.g., segmentation fault. .TP .B 91 Envelope format error. .SH "SEE ALSO" addresses(5), envelopes(5), qmail-header(5), qmail-inject(8), qmail-qmqpc(8), qmail-send(8), qmail-smtpd(8) netqmail-1.06/tcp-env.10000644000076400007640000000205006541176434014305 0ustar nelsonnelson.TH tcp-env 1 .SH NAME tcp-env \- set up TCP-related environment variables .SH SYNOPSIS .B tcp-env [ .B \-rR ] [ .B \-t\fItimeout ] .I program [ .I arg ... ] .SH DESCRIPTION The input for .B tcp-env must be a TCP connection. .B tcp-env finds out information about that connection, puts the information into several environment variables as described in .B tcp-environ(5), and runs .I program with the given arguments. Usually .B tcp-env is run from .BR inetd . It might instead be run from another server that already sets up the right environment variables; if .B PROTO is set to .B TCP when .B tcp-env is invoked, .B tcp-env assumes that all the other variables are set up properly, and it does not check whether the input is a TCP connection. .SH OPTIONS .TP .B \-r (Default.) Attempt to obtain .B TCPREMOTEINFO from the remote host. .TP .B \-R Do not attempt to obtain .B TCPREMOTEINFO from the remote host. .TP .B \-t\fItimeout Give up on the .B TCPREMOTEINFO connection attempt after .I timeout seconds. Default: 30. .SH "SEE ALSO" tcp-environ(5), inetd(8) netqmail-1.06/qmail-newu.c0000644000076400007640000000626206541176434015103 0ustar nelsonnelson#include "stralloc.h" #include "subfd.h" #include "getln.h" #include "substdio.h" #include "cdbmss.h" #include "exit.h" #include "readwrite.h" #include "open.h" #include "error.h" #include "case.h" #include "auto_qmail.h" void die_temp() { _exit(111); } void die_chdir() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to chdir\n"); die_temp(); } void die_nomem() { substdio_putsflush(subfderr,"qmail-newu: fatal: out of memory\n"); die_temp(); } void die_opena() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to open users/assign\n"); die_temp(); } void die_reada() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to read users/assign\n"); die_temp(); } void die_format() { substdio_putsflush(subfderr,"qmail-newu: fatal: bad format in users/assign\n"); die_temp(); } void die_opent() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to open users/cdb.tmp\n"); die_temp(); } void die_writet() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to write users/cdb.tmp\n"); die_temp(); } void die_rename() { substdio_putsflush(subfderr,"qmail-newu: fatal: unable to move users/cdb.tmp to users/cdb\n"); die_temp(); } struct cdbmss cdbmss; stralloc key = {0}; stralloc data = {0}; char inbuf[1024]; substdio ssin; int fd; int fdtemp; stralloc line = {0}; int match; stralloc wildchars = {0}; void main() { int i; int numcolons; umask(033); if (chdir(auto_qmail) == -1) die_chdir(); fd = open_read("users/assign"); if (fd == -1) die_opena(); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof(inbuf)); fdtemp = open_trunc("users/cdb.tmp"); if (fdtemp == -1) die_opent(); if (cdbmss_start(&cdbmss,fdtemp) == -1) die_writet(); if (!stralloc_copys(&wildchars,"")) die_nomem(); for (;;) { if (getln(&ssin,&line,&match,'\n') != 0) die_reada(); if (line.len && (line.s[0] == '.')) break; if (!match) die_format(); if (byte_chr(line.s,line.len,'\0') < line.len) die_format(); i = byte_chr(line.s,line.len,':'); if (i == line.len) die_format(); if (i == 0) die_format(); if (!stralloc_copys(&key,"!")) die_nomem(); if (line.s[0] == '+') { if (!stralloc_catb(&key,line.s + 1,i - 1)) die_nomem(); case_lowerb(key.s,key.len); if (i >= 2) if (byte_chr(wildchars.s,wildchars.len,line.s[i - 1]) == wildchars.len) if (!stralloc_append(&wildchars,line.s + i - 1)) die_nomem(); } else { if (!stralloc_catb(&key,line.s + 1,i - 1)) die_nomem(); if (!stralloc_0(&key)) die_nomem(); case_lowerb(key.s,key.len); } if (!stralloc_copyb(&data,line.s + i + 1,line.len - i - 1)) die_nomem(); numcolons = 0; for (i = 0;i < data.len;++i) if (data.s[i] == ':') { data.s[i] = 0; if (++numcolons == 6) break; } if (numcolons < 6) die_format(); data.len = i; if (cdbmss_add(&cdbmss,key.s,key.len,data.s,data.len) == -1) die_writet(); } if (cdbmss_add(&cdbmss,"",0,wildchars.s,wildchars.len) == -1) die_writet(); if (cdbmss_finish(&cdbmss) == -1) die_writet(); if (fsync(fdtemp) == -1) die_writet(); if (close(fdtemp) == -1) die_writet(); /* NFS stupidity */ if (rename("users/cdb.tmp","users/cdb") == -1) die_rename(); _exit(0); } netqmail-1.06/proc.sh0000644000076400007640000000033206541176434014147 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using procmail to deliver messages to /var/spool/mail/$USER by default. exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|preline procmail' splogger qmail netqmail-1.06/forward.10000644000076400007640000000075706541176434014411 0ustar nelsonnelson.TH forward 1 .SH NAME forward \- forward new mail to one or more addresses .SH SYNOPSIS in .BR .qmail : .B |forward .I address ... .SH DESCRIPTION .B forward forwards each new mail message to the specified list of addresses. It is a simple wrapper around .BR qmail-queue . It achieves the same results as listing each .I address separately in .BR .qmail , but it is more programmable since .I address can be constructed on the fly. .SH "SEE ALSO" dot-qmail(5), qmail-command(8), qmail-queue(8) netqmail-1.06/trysgprm.c0000644000076400007640000000022306541176434014702 0ustar nelsonnelson#include void main() { sigset_t ss; sigemptyset(&ss); sigaddset(&ss,SIGCHLD); sigprocmask(SIG_SETMASK,&ss,(sigset_t *) 0); } netqmail-1.06/ipalloc.c0000644000076400007640000000037406541176434014445 0ustar nelsonnelson#include "alloc.h" #include "gen_allocdefs.h" #include "ip.h" #include "ipalloc.h" GEN_ALLOC_readyplus(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus) GEN_ALLOC_append(ipalloc,struct ip_mx,ix,len,a,i,n,x,10,ipalloc_readyplus,ipalloc_append) netqmail-1.06/case_lowers.c0000644000076400007640000000023306541176434015322 0ustar nelsonnelson#include "case.h" void case_lowers(s) char *s; { unsigned char x; while (x = *s) { x -= 'A'; if (x <= 'Z' - 'A') *s = x + 'a'; ++s; } } netqmail-1.06/make-compile.sh0000644000076400007640000000003706541176434015551 0ustar nelsonnelsonecho exec "$CC" -c '${1+"$@"}' netqmail-1.06/qsutil.h0000644000076400007640000000030006541176434014335 0ustar nelsonnelson#ifndef QSUTIL_H #define QSUTIL_H extern void log1(); extern void log2(); extern void log3(); extern void logsa(); extern void nomem(); extern void pausedir(); extern void logsafe(); #endif netqmail-1.06/BLURB30000644000076400007640000000740006541176434013527 0ustar nelsonnelsonHere are some of qmail's features. Setup: * automatic adaptation to your UNIX variant---no configuration needed * AIX, BSD/OS, FreeBSD, HP/UX, Irix, Linux, OSF/1, SunOS, Solaris, and more * automatic per-host configuration (config, config-fast) * quick installation---no big list of decisions to make Security: * clear separation between addresses, files, and programs * minimization of setuid code (qmail-queue) * minimization of root code (qmail-start, qmail-lspawn) * five-way trust partitioning---security in depth * optional logging of one-way hashes, entire contents, etc. (QUEUE_EXTRA) Message construction (qmail-inject): * RFC 822, RFC 1123 * full support for address groups * automatic conversion of old-style address lists to RFC 822 format * sendmail hook for compatibility with current user agents * header line length limited only by memory * host masquerading (control/defaulthost) * user masquerading ($MAILUSER, $MAILHOST) * automatic Mail-Followup-To creation ($QMAILMFTFILE) SMTP service (qmail-smtpd): * RFC 821, RFC 1123, RFC 1651, RFC 1652, RFC 1854 * 8-bit clean * 931/1413/ident/TAP callback (tcp-env) * relay control---stop unauthorized relaying by outsiders (control/rcpthosts) * no interference between relay control and forwarding * tcpd hook---reject SMTP connections from known abusers * automatic recognition of local IP addresses * per-buffer timeouts * hop counting Queue management (qmail-send): * instant handling of messages added to queue * parallelism limit (control/concurrencyremote, control/concurrencylocal) * split queue directory---no slowdown when queue gets big * quadratic retry schedule---old messages tried less often * independent message retry schedules * automatic safe queueing---no loss of mail if system crashes * automatic per-recipient checkpointing * automatic queue cleanups (qmail-clean) * queue viewing (qmail-qread) * detailed delivery statistics (qmailanalog, available separately) Bounces (qmail-send): * QSBMF bounce messages---both machine-readable and human-readable * HCMSSC support---language-independent RFC 1893 error codes * double bounces sent to postmaster Routing by domain (qmail-send): * any number of names for local host (control/locals) * any number of virtual domains (control/virtualdomains) * domain wildcards (control/virtualdomains) * configurable percent hack support (control/percenthack) * UUCP hook SMTP delivery (qmail-remote): * RFC 821, RFC 974, RFC 1123 * 8-bit clean * automatic downed host backoffs * artificial routing---smarthost, localnet, mailertable (control/smtproutes) * per-buffer timeouts * passive SMTP queue---perfect for SLIP/PPP (serialmail, available separately) Forwarding and mailing lists (qmail-local): * address wildcards (.qmail-default, .qmail-foo-default, etc.) * sendmail .forward compatibility (dot-forward, available separately) * fast forwarding databases (fastforward, available separately) * sendmail /etc/aliases compatibility (fastforward/newaliases) * mailing list owners---automatically divert bounces and vacation messages * VERPs---automatic recipient identification for mailing list bounces * Delivered-To---automatic loop prevention, even across hosts * automatic mailing list management (ezmlm, available separately) Local delivery (qmail-local): * user-controlled address hierarchy---fred controls fred-anything * mbox delivery * reliable NFS delivery (maildir) * user-controlled program delivery: procmail etc. (qmail-command) * optional new-mail notification (qbiff) * optional NRUDT return receipts (qreceipt) * conditional filtering (condredirect, bouncesaying) POP3 service (qmail-popup, qmail-pop3d): * RFC 1939 * UIDL support * TOP support * APOP hook * modular password checking (checkpassword, available separately) netqmail-1.06/direntry.h20000644000076400007640000000017106541176434014744 0ustar nelsonnelson#ifndef DIRENTRY_H #define DIRENTRY_H #include #include #define direntry struct dirent #endif netqmail-1.06/qmail-showctl.c0000644000076400007640000002434506541176434015612 0ustar nelsonnelson#include #include #include "substdio.h" #include "subfd.h" #include "exit.h" #include "fmt.h" #include "str.h" #include "control.h" #include "constmap.h" #include "stralloc.h" #include "direntry.h" #include "auto_uids.h" #include "auto_qmail.h" #include "auto_break.h" #include "auto_patrn.h" #include "auto_spawn.h" #include "auto_split.h" stralloc me = {0}; int meok; stralloc line = {0}; char num[FMT_ULONG]; void safeput(buf,len) char *buf; unsigned int len; { char ch; while (len > 0) { ch = *buf; if ((ch < 32) || (ch > 126)) ch = '?'; substdio_put(subfdout,&ch,1); ++buf; --len; } } void do_int(fn,def,pre,post) char *fn; char *def; char *pre; char *post; { int i; substdio_puts(subfdout,"\n"); substdio_puts(subfdout,fn); substdio_puts(subfdout,": "); switch(control_readint(&i,fn)) { case 0: substdio_puts(subfdout,"(Default.) "); substdio_puts(subfdout,pre); substdio_puts(subfdout,def); substdio_puts(subfdout,post); substdio_puts(subfdout,".\n"); break; case 1: if (i < 0) i = 0; substdio_puts(subfdout,pre); substdio_put(subfdout,num,fmt_uint(num,i)); substdio_puts(subfdout,post); substdio_puts(subfdout,".\n"); break; default: substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); break; } } void do_str(fn,flagme,def,pre) char *fn; int flagme; char *def; char *pre; { substdio_puts(subfdout,"\n"); substdio_puts(subfdout,fn); substdio_puts(subfdout,": "); switch(control_readline(&line,fn)) { case 0: substdio_puts(subfdout,"(Default.) "); if (!stralloc_copys(&line,def)) { substdio_puts(subfdout,"Oops! Out of memory.\n"); break; } if (flagme && meok) if (!stralloc_copy(&line,&me)) { substdio_puts(subfdout,"Oops! Out of memory.\n"); break; } case 1: substdio_puts(subfdout,pre); safeput(line.s,line.len); substdio_puts(subfdout,".\n"); break; default: substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); break; } } int do_lst(fn,def,pre,post) char *fn; char *def; char *pre; char *post; { int i; int j; substdio_puts(subfdout,"\n"); substdio_puts(subfdout,fn); substdio_puts(subfdout,": "); switch(control_readfile(&line,fn)) { case 0: substdio_puts(subfdout,"(Default.) "); substdio_puts(subfdout,def); substdio_puts(subfdout,"\n"); return 0; case 1: substdio_puts(subfdout,"\n"); i = 0; for (j = 0;j < line.len;++j) if (!line.s[j]) { substdio_puts(subfdout,pre); safeput(line.s + i,j - i); substdio_puts(subfdout,post); substdio_puts(subfdout,"\n"); i = j + 1; } return 1; default: substdio_puts(subfdout,"Oops! Trouble reading this file.\n"); return -1; } } void main() { DIR *dir; direntry *d; struct stat stmrh; struct stat stmrhcdb; substdio_puts(subfdout,"qmail home directory: "); substdio_puts(subfdout,auto_qmail); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"user-ext delimiter: "); substdio_puts(subfdout,auto_break); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"paternalism (in decimal): "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_patrn)); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"silent concurrency limit: "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_spawn)); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"subdirectory split: "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_split)); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"user ids: "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uida)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidd)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidl)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uido)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidp)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidq)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uidr)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_uids)); substdio_puts(subfdout,".\n"); substdio_puts(subfdout,"group ids: "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidn)); substdio_puts(subfdout,", "); substdio_put(subfdout,num,fmt_ulong(num,(unsigned long) auto_gidq)); substdio_puts(subfdout,".\n"); if (chdir(auto_qmail) == -1) { substdio_puts(subfdout,"Oops! Unable to chdir to "); substdio_puts(subfdout,auto_qmail); substdio_puts(subfdout,".\n"); substdio_flush(subfdout); _exit(111); } if (chdir("control") == -1) { substdio_puts(subfdout,"Oops! Unable to chdir to control.\n"); substdio_flush(subfdout); _exit(111); } dir = opendir("."); if (!dir) { substdio_puts(subfdout,"Oops! Unable to open current directory.\n"); substdio_flush(subfdout); _exit(111); } meok = control_readline(&me,"me"); if (meok == -1) { substdio_puts(subfdout,"Oops! Trouble reading control/me."); substdio_flush(subfdout); _exit(111); } do_lst("badmailfrom","Any MAIL FROM is allowed.",""," not accepted in MAIL FROM."); do_str("bouncefrom",0,"MAILER-DAEMON","Bounce user name is "); do_str("bouncehost",1,"bouncehost","Bounce host name is "); do_int("concurrencylocal","10","Local concurrency is ",""); do_int("concurrencyremote","20","Remote concurrency is ",""); do_int("databytes","0","SMTP DATA limit is "," bytes"); do_str("defaultdomain",1,"defaultdomain","Default domain name is "); do_str("defaulthost",1,"defaulthost","Default host name is "); do_str("doublebouncehost",1,"doublebouncehost","2B recipient host: "); do_str("doublebounceto",0,"postmaster","2B recipient user: "); do_str("envnoathost",1,"envnoathost","Presumed domain name is "); do_str("helohost",1,"helohost","SMTP client HELO host name is "); do_str("idhost",1,"idhost","Message-ID host name is "); do_str("localiphost",1,"localiphost","Local IP address becomes "); do_lst("locals","Messages for me are delivered locally.","Messages for "," are delivered locally."); do_str("me",0,"undefined! Uh-oh","My name is "); do_lst("percenthack","The percent hack is not allowed.","The percent hack is allowed for user%host@","."); do_str("plusdomain",1,"plusdomain","Plus domain name is "); do_lst("qmqpservers","No QMQP servers.","QMQP server: ","."); do_int("queuelifetime","604800","Message lifetime in the queue is "," seconds"); if (do_lst("rcpthosts","SMTP clients may send messages to any recipient.","SMTP clients may send messages to recipients at ",".")) do_lst("morercpthosts","No effect.","SMTP clients may send messages to recipients at ","."); else do_lst("morercpthosts","No rcpthosts; morercpthosts is irrelevant.","No rcpthosts; doesn't matter that morercpthosts has ","."); /* XXX: check morercpthosts.cdb contents */ substdio_puts(subfdout,"\nmorercpthosts.cdb: "); if (stat("morercpthosts",&stmrh) == -1) if (stat("morercpthosts.cdb",&stmrhcdb) == -1) substdio_puts(subfdout,"(Default.) No effect.\n"); else substdio_puts(subfdout,"Oops! morercpthosts.cdb exists but morercpthosts doesn't.\n"); else if (stat("morercpthosts.cdb",&stmrhcdb) == -1) substdio_puts(subfdout,"Oops! morercpthosts exists but morercpthosts.cdb doesn't.\n"); else if (stmrh.st_mtime > stmrhcdb.st_mtime) substdio_puts(subfdout,"Oops! morercpthosts.cdb is older than morercpthosts.\n"); else substdio_puts(subfdout,"Modified recently enough; hopefully up to date.\n"); do_str("smtpgreeting",1,"smtpgreeting","SMTP greeting: 220 "); do_lst("smtproutes","No artificial SMTP routes.","SMTP route: ",""); do_int("timeoutconnect","60","SMTP client connection timeout is "," seconds"); do_int("timeoutremote","1200","SMTP client data timeout is "," seconds"); do_int("timeoutsmtpd","1200","SMTP server data timeout is "," seconds"); do_lst("virtualdomains","No virtual domains.","Virtual domain: ",""); while (d = readdir(dir)) { if (str_equal(d->d_name,".")) continue; if (str_equal(d->d_name,"..")) continue; if (str_equal(d->d_name,"bouncefrom")) continue; if (str_equal(d->d_name,"bouncehost")) continue; if (str_equal(d->d_name,"badmailfrom")) continue; if (str_equal(d->d_name,"bouncefrom")) continue; if (str_equal(d->d_name,"bouncehost")) continue; if (str_equal(d->d_name,"concurrencylocal")) continue; if (str_equal(d->d_name,"concurrencyremote")) continue; if (str_equal(d->d_name,"databytes")) continue; if (str_equal(d->d_name,"defaultdomain")) continue; if (str_equal(d->d_name,"defaulthost")) continue; if (str_equal(d->d_name,"doublebouncehost")) continue; if (str_equal(d->d_name,"doublebounceto")) continue; if (str_equal(d->d_name,"envnoathost")) continue; if (str_equal(d->d_name,"helohost")) continue; if (str_equal(d->d_name,"idhost")) continue; if (str_equal(d->d_name,"localiphost")) continue; if (str_equal(d->d_name,"locals")) continue; if (str_equal(d->d_name,"me")) continue; if (str_equal(d->d_name,"morercpthosts")) continue; if (str_equal(d->d_name,"morercpthosts.cdb")) continue; if (str_equal(d->d_name,"percenthack")) continue; if (str_equal(d->d_name,"plusdomain")) continue; if (str_equal(d->d_name,"qmqpservers")) continue; if (str_equal(d->d_name,"queuelifetime")) continue; if (str_equal(d->d_name,"rcpthosts")) continue; if (str_equal(d->d_name,"smtpgreeting")) continue; if (str_equal(d->d_name,"smtproutes")) continue; if (str_equal(d->d_name,"timeoutconnect")) continue; if (str_equal(d->d_name,"timeoutremote")) continue; if (str_equal(d->d_name,"timeoutsmtpd")) continue; if (str_equal(d->d_name,"virtualdomains")) continue; substdio_puts(subfdout,"\n"); substdio_puts(subfdout,d->d_name); substdio_puts(subfdout,": I have no idea what this file does.\n"); } substdio_flush(subfdout); _exit(0); } netqmail-1.06/qmail-rspawn.80000644000076400007640000000070106541176434015354 0ustar nelsonnelson.TH qmail-rspawn 8 .SH NAME qmail-rspawn \- schedule remote deliveries .SH SYNOPSIS .B qmail-rspawn .SH DESCRIPTION .B qmail-rspawn reads a series of remote delivery commands from descriptor 0, invokes .B qmail-remote to perform the deliveries, and prints the results to descriptor 1. .B qmail-rspawn invokes .B qmail-remote asynchronously, so the results may not be in the same order as the commands. .SH "SEE ALSO" qmail-send(8), qmail-remote(8) netqmail-1.06/control.h0000644000076400007640000000030006541176434014474 0ustar nelsonnelson#ifndef CONTROL_H #define CONTROL_H extern int control_init(); extern int control_readline(); extern int control_rldef(); extern int control_readint(); extern int control_readfile(); #endif netqmail-1.06/gen_allocdefs.h0000644000076400007640000000226206541176434015612 0ustar nelsonnelson#ifndef GEN_ALLOC_DEFS_H #define GEN_ALLOC_DEFS_H #define GEN_ALLOC_ready(ta,type,field,len,a,i,n,x,base,ta_ready) \ int ta_ready(x,n) register ta *x; register unsigned int n; \ { register unsigned int i; \ if (x->field) { \ i = x->a; \ if (n > i) { \ x->a = base + n + (n >> 3); \ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } #define GEN_ALLOC_readyplus(ta,type,field,len,a,i,n,x,base,ta_rplus) \ int ta_rplus(x,n) register ta *x; register unsigned int n; \ { register unsigned int i; \ if (x->field) { \ i = x->a; n += x->len; \ if (n > i) { \ x->a = base + n + (n >> 3); \ if (alloc_re(&x->field,i * sizeof(type),x->a * sizeof(type))) return 1; \ x->a = i; return 0; } \ return 1; } \ x->len = 0; \ return !!(x->field = (type *) alloc((x->a = n) * sizeof(type))); } #define GEN_ALLOC_append(ta,type,field,len,a,i,n,x,base,ta_rplus,ta_append) \ int ta_append(x,i) register ta *x; register type *i; \ { if (!ta_rplus(x,1)) return 0; x->field[x->len++] = *i; return 1; } #endif netqmail-1.06/prioq.h0000644000076400007640000000042406541176434014155 0ustar nelsonnelson#ifndef PRIOQ_H #define PRIOQ_H #include "datetime.h" #include "gen_alloc.h" struct prioq_elt { datetime_sec dt; unsigned long id; } ; GEN_ALLOC_typedef(prioq,struct prioq_elt,p,len,a) extern int prioq_insert(); extern int prioq_min(); extern void prioq_delmin(); #endif netqmail-1.06/lock_ex.c0000644000076400007640000000035606541176434014446 0ustar nelsonnelson#include #include #include #include "hasflock.h" #include "lock.h" #ifdef HASFLOCK int lock_ex(fd) int fd; { return flock(fd,LOCK_EX); } #else int lock_ex(fd) int fd; { return lockf(fd,1,0); } #endif netqmail-1.06/qail.sh0000644000076400007640000000005606541176434014135 0ustar nelsonnelsonQMAIL/bin/maildir2mbox && exec Mail ${1+"$@"} netqmail-1.06/gen_alloc.h0000644000076400007640000000025506541176434014750 0ustar nelsonnelson#ifndef GEN_ALLOC_H #define GEN_ALLOC_H #define GEN_ALLOC_typedef(ta,type,field,len,a) \ typedef struct ta { type *field; unsigned int len; unsigned int a; } ta; #endif netqmail-1.06/VERSION0000644000076400007640000000001610727260204013705 0ustar nelsonnelsonnetqmail 1.06 netqmail-1.06/byte_chr.c0000644000076400007640000000060206541176434014613 0ustar nelsonnelson#include "byte.h" unsigned int byte_chr(s,n,c) char *s; register unsigned int n; int c; { register char ch; register char *t; ch = c; t = s; for (;;) { if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; if (!n) break; if (*t == ch) break; ++t; --n; } return t - s; } netqmail-1.06/fmt_str.c0000644000076400007640000000034206541176434014473 0ustar nelsonnelson#include "fmt.h" unsigned int fmt_str(s,t) register char *s; register char *t; { register unsigned int len; char ch; len = 0; if (s) { while (ch = t[len]) s[len++] = ch; } else while (t[len]) len++; return len; } netqmail-1.06/subfderr.c0000644000076400007640000000026206541176434014632 0ustar nelsonnelson#include "readwrite.h" #include "substdio.h" #include "subfd.h" char subfd_errbuf[256]; static substdio it = SUBSTDIO_FDBUF(write,2,subfd_errbuf,256); substdio *subfderr = ⁢ netqmail-1.06/direntry.h10000644000076400007640000000017206541176434014744 0ustar nelsonnelson#ifndef DIRENTRY_H #define DIRENTRY_H #include #include #define direntry struct direct #endif netqmail-1.06/cdbmake_add.c0000644000076400007640000000443310724070436015211 0ustar nelsonnelson#include "alloc.h" #include "cdbmake.h" void cdbmake_init(cdbm) struct cdbmake *cdbm; { cdbm->head = 0; cdbm->split = 0; cdbm->hash = 0; cdbm->numentries = 0; } int cdbmake_add(cdbm,h,p,alloc) struct cdbmake *cdbm; uint32 h; uint32 p; char *(*alloc)(); { struct cdbmake_hplist *head; head = cdbm->head; if (!head || (head->num >= CDBMAKE_HPLIST)) { head = (struct cdbmake_hplist *) alloc(sizeof(struct cdbmake_hplist)); if (!head) return 0; head->num = 0; head->next = cdbm->head; cdbm->head = head; } head->hp[head->num].h = h; head->hp[head->num].p = p; ++head->num; ++cdbm->numentries; return 1; } int cdbmake_split(cdbm,alloc) struct cdbmake *cdbm; char *(*alloc)(); { int i; uint32 u; uint32 memsize; struct cdbmake_hplist *x; for (i = 0;i < 256;++i) cdbm->count[i] = 0; for (x = cdbm->head;x;x = x->next) { i = x->num; while (i--) ++cdbm->count[255 & x->hp[i].h]; } memsize = 1; for (i = 0;i < 256;++i) { u = cdbm->count[i] * 2; if (u > memsize) memsize = u; } memsize += cdbm->numentries; /* no overflow possible up to now */ u = (uint32) 0 - (uint32) 1; u /= sizeof(struct cdbmake_hp); if (memsize > u) return 0; cdbm->split = (struct cdbmake_hp *) alloc(memsize * sizeof(struct cdbmake_hp)); if (!cdbm->split) return 0; cdbm->hash = cdbm->split + cdbm->numentries; u = 0; for (i = 0;i < 256;++i) { u += cdbm->count[i]; /* bounded by numentries, so no overflow */ cdbm->start[i] = u; } for (x = cdbm->head;x;x = x->next) { i = x->num; while (i--) cdbm->split[--cdbm->start[255 & x->hp[i].h]] = x->hp[i]; } return 1; } uint32 cdbmake_throw(cdbm,pos,b) struct cdbmake *cdbm; uint32 pos; int b; { uint32 len; uint32 j; uint32 count; struct cdbmake_hp *hp; uint32 where; count = cdbm->count[b]; len = count + count; /* no overflow possible */ cdbmake_pack(cdbm->final + 8 * b,pos); cdbmake_pack(cdbm->final + 8 * b + 4,len); if (len) { for (j = 0;j < len;++j) cdbm->hash[j].h = cdbm->hash[j].p = 0; hp = cdbm->split + cdbm->start[b]; for (j = 0;j < count;++j) { where = (hp->h >> 8) % len; while (cdbm->hash[where].p) if (++where == len) where = 0; cdbm->hash[where] = *hp++; } } return len; } netqmail-1.06/qmail-local.80000644000076400007640000000324106541176434015136 0ustar nelsonnelson.TH qmail-local 8 .SH NAME qmail-local \- deliver or forward a mail message .SH SYNOPSIS .B qmail-local [ .B \-nN ] .I user .I homedir .I local .I dash .I ext .I domain .I sender .I defaultdelivery .SH DESCRIPTION .B qmail-local reads a mail message and delivers it to .I user by the procedure described in .BR dot-qmail(5) . The message's envelope recipient is .IR local@domain . .B qmail-local records .I local@domain in a new .B Delivered-To header field. If exactly the same .B Delivered-To: \fIlocal@domain already appears in the header, .B qmail-local bounces the message, to prevent mail forwarding loops. The message's envelope sender is .IR sender . .B qmail-local records .I sender in a new .B Return-Path header field. .I homedir is the user's home directory. It must be an absolute directory name. .I dash and .I ext identify the .B .qmail\fIdashext file used by .BR qmail-local ; see .BR dot-qmail(5) . Normally .I dash is either empty or a lone hyphen. If it is empty, .B qmail-local treats a nonexistent .B .qmail\fIext the same way as an empty .BR .qmail\fIext : namely, following the delivery instructions in .IR defaultdelivery . The standard input for .B qmail-local must be a seekable file, so that .B qmail-local can read it more than once. .SH "OPTIONS" .TP .B \-n Instead of reading and delivering the message, print a description of the delivery instructions. .TP .B \-N (Default.) Read and deliver the message. .SH "EXIT CODES" 0 if the delivery is completely successful; nonzero if any delivery instruction failed. Exit code 111 indicates temporary failure. .SH "SEE ALSO" dot-qmail(5), envelopes(5), qmail-command(8), qmail-queue(8), qmail-send(8), qmail-lspawn(8) netqmail-1.06/qmail.h0000644000076400007640000000060406541176434014126 0ustar nelsonnelson#ifndef QMAIL_H #define QMAIL_H #include "substdio.h" struct qmail { int flagerr; unsigned long pid; int fdm; int fde; substdio ss; char buf[1024]; } ; extern int qmail_open(); extern void qmail_put(); extern void qmail_puts(); extern void qmail_from(); extern void qmail_to(); extern void qmail_fail(); extern char *qmail_close(); extern unsigned long qmail_qp(); #endif netqmail-1.06/newfield.h0000644000076400007640000000030706541176434014620 0ustar nelsonnelson#ifndef NEWFIELD_H #define NEWFIELD_H #include "stralloc.h" extern stralloc newfield_date; extern int newfield_datemake(); extern stralloc newfield_msgid; extern int newfield_msgidmake(); #endif netqmail-1.06/timeoutread.c0000644000076400007640000000066206541176434015344 0ustar nelsonnelson#include "timeoutread.h" #include "select.h" #include "error.h" #include "readwrite.h" int timeoutread(t,fd,buf,len) int t; int fd; char *buf; int len; { fd_set rfds; struct timeval tv; tv.tv_sec = t; tv.tv_usec = 0; FD_ZERO(&rfds); FD_SET(fd,&rfds); if (select(fd + 1,&rfds,(fd_set *) 0,(fd_set *) 0,&tv) == -1) return -1; if (FD_ISSET(fd,&rfds)) return read(fd,buf,len); errno = error_timeout; return -1; } netqmail-1.06/datetime.30000644000076400007640000000311306541176434014530 0ustar nelsonnelson.TH datetime 3 .SH NAME datetime \- convert between TAI labels and seconds .SH SYNTAX .B #include void \fBdatetime_tai\fP(&\fIdt\fR,\fIt\fR); datetime_sec \fBdatetime_untai\fP(&\fIdt\fR); struct datetime \fIdt\fR; .br datetime_sec \fIt\fR; .SH DESCRIPTION International Atomic Time, TAI, is the fundamental unit for time measurements. TAI has one label for every second of real time, without complications such as leap seconds. A struct datetime variable, such as .IR dt , stores a TAI label. .I dt\fB.year is the year number minus 1900; .I dt\fB.mon is the month number, from 0 (January) through 11 (December); .I dt\fB.mday is the day of the month, from 1 through 31; .I dt\fB.hour is the hour, from 0 through 23; .I dt\fB.min is the minute, from 0 through 59; .I dt\fB.sec is the second, from 0 through 59; .I dt\fB.wday is the day of the week, from 0 (Sunday) through 6 (Saturday); .I dt\fB.yday is the day of the year, from 0 through 365. The .B datetime library supports more convenient TAI manipulation with the datetime_sec type. A datetime_sec value, such as .IR t , is an integer referring to the .IR t th second after the beginning of 1970 TAI. The first second of 1970 TAI was 0; the next second was 1; the last second of 1969 TAI was -1. The difference between two datetime_sec values is a number of real-time seconds. .B datetime_tai converts a datetime_sec to a TAI label. .B datetime_untai reads a TAI label (specifically .IR dt\fB.year , .IR dt\fB.mon , .IR dt\fB.mday , .IR dt\fB.hour , .IR dt\fB.min , and .IR dt\fB.sec ) and returns a datetime_sec. .SH "SEE ALSO" now(3) netqmail-1.06/condredirect.c0000644000076400007640000000376706541176434015500 0ustar nelsonnelson#include "sig.h" #include "readwrite.h" #include "exit.h" #include "env.h" #include "error.h" #include "fork.h" #include "wait.h" #include "seek.h" #include "qmail.h" #include "strerr.h" #include "substdio.h" #include "fmt.h" #define FATAL "condredirect: fatal: " struct qmail qqt; int mywrite(fd,buf,len) int fd; char *buf; int len; { qmail_put(&qqt,buf,len); return len; } char inbuf[SUBSTDIO_INSIZE]; char outbuf[1]; substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf); char num[FMT_ULONG]; void main(argc,argv) int argc; char **argv; { char *sender; char *dtline; int pid; int wstat; char *qqx; if (!argv[1] || !argv[2]) strerr_die1x(100,"condredirect: usage: condredirect newaddress program [ arg ... ]"); pid = fork(); if (pid == -1) strerr_die2sys(111,FATAL,"unable to fork: "); if (pid == 0) { execvp(argv[2],argv + 2); if (error_temp(errno)) _exit(111); _exit(100); } if (wait_pid(&wstat,pid) == -1) strerr_die2x(111,FATAL,"wait failed"); if (wait_crashed(wstat)) strerr_die2x(111,FATAL,"child crashed"); switch(wait_exitcode(wstat)) { case 0: break; case 111: strerr_die2x(111,FATAL,"temporary child error"); default: _exit(0); } if (seek_begin(0) == -1) strerr_die2sys(111,FATAL,"unable to rewind: "); sig_pipeignore(); sender = env_get("SENDER"); if (!sender) strerr_die2x(100,FATAL,"SENDER not set"); dtline = env_get("DTLINE"); if (!dtline) strerr_die2x(100,FATAL,"DTLINE not set"); if (qmail_open(&qqt) == -1) strerr_die2sys(111,FATAL,"unable to fork: "); qmail_puts(&qqt,dtline); if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to read message: "); substdio_flush(&ssout); num[fmt_ulong(num,qmail_qp(&qqt))] = 0; qmail_from(&qqt,sender); qmail_to(&qqt,argv[1]); qqx = qmail_close(&qqt); if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); strerr_die2x(99,"condredirect: qp ",num); } netqmail-1.06/qmail-queue.c0000644000076400007640000001306206541176434015245 0ustar nelsonnelson#include #include #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(53); } void die_read() { cleanup(); die(54); } void sigalrm() { /* thou shalt not clean up here */ die(52); } void sigbug() { die(81); } 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(51); 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(51); 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(51); for (seq = 1;seq < 10;++seq) { if (pidfmt((char *) 0,seq) > len) die(81); /* paranoia */ pidfmt(pidfn,seq); messfd = open_excl(pidfn); if (messfd != -1) return; } die(63); } char tmp[FMT_ULONG]; void main() { unsigned int len; char ch; sig_blocknone(); umask(033); if (chdir(auto_qmail) == -1) die(61); if (chdir("queue") == -1) die(62); 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(63); messnum = pidst.st_ino; messfn = fnnum("mess/",1); todofn = fnnum("todo/",0); intdfn = fnnum("intd/",0); if (link(pidfn,messfn) == -1) die(64); if (unlink(pidfn) == -1) die(63); 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(65); 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(91); 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(11); 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(91); 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(11); } if (substdio_flush(&ssout) == -1) die_write(); if (fsync(intdfd) == -1) die_write(); if (link(intdfn,todofn) == -1) die(66); triggerpull(); die(0); } netqmail-1.06/commands.h0000644000076400007640000000021706541176434014624 0ustar nelsonnelson#ifndef COMMANDS_H #define COMMANDS_H struct commands { char *text; void (*fun)(); void (*flush)(); } ; extern int commands(); #endif netqmail-1.06/qmail-getpw.c0000644000076400007640000000357606541176434015260 0ustar nelsonnelson#include #include #include #include "readwrite.h" #include "substdio.h" #include "subfd.h" #include "error.h" #include "exit.h" #include "byte.h" #include "str.h" #include "case.h" #include "fmt.h" #include "auto_usera.h" #include "auto_break.h" #include "qlx.h" #define GETPW_USERLEN 32 char *local; struct passwd *pw; char *dash; char *extension; int userext() { char username[GETPW_USERLEN]; struct stat st; extension = local + str_len(local); for (;;) { if (extension - local < sizeof(username)) if (!*extension || (*extension == *auto_break)) { byte_copy(username,extension - local,local); username[extension - local] = 0; case_lowers(username); errno = 0; pw = getpwnam(username); if (errno == error_txtbsy) _exit(QLX_SYS); if (pw) if (pw->pw_uid) if (stat(pw->pw_dir,&st) == 0) { if (st.st_uid == pw->pw_uid) { dash = ""; if (*extension) { ++extension; dash = "-"; } return 1; } } else if (error_temp(errno)) _exit(QLX_NFS); } if (extension == local) return 0; --extension; } } char num[FMT_ULONG]; void main(argc,argv) int argc; char **argv; { local = argv[1]; if (!local) _exit(100); if (!userext()) { extension = local; dash = "-"; pw = getpwnam(auto_usera); } if (!pw) _exit(QLX_NOALIAS); substdio_puts(subfdoutsmall,pw->pw_name); substdio_put(subfdoutsmall,"",1); substdio_put(subfdoutsmall,num,fmt_ulong(num,(long) pw->pw_uid)); substdio_put(subfdoutsmall,"",1); substdio_put(subfdoutsmall,num,fmt_ulong(num,(long) pw->pw_gid)); substdio_put(subfdoutsmall,"",1); substdio_puts(subfdoutsmall,pw->pw_dir); substdio_put(subfdoutsmall,"",1); substdio_puts(subfdoutsmall,dash); substdio_put(subfdoutsmall,"",1); substdio_puts(subfdoutsmall,extension); substdio_put(subfdoutsmall,"",1); substdio_flush(subfdoutsmall); _exit(0); } netqmail-1.06/binm3.sh0000644000076400007640000000046506541176434014223 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using V7 binmail interface: /bin/mail -f exec env - PATH="QMAIL/bin:$PATH" \ qmail-start \ '|preline -f /bin/mail -f "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/other-patches/0000755000076400007640000000000010117107755015412 5ustar nelsonnelsonnetqmail-1.06/other-patches/djbdns-1.05.errno.patch0000664000076400007640000000047607610701400021404 0ustar nelsonnelsondiff -u djbdns-1.05.old/error.h djbdns-1.05/error.h --- djbdns-1.05.old/error.h 2001-02-11 15:11:23.000000000 -0600 +++ djbdns-1.05/error.h 2003-01-08 16:08:42.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/other-patches/ucspi-tcp-0.88.a_record.patch0000644000076400007640000000344407610700705022515 0ustar nelsonnelsondiff -ruN --exclude conf-* ucspi-tcp-0.88/rblsmtpd.c ucspi-tcp-0.88.fix/rblsmtpd.c --- ucspi-tcp-0.88/rblsmtpd.c Sat Mar 18 10:18:42 2000 +++ ucspi-tcp-0.88.fix/rblsmtpd.c Wed Aug 9 16:42:33 2000 @@ -60,16 +60,54 @@ void rbl(char *base) { + int i; + char *altreply = 0; if (decision) return; if (!stralloc_copy(&tmp,&ip_reverse)) nomem(); + i = str_chr(base, ':'); + if (base[i]) { + base[i] = 0; + altreply = base+i+1; + } if (!stralloc_cats(&tmp,base)) nomem(); - if (dns_txt(&text,&tmp) == -1) { - flagmustnotbounce = 1; - if (flagfailclosed) { - if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); - decision = 2; + if (altreply) { + if (dns_ip4(&text,&tmp) == -1) { + flagmustnotbounce = 1; + if (flagfailclosed) { + if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); + decision = 2; + } + return; + } + if (text.len) { + if(!stralloc_copys(&text, "")) nomem(); + while(*altreply) { + char *x; + i = str_chr(altreply, '%'); + if(!stralloc_catb(&text, altreply, i)) nomem(); + if(altreply[i] && + altreply[i+1]=='I' && + altreply[i+2]=='P' && + altreply[i+3]=='%') { + if(!stralloc_catb(&text, ip_env, str_len(ip_env))) nomem(); + altreply+=i+4; + } else if(altreply[i]) { + if(!stralloc_cats(&text, "%")) nomem(); + altreply+=i+1; + } else { + altreply+=i; + } + } + } + } else { + if (dns_txt(&text,&tmp) == -1) { + flagmustnotbounce = 1; + if (flagfailclosed) { + if (!stralloc_copys(&text,"temporary RBL lookup error")) nomem(); + decision = 2; + } + return; } - return; } if (text.len) if (flagrblbounce) netqmail-1.06/other-patches/mess822-0.58.errno.patch0000644000076400007640000000173007610717031021351 0ustar nelsonnelsondiff -u mess822-0.58.old/cdb_seek.c mess822-0.58/cdb_seek.c --- mess822-0.58.old/cdb_seek.c 1998-09-04 21:33:37.000000000 -0500 +++ mess822-0.58/cdb_seek.c 2003-01-13 23:17:30.000000000 -0600 @@ -1,6 +1,5 @@ #include #include -extern int errno; #include "cdb.h" #ifndef SEEK_SET diff -u mess822-0.58.old/error.h mess822-0.58/error.h --- mess822-0.58.old/error.h 1998-09-04 21:33:37.000000000 -0500 +++ mess822-0.58/error.h 2003-01-13 23:18:09.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; diff -u mess822-0.58.old/leapsecs_read.c mess822-0.58/leapsecs_read.c --- mess822-0.58.old/leapsecs_read.c 1998-09-04 21:33:37.000000000 -0500 +++ mess822-0.58/leapsecs_read.c 2003-01-13 23:19:17.000000000 -0600 @@ -2,7 +2,6 @@ #include #include #include -extern int errno; #include "tai.h" #include "leapsecs.h" netqmail-1.06/other-patches/daemontools-0.76.errno.patch0000644000076400007640000000054307610701177022477 0ustar nelsonnelsondiff -ur daemontools-0.76.old/src/error.h daemontools-0.76/src/error.h --- daemontools-0.76.old/src/error.h 2001-07-12 11:49:49.000000000 -0500 +++ daemontools-0.76/src/error.h 2003-01-09 21:52:01.000000000 -0600 @@ -3,7 +3,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/other-patches/ucspi-tcp-0.88.nodefaultrbl.patch0000644000076400007640000000146607635375376023445 0ustar nelsonnelsondiff -ur ucspi-tcp-0.88.orig/rblsmtpd.c ucspi-tcp-0.88/rblsmtpd.c --- ucspi-tcp-0.88.orig/rblsmtpd.c Thu Jan 16 14:33:56 2003 +++ ucspi-tcp-0.88/rblsmtpd.c Thu Jan 16 14:38:17 2003 @@ -155,7 +155,6 @@ main(int argc,char **argv,char **envp) { - int flagwantdefaultrbl = 1; char *x; int opt; @@ -182,7 +181,7 @@ case 'c': flagfailclosed = 1; break; case 'C': flagfailclosed = 0; break; case 't': scan_ulong(optarg,&timeout); break; - case 'r': rbl(optarg); flagwantdefaultrbl = 0; break; + case 'r': rbl(optarg); break; case 'a': antirbl(optarg); break; default: usage(); } @@ -190,7 +189,6 @@ argv += optind; if (!*argv) usage(); - if (flagwantdefaultrbl) rbl("rbl.maps.vix.com"); if (decision >= 2) rblsmtpd(); pathexec_run(*argv,argv,envp); netqmail-1.06/other-patches/ucspi-tcp-0.88.errno.patch0000644000076400007640000000051207610700705022055 0ustar nelsonnelsondiff -u ucspi-tcp-0.88.old/error.h ucspi-tcp-0.88/error.h --- ucspi-tcp-0.88.old/error.h 2000-03-18 09:18:20.000000000 -0600 +++ ucspi-tcp-0.88/error.h 2003-01-08 13:39:12.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/other-patches/fastforward-0.51.errno.patch0000664000076400007640000000123310006240045022446 0ustar nelsonnelsondiff -u fastforward-0.51.orig/cdb_seek.c fastforward-0.51/cdb_seek.c --- fastforward-0.51.orig/cdb_seek.c 1998-05-19 11:25:42.000000000 -0500 +++ fastforward-0.51/cdb_seek.c 2004-01-29 11:22:24.000000000 -0600 @@ -1,6 +1,5 @@ #include #include -extern int errno; #include "cdb.h" #ifndef SEEK_SET diff -u fastforward-0.51.orig/error.h fastforward-0.51/error.h --- fastforward-0.51.orig/error.h 1998-05-19 11:25:42.000000000 -0500 +++ fastforward-0.51/error.h 2004-01-29 11:14:47.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/other-patches/qmailanalog-0.70.errno.patch0000644000076400007640000000454110117107447022430 0ustar nelsonnelsondiff -u orig/error.3 ./error.3 --- orig/error.3 1998-08-30 17:39:27.000000000 -0400 +++ ./error.3 2004-09-06 12:17:26.000000000 -0400 @@ -3,8 +3,8 @@ error \- syscall error codes .SH SYNTAX .B #include - -extern int \fBerrno\fP; +.br +.B #include extern int \fBerror_intr\fP; .br diff -u orig/error.c ./error.c --- orig/error.c 1998-08-30 17:39:27.000000000 -0400 +++ ./error.c 2004-09-06 12:17:26.000000000 -0400 @@ -1,4 +1,3 @@ -#include #include "error.h" /* warning: as coverage improves here, should update error_{str,temp} */ diff -u orig/error.h ./error.h --- orig/error.h 1998-08-30 17:39:27.000000000 -0400 +++ ./error.h 2004-09-06 12:17:26.000000000 -0400 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; diff -u orig/Makefile ./Makefile --- orig/Makefile 1998-08-30 17:39:26.000000000 -0400 +++ ./Makefile 2004-09-06 12:17:26.000000000 -0400 @@ -259,7 +259,7 @@ matchup.o: \ compile matchup.c stralloc.h gen_alloc.h gen_alloc.h gen_allocdefs.h \ strerr.h getln.h substdio.h subfd.h substdio.h readwrite.h exit.h \ -str.h fmt.h scan.h case.h +str.h fmt.h scan.h case.h alloc.h ./compile matchup.c open.a: \ diff -u orig/matchup.c ./matchup.c --- orig/matchup.c 1998-08-30 17:39:27.000000000 -0400 +++ ./matchup.c 2004-09-06 12:23:20.000000000 -0400 @@ -1,3 +1,4 @@ +#include "alloc.h" #include "stralloc.h" #include "gen_alloc.h" #include "gen_allocdefs.h" @@ -439,6 +440,32 @@ if (getln(subfdin,&line,&match,'\n') == -1) die_read(); if (!match) break; + if (line.s[0] == '@' && line.len >= 25) { + unsigned long secs; + unsigned long nanosecs; + unsigned long u; + + secs = 0; + nanosecs = 0; + for (i = 1; i < line.len;i++) { + u = line.s[i] - '0'; + if (u >= 10) { + u = line.s[i] - 'a'; + if (u >= 6) break; + u += 10; + } + secs <<= 4; + secs += nanosecs >> 28; + nanosecs &= 0xfffffff; + nanosecs <<= 4; + nanosecs += u; + } + secs -= 4611686018427387914ULL; + i = fmt_uint0(line.s,secs,9); + line.s[i++] = '.'; + i += fmt_uint0(line.s+i,nanosecs,9); + while (i < 25) line.s[i++] = ' '; + } if (!stralloc_copy(&outline,&line)) nomem(); for (i = 0;i < line.len;++i) { netqmail-1.06/other-patches/serialmail-0.75.errno.patch0000664000076400007640000000127710006240045022264 0ustar nelsonnelsondiff -u serialmail-0.75.orig/error.h serialmail-0.75/error.h --- serialmail-0.75.orig/error.h 1998-11-14 20:28:23.000000000 -0600 +++ serialmail-0.75/error.h 2004-01-29 11:15:32.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; diff -u serialmail-0.75.orig/leapsecs_read.c serialmail-0.75/leapsecs_read.c --- serialmail-0.75.orig/leapsecs_read.c 1998-11-14 20:28:23.000000000 -0600 +++ serialmail-0.75/leapsecs_read.c 2004-01-29 11:20:09.000000000 -0600 @@ -2,7 +2,6 @@ #include #include #include -extern int errno; #include "tai.h" #include "leapsecs.h" netqmail-1.06/other-patches/dot-forward-0.71.errno.patch0000664000076400007640000000052410006240045022360 0ustar nelsonnelsondiff -u dot-forward-0.71.orig/error.h dot-forward-0.71/error.h --- dot-forward-0.71.orig/error.h 1998-05-19 05:15:50.000000000 -0500 +++ dot-forward-0.71/error.h 2004-01-29 11:16:01.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/other-patches/README0000664000076400007640000000310410117107755016272 0ustar nelsonnelsonIf you have glibc-2.3.1 or later then none of the software written by djb will compile because of an incompatible declaration of errno. Here you can find patches correcting this problem for software likely you need if you run qmail. To use the patches ================== From the top distribution directory, apply the appropriate errno patch with -p1. So, for example, for mess822, you would do tar zxvf mess822-0.58.tar.gz cd mess822-0.58 patch -p1 < /path/to/mess822-0.58.errno.patch In case of daemontools, you need the following adjustment: tar zxvf daemontools-0.76.tar.gz cd admin/daemontools-0.76 patch -p1 /path/to/daemontools-0.76.errno.patch Notes ----- ucspi-tcp: In addition to the errno patch, there are two other patches included here; both update rblsmtpd's behavior to current practices on the net. The a_record patch allows you to specify the error that will be returned by rblsmtpd for a zone that has only A records in it. The nodefaultrbl patch changes the behavior of rblsmtpd so that if no `-r' flag is given, than instead of falling back to rbl.maps.vix.com as the default RBL, rblsmtpd assumes that no RBL is to be used. qmailanalog: In addition to the required errno change, the qmailanalog patch also changes qmailanalog to accept both tai and tai64n times. This is necessary because djb never updated qmailanalog after he changed daemontools to tai64n. These notes were originally written by Mate Wierdl, and have been modified for this distribution by Russell Nelson, and then were rewritten by Mate again, and then added to by Russell Nelson. netqmail-1.06/other-patches/checkpassword-0.90.errno.patch0000644000076400007640000000053207610731562023006 0ustar nelsonnelsondiff -u checkpassword-0.90.old/error.h checkpassword-0.90/error.h --- checkpassword-0.90.old/error.h 2000-12-23 00:40:46.000000000 -0600 +++ checkpassword-0.90/error.h 2003-01-14 00:49:57.000000000 -0600 @@ -1,7 +1,7 @@ #ifndef ERROR_H #define ERROR_H -extern int errno; +#include extern int error_intr; extern int error_nomem; netqmail-1.06/tcpto.c0000644000076400007640000000703706541176434014156 0ustar nelsonnelson#include "tcpto.h" #include "open.h" #include "lock.h" #include "seek.h" #include "now.h" #include "ip.h" #include "byte.h" #include "datetime.h" #include "readwrite.h" char tcpto_buf[1024]; static int flagwasthere; static int fdlock; static int getbuf() { int r; int fd; fdlock = open_write("queue/lock/tcpto"); if (fdlock == -1) return 0; fd = open_read("queue/lock/tcpto"); if (fd == -1) { close(fdlock); return 0; } if (lock_ex(fdlock) == -1) { close(fdlock); close(fd); return 0; } r = read(fd,tcpto_buf,sizeof(tcpto_buf)); close(fd); if (r < 0) { close(fdlock); return 0; } r >>= 4; if (!r) close(fdlock); return r; } int tcpto(ip) struct ip_address *ip; { int n; int i; char *record; datetime_sec when; flagwasthere = 0; n = getbuf(); if (!n) return 0; close(fdlock); record = tcpto_buf; for (i = 0;i < n;++i) { if (byte_equal(ip->d,4,record)) { flagwasthere = 1; if (record[4] >= 2) { when = (unsigned long) (unsigned char) record[11]; when = (when << 8) + (unsigned long) (unsigned char) record[10]; when = (when << 8) + (unsigned long) (unsigned char) record[9]; when = (when << 8) + (unsigned long) (unsigned char) record[8]; if (now() - when < ((60 + (getpid() & 31)) << 6)) return 1; } return 0; } record += 16; } return 0; } void tcpto_err(ip,flagerr) struct ip_address *ip; int flagerr; { int n; int i; char *record; datetime_sec when; datetime_sec firstwhen; int firstpos; datetime_sec lastwhen; if (!flagerr) if (!flagwasthere) return; /* could have been added, but not worth the effort to check */ n = getbuf(); if (!n) return; record = tcpto_buf; for (i = 0;i < n;++i) { if (byte_equal(ip->d,4,record)) { if (!flagerr) record[4] = 0; else { lastwhen = (unsigned long) (unsigned char) record[11]; lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[10]; lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[9]; lastwhen = (lastwhen << 8) + (unsigned long) (unsigned char) record[8]; when = now(); if (record[4] && (when < 120 + lastwhen)) { close(fdlock); return; } if (++record[4] > 10) record[4] = 10; record[8] = when; when >>= 8; record[9] = when; when >>= 8; record[10] = when; when >>= 8; record[11] = when; } if (seek_set(fdlock,i << 4) == 0) if (write(fdlock,record,16) < 16) ; /*XXX*/ close(fdlock); return; } record += 16; } if (!flagerr) { close(fdlock); return; } record = tcpto_buf; for (i = 0;i < n;++i) { if (!record[4]) break; record += 16; } if (i >= n) { firstpos = -1; record = tcpto_buf; for (i = 0;i < n;++i) { when = (unsigned long) (unsigned char) record[11]; when = (when << 8) + (unsigned long) (unsigned char) record[10]; when = (when << 8) + (unsigned long) (unsigned char) record[9]; when = (when << 8) + (unsigned long) (unsigned char) record[8]; when += (record[4] << 10); if ((firstpos < 0) || (when < firstwhen)) { firstpos = i; firstwhen = when; } record += 16; } i = firstpos; } if (i >= 0) { record = tcpto_buf + (i << 4); byte_copy(record,4,ip->d); when = now(); record[8] = when; when >>= 8; record[9] = when; when >>= 8; record[10] = when; when >>= 8; record[11] = when; record[4] = 1; if (seek_set(fdlock,i << 4) == 0) if (write(fdlock,record,16) < 16) ; /*XXX*/ } close(fdlock); } netqmail-1.06/qreceipt.10000644000076400007640000000111106541176434014542 0ustar nelsonnelson.TH qreceipt 1 .SH NAME qreceipt \- respond to delivery notice requests .SH SYNOPSIS in .BR .qmail : .B |qreceipt .I youraddress .SH DESCRIPTION When a mail message arrives with .I youraddress listed in a .B Notice-Requested-Upon-Delivery-To header field, .B qreceipt sends a success notice back to the envelope sender. .B WARNING: If you create a .B .qmail file to enable .BR qreceipt , make sure to also add a line specifying delivery to your normal mailbox. For example: .EX /home/joe/Mailbox .br |qreceipt joe@nowhere.mil .EE .SH "SEE ALSO" dot-qmail(5), envelopes(5) netqmail-1.06/date822fmt.c0000644000076400007640000000163206541176434014700 0ustar nelsonnelson#include "datetime.h" #include "fmt.h" #include "date822fmt.h" static char *montab[12] = { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" }; unsigned int date822fmt(s,dt) char *s; struct datetime *dt; { unsigned int i; unsigned int len; len = 0; i = fmt_uint(s,dt->mday); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; i = fmt_str(s,montab[dt->mon]); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; i = fmt_uint(s,dt->year + 1900); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; i = fmt_uint0(s,dt->hour,2); len += i; if (s) s += i; i = fmt_str(s,":"); len += i; if (s) s += i; i = fmt_uint0(s,dt->min,2); len += i; if (s) s += i; i = fmt_str(s,":"); len += i; if (s) s += i; i = fmt_uint0(s,dt->sec,2); len += i; if (s) s += i; i = fmt_str(s," -0000\n"); len += i; if (s) s += i; return len; } netqmail-1.06/stralloc_pend.c0000644000076400007640000000023106541176434015643 0ustar nelsonnelson#include "alloc.h" #include "stralloc.h" #include "gen_allocdefs.h" GEN_ALLOC_append(stralloc,char,s,len,a,i,n,x,30,stralloc_readyplus,stralloc_append) netqmail-1.06/now.30000644000076400007640000000040106541176434013534 0ustar nelsonnelson.TH now 3 .SH NAME now \- get current time, in seconds .SH SYNTAX .B #include datetime_sec \fBnow\fP(); .SH DESCRIPTION .B now returns the number of real-time seconds that have elapsed since the end of 1969 TAI. .SH "SEE ALSO" datetime(3), time(3) netqmail-1.06/byte_rchr.c0000644000076400007640000000066106541176434015002 0ustar nelsonnelson#include "byte.h" unsigned int byte_rchr(s,n,c) char *s; register unsigned int n; int c; { register char ch; register char *t; register char *u; ch = c; t = s; u = 0; for (;;) { if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; if (!n) break; if (*t == ch) u = t; ++t; --n; } if (!u) u = t; return u - s; } netqmail-1.06/cdb.h0000644000076400007640000000024006541176434013547 0ustar nelsonnelson#ifndef CDB_H #define CDB_H #include "uint32.h" extern uint32 cdb_hash(); extern uint32 cdb_unpack(); extern int cdb_bread(); extern int cdb_seek(); #endif netqmail-1.06/trymkffo.c0000644000076400007640000000013306541176434014654 0ustar nelsonnelson#include #include void main() { mkfifo("temp-trymkffo",0); } netqmail-1.06/PIC.relaygood0000644000076400007640000000214706541176434015200 0ustar nelsonnelsonqmail-smtpd Receive message by SMTP from another host: | MAIL FROM: | RCPT TO: | | Is $RELAYCLIENT set? Yes: "". | Accept RCPT. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, bill@irs.gov. | Is irs.gov in locals? No. | Is bill@irs.gov in virtualdomains? No. | Is irs.gov in virtualdomains? No. | Is .gov in virtualdomains? No. | Deliver remotely to bill@irs.gov. V qmail-rspawn Run qmail-remote. | V qmail-remote Look at host name, irs.gov. Is irs.gov listed in smtproutes? No. Look up DNS MX/A for irs.gov and connect to it by SMTP: MAIL FROM: RCPT TO: netqmail-1.06/trysalen.c0000644000076400007640000000025206541176434014656 0ustar nelsonnelson#include #include #include #include #include void foo() { struct sockaddr sa; sa.sa_len = 0; } netqmail-1.06/qmail-qread.80000644000076400007640000000103306541176434015135 0ustar nelsonnelson.TH qmail-qread 8 .SH NAME qmail-qread \- list outgoing messages and recipients .SH SYNOPSIS .B qmail-qread .SH DESCRIPTION .B qmail-qread scans the outgoing queue of messages. For each message it prints various human-readable information, including the date the message entered the queue, the number of bytes in the message, the message sender, and all the recipients still under consideration. .B qmail-qread must be run either as .B root or with user id .B qmails and group id .BR qmail . .SH "SEE ALSO" qmail-qstat(8), qmail-send(8) netqmail-1.06/fd_copy.c0000644000076400007640000000034106541176434014437 0ustar nelsonnelson#include #include "fd.h" int fd_copy(to,from) int to; int from; { if (to == from) return 0; if (fcntl(from,F_GETFL,0) == -1) return -1; close(to); if (fcntl(from,F_DUPFD,to) == -1) return -1; return 0; } netqmail-1.06/timeoutread.h0000644000076400007640000000011706541176434015344 0ustar nelsonnelson#ifndef TIMEOUTREAD_H #define TIMEOUTREAD_H extern int timeoutread(); #endif netqmail-1.06/PIC.local2local0000644000076400007640000000264706541176434015407 0ustar nelsonnelson Original message: To: fred Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to fred@heaven.af.mil | From: joe@heaven.af.mil | To: fred@heaven.af.mil | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, fred@heaven.af.mil. | Is heaven.af.mil in locals? Yes. | Deliver locally to fred@heaven.af.mil. V qmail-lspawn ./Mailbox | Look at mailbox name, fred. | Is fred listed in qmail-users? No. | Is there a fred account? Yes. | Is fred's uid nonzero? Yes. | Is ~fred visible to the qmailp user? Yes. | Is ~fred owned by fred? Yes. | Give control of the message to fred. | Run qmail-local. V qmail-local fred ~fred fred '' '' heaven.af.mil joe@heaven.af.mil ./Mailbox Does ~fred/.qmail exist? No. Write message to ./Mailbox in mbox format. netqmail-1.06/alloc.h0000644000076400007640000000020306541176434014110 0ustar nelsonnelson#ifndef ALLOC_H #define ALLOC_H extern /*@null@*//*@out@*/char *alloc(); extern void alloc_free(); extern int alloc_re(); #endif netqmail-1.06/FILES0000644000076400007640000001136110724070436013432 0ustar nelsonnelsonBLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL-1.03 INSTALL.vsm REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README BIN.Makefile idedit.c conf-break auto_break.h conf-spawn auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c trynpbg1.c trysyslog.c conf-cc conf-ld home.sh home+df.sh proc.sh proc+df.sh binm1.sh binm2.sh binm3.sh binm1+df.sh binm2+df.sh binm3+df.sh find-systype.sh make-compile.sh make-load.sh make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c open.h open_append.c open_excl.c open_read.c open_trunc.c open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c headerbody.h headerbody.c token822.h token822.c control.h control.c datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c netqmail-1.06/commands.c0000644000076400007640000000142606541176434014622 0ustar nelsonnelson#include "commands.h" #include "substdio.h" #include "stralloc.h" #include "str.h" #include "case.h" static stralloc cmd = {0}; int commands(ss,c) substdio *ss; struct commands *c; { int i; char *arg; for (;;) { if (!stralloc_copys(&cmd,"")) return -1; for (;;) { if (!stralloc_readyplus(&cmd,1)) return -1; i = substdio_get(ss,cmd.s + cmd.len,1); if (i != 1) return i; if (cmd.s[cmd.len] == '\n') break; ++cmd.len; } if (cmd.len > 0) if (cmd.s[cmd.len - 1] == '\r') --cmd.len; cmd.s[cmd.len] = 0; i = str_chr(cmd.s,' '); arg = cmd.s + i; while (*arg == ' ') ++arg; cmd.s[i] = 0; for (i = 0;c[i].text;++i) if (case_equals(c[i].text,cmd.s)) break; c[i].fun(arg); if (c[i].flush) c[i].flush(); } } netqmail-1.06/qmail-users.90000644000076400007640000000371606541176434015215 0ustar nelsonnelson.TH qmail-users 5 .SH NAME qmail-users \- assign mail addresses to users .SH OVERVIEW The file .B QMAILHOME/users/assign assigns addresses to users. For example, .EX =joe.shmoe:joe:503:78:/home/joe::: .EE says that mail for .B joe.shmoe should be delivered to user .BR joe , with uid 503 and gid 78, as specified by .BR /home/joe/.qmail . Assignments fed to .B qmail-newu will be used by .B qmail-lspawn to control .BR qmail-local 's deliveries. See .BR qmail-newu (8). A change to .B QMAILHOME/users/assign will have no effect until .B qmail-newu is run. .SH STRUCTURE .B QMAILHOME/users/assign is a series of assignments, one per line. It ends with a line containing a single dot. Lines must not contain NUL. .SH "SIMPLE ASSIGNMENTS" A simple assignment is a line of the form .EX =local:user:uid:gid:homedir:dash:ext: .EE Here .I local is an address; .IR user , .IR uid , and .I gid are the account name, uid, and gid of the user in charge of .IR local ; and messages to .I local will be controlled by .IR homedir\fB/.qmail\fIdashext . If there are several assignments for the same .I local address, .B qmail-lspawn will use the first one. .I local is interpreted without regard to case. .SH "WILDCARD ASSIGNMENTS" A wildcard assignment is a line of the form .EX +loc:user:uid:gid:homedir:dash:pre: .EE This assignment applies to any address beginning with .IR loc , including .I loc itself. It means the same as .EX =locext:user:uid:gid:homedir:dash:preext: .EE for every string .IR ext . A more specific wildcard assignment overrides a less specific assignment, and a simple assignment overrides any wildcard assignment. For example: .EX +:alias:7790:2108:QMAILHOME/alias:-:: +joe-:joe:507:100:/home/joe:-:: =joe:joe:507:100:/home/joe::: .EE The address .B joe is handled by the third line; the address .B joe-direct is handled by the second line; the address .B bill is handled by the first line. .SH "SEE ALSO" qmail-pw2u(8), qmail-newu(8), qmail-lspawn(8) netqmail-1.06/qmail-qmqpd.c0000644000076400007640000000614206541176434015244 0ustar nelsonnelson#include "auto_qmail.h" #include "qmail.h" #include "received.h" #include "sig.h" #include "substdio.h" #include "readwrite.h" #include "exit.h" #include "now.h" #include "fmt.h" #include "env.h" void resources() { _exit(111); } int safewrite(fd,buf,len) int fd; char *buf; int len; { int r; r = write(fd,buf,len); if (r <= 0) _exit(0); return r; } int saferead(fd,buf,len) int fd; char *buf; int len; { int r; r = read(fd,buf,len); if (r <= 0) _exit(0); return r; } char ssinbuf[512]; substdio ssin = SUBSTDIO_FDBUF(saferead,0,ssinbuf,sizeof ssinbuf); char ssoutbuf[256]; substdio ssout = SUBSTDIO_FDBUF(safewrite,1,ssoutbuf,sizeof ssoutbuf); unsigned long bytesleft = 100; void getbyte(ch) char *ch; { if (!bytesleft--) _exit(100); substdio_get(&ssin,ch,1); } unsigned long getlen() { unsigned long len = 0; char ch; for (;;) { getbyte(&ch); if (ch == ':') return len; if (len > 200000000) resources(); len = 10 * len + (ch - '0'); } } void getcomma() { char ch; getbyte(&ch); if (ch != ',') _exit(100); } struct qmail qq; void identify() { char *remotehost; char *remoteinfo; char *remoteip; char *local; remotehost = env_get("TCPREMOTEHOST"); if (!remotehost) remotehost = "unknown"; remoteinfo = env_get("TCPREMOTEINFO"); remoteip = env_get("TCPREMOTEIP"); if (!remoteip) remoteip = "unknown"; local = env_get("TCPLOCALHOST"); if (!local) local = env_get("TCPLOCALIP"); if (!local) local = "unknown"; received(&qq,"QMQP",local,remoteip,remotehost,remoteinfo,(char *) 0); } char buf[1000]; char strnum[FMT_ULONG]; int getbuf() { unsigned long len; int i; len = getlen(); if (len >= 1000) { for (i = 0;i < len;++i) getbyte(buf); getcomma(); buf[0] = 0; return 0; } for (i = 0;i < len;++i) getbyte(buf + i); getcomma(); buf[len] = 0; return byte_chr(buf,len,'\0') == len; } int flagok = 1; main() { char *result; unsigned long qp; unsigned long len; char ch; sig_pipeignore(); sig_alarmcatch(resources); alarm(3600); bytesleft = getlen(); len = getlen(); if (chdir(auto_qmail) == -1) resources(); if (qmail_open(&qq) == -1) resources(); qp = qmail_qp(&qq); identify(); while (len > 0) { /* XXX: could speed this up */ getbyte(&ch); --len; qmail_put(&qq,&ch,1); } getcomma(); if (getbuf()) qmail_from(&qq,buf); else { qmail_from(&qq,""); qmail_fail(&qq); flagok = 0; } while (bytesleft) if (getbuf()) qmail_to(&qq,buf); else { qmail_fail(&qq); flagok = 0; } bytesleft = 1; getcomma(); result = qmail_close(&qq); if (!*result) { len = fmt_str(buf,"Kok "); len += fmt_ulong(buf + len,(unsigned long) now()); len += fmt_str(buf + len," qp "); len += fmt_ulong(buf + len,qp); buf[len] = 0; result = buf; } if (!flagok) result = "Dsorry, I can't accept addresses like that (#5.1.3)"; substdio_put(&ssout,strnum,fmt_ulong(strnum,(unsigned long) str_len(result))); substdio_puts(&ssout,":"); substdio_puts(&ssout,result); substdio_puts(&ssout,","); substdio_flush(&ssout); _exit(0); } netqmail-1.06/chkshsgr.c0000644000076400007640000000021306541176434014626 0ustar nelsonnelson#include "exit.h" void main() { short x[4]; x[0] = x[1] = 0; if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); _exit(0); } netqmail-1.06/date822fmt.h0000644000076400007640000000015306541176434014702 0ustar nelsonnelson#ifndef DATE822FMT_H #define DATE822FMT_H extern unsigned int date822fmt(); #define DATE822FMT 60 #endif netqmail-1.06/maildir.c0000644000076400007640000000443506541176434014445 0ustar nelsonnelson#include #include #include "prioq.h" #include "env.h" #include "stralloc.h" #include "direntry.h" #include "datetime.h" #include "now.h" #include "str.h" #include "maildir.h" struct strerr maildir_chdir_err; struct strerr maildir_scan_err; int maildir_chdir() { char *maildir; maildir = env_get("MAILDIR"); if (!maildir) STRERR(-1,maildir_chdir_err,"MAILDIR not set") if (chdir(maildir) == -1) STRERR_SYS3(-1,maildir_chdir_err,"unable to chdir to ",maildir,": ") return 0; } void maildir_clean(tmpname) stralloc *tmpname; { DIR *dir; direntry *d; datetime_sec time; struct stat st; time = now(); dir = opendir("tmp"); if (!dir) return; while (d = readdir(dir)) { if (d->d_name[0] == '.') continue; if (!stralloc_copys(tmpname,"tmp/")) break; if (!stralloc_cats(tmpname,d->d_name)) break; if (!stralloc_0(tmpname)) break; if (stat(tmpname->s,&st) == 0) if (time > st.st_atime + 129600) unlink(tmpname->s); } closedir(dir); } static int append(pq,filenames,subdir,time) prioq *pq; stralloc *filenames; char *subdir; datetime_sec time; { DIR *dir; direntry *d; struct prioq_elt pe; unsigned int pos; struct stat st; dir = opendir(subdir); if (!dir) STRERR_SYS3(-1,maildir_scan_err,"unable to scan $MAILDIR/",subdir,": ") while (d = readdir(dir)) { if (d->d_name[0] == '.') continue; pos = filenames->len; if (!stralloc_cats(filenames,subdir)) break; if (!stralloc_cats(filenames,"/")) break; if (!stralloc_cats(filenames,d->d_name)) break; if (!stralloc_0(filenames)) break; if (stat(filenames->s + pos,&st) == 0) if (st.st_mtime < time) /* don't want to mix up the order */ { pe.dt = st.st_mtime; pe.id = pos; if (!prioq_insert(pq,&pe)) break; } } closedir(dir); if (d) STRERR_SYS3(-1,maildir_scan_err,"unable to read $MAILDIR/",subdir,": ") return 0; } int maildir_scan(pq,filenames,flagnew,flagcur) prioq *pq; stralloc *filenames; int flagnew; int flagcur; { struct prioq_elt pe; datetime_sec time; int r; if (!stralloc_copys(filenames,"")) return 0; while (prioq_min(pq,&pe)) prioq_delmin(pq); time = now(); if (flagnew) if (append(pq,filenames,"new",time) == -1) return -1; if (flagcur) if (append(pq,filenames,"cur",time) == -1) return -1; return 0; } netqmail-1.06/tcpto_clean.c0000644000076400007640000000070306541176434015311 0ustar nelsonnelson#include "tcpto.h" #include "open.h" #include "substdio.h" #include "readwrite.h" char tcpto_cleanbuf[1024]; void tcpto_clean() /* running from queue/mess */ { int fd; int i; substdio ss; fd = open_write("../lock/tcpto"); if (fd == -1) return; substdio_fdbuf(&ss,write,fd,tcpto_cleanbuf,sizeof(tcpto_cleanbuf)); for (i = 0;i < sizeof(tcpto_cleanbuf);++i) substdio_put(&ss,"",1); substdio_flush(&ss); /* if it fails, bummer */ close(fd); } netqmail-1.06/substdio.h0000644000076400007640000000171406541176434014662 0ustar nelsonnelson#ifndef SUBSTDIO_H #define SUBSTDIO_H typedef struct substdio { char *x; int p; int n; int fd; int (*op)(); } substdio; #define SUBSTDIO_FDBUF(op,fd,buf,len) { (buf), 0, (len), (fd), (op) } extern void substdio_fdbuf(); extern int substdio_flush(); extern int substdio_put(); extern int substdio_bput(); extern int substdio_putflush(); extern int substdio_puts(); extern int substdio_bputs(); extern int substdio_putsflush(); extern int substdio_get(); extern int substdio_bget(); extern int substdio_feed(); extern char *substdio_peek(); extern void substdio_seek(); #define substdio_fileno(s) ((s)->fd) #define SUBSTDIO_INSIZE 8192 #define SUBSTDIO_OUTSIZE 8192 #define substdio_PEEK(s) ( (s)->x + (s)->n ) #define substdio_SEEK(s,len) ( ( (s)->p -= (len) ) , ( (s)->n += (len) ) ) #define substdio_BPUTC(s,c) \ ( ((s)->n != (s)->p) \ ? ( (s)->x[(s)->p++] = (c), 0 ) \ : substdio_bput((s),&(c),1) \ ) extern int substdio_copy(); #endif netqmail-1.06/case_diffb.c0000644000076400007640000000064706541176434015072 0ustar nelsonnelson#include "case.h" int case_diffb(s,len,t) register char *s; unsigned int len; register char *t; { register unsigned char x; register unsigned char y; while (len > 0) { --len; x = *s++ - 'A'; if (x <= 'Z' - 'A') x += 'a'; else x += 'A'; y = *t++ - 'A'; if (y <= 'Z' - 'A') y += 'a'; else y += 'A'; if (x != y) return ((int)(unsigned int) x) - ((int)(unsigned int) y); } return 0; } netqmail-1.06/hier.c0000644000076400007640000003252106541176434013750 0ustar nelsonnelson#include "auto_qmail.h" #include "auto_split.h" #include "auto_uids.h" #include "fmt.h" #include "fifo.h" char buf[100 + FMT_ULONG]; void dsplit(base,uid,mode) char *base; /* must be under 100 bytes */ int uid; int mode; { char *x; unsigned long i; d(auto_qmail,base,uid,auto_gidq,mode); for (i = 0;i < auto_split;++i) { x = buf; x += fmt_str(x,base); x += fmt_str(x,"/"); x += fmt_ulong(x,i); *x = 0; d(auto_qmail,buf,uid,auto_gidq,mode); } } void hier() { h(auto_qmail,auto_uido,auto_gidq,0755); d(auto_qmail,"control",auto_uido,auto_gidq,0755); d(auto_qmail,"users",auto_uido,auto_gidq,0755); d(auto_qmail,"bin",auto_uido,auto_gidq,0755); d(auto_qmail,"boot",auto_uido,auto_gidq,0755); d(auto_qmail,"doc",auto_uido,auto_gidq,0755); d(auto_qmail,"man",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat1",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat5",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat7",auto_uido,auto_gidq,0755); d(auto_qmail,"man/cat8",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man1",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man5",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man7",auto_uido,auto_gidq,0755); d(auto_qmail,"man/man8",auto_uido,auto_gidq,0755); d(auto_qmail,"alias",auto_uida,auto_gidq,02755); d(auto_qmail,"queue",auto_uidq,auto_gidq,0750); d(auto_qmail,"queue/pid",auto_uidq,auto_gidq,0700); d(auto_qmail,"queue/intd",auto_uidq,auto_gidq,0700); d(auto_qmail,"queue/todo",auto_uidq,auto_gidq,0750); d(auto_qmail,"queue/bounce",auto_uids,auto_gidq,0700); dsplit("queue/mess",auto_uidq,0750); dsplit("queue/info",auto_uids,0700); dsplit("queue/local",auto_uids,0700); dsplit("queue/remote",auto_uids,0700); d(auto_qmail,"queue/lock",auto_uidq,auto_gidq,0750); z(auto_qmail,"queue/lock/tcpto",1024,auto_uidr,auto_gidq,0644); z(auto_qmail,"queue/lock/sendmutex",0,auto_uids,auto_gidq,0600); p(auto_qmail,"queue/lock/trigger",auto_uids,auto_gidq,0622); c(auto_qmail,"boot","home",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","home+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","proc",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","proc+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm1",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm1+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm2",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm2+df",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm3",auto_uido,auto_gidq,0755); c(auto_qmail,"boot","binm3+df",auto_uido,auto_gidq,0755); c(auto_qmail,"doc","FAQ",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","UPGRADE",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","SENDMAIL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.alias",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.ctl",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.ids",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.maildir",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.mbox",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","INSTALL.vsm",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","TEST.deliver",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","TEST.receive",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","REMOVE.sendmail",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","REMOVE.binmail",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2alias",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2ext",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2local",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2rem",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.local2virt",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.nullclient",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.relaybad",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.relaygood",auto_uido,auto_gidq,0644); c(auto_qmail,"doc","PIC.rem2local",auto_uido,auto_gidq,0644); c(auto_qmail,"bin","qmail-queue",auto_uidq,auto_gidq,04711); c(auto_qmail,"bin","qmail-lspawn",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-start",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-getpw",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-local",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-remote",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-rspawn",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-clean",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-send",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","splogger",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-newu",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-newmrh",auto_uido,auto_gidq,0700); c(auto_qmail,"bin","qmail-pw2u",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-inject",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","predate",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","datemail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","mailsubj",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-showctl",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qread",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qstat",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-tcpto",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-tcpok",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-pop3d",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-popup",auto_uido,auto_gidq,0711); c(auto_qmail,"bin","qmail-qmqpc",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qmqpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-qmtpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qmail-smtpd",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","sendmail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","tcp-env",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qreceipt",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qsmhook",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qbiff",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","forward",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","preline",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","condredirect",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","bouncesaying",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","except",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildirmake",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildir2mbox",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","maildirwatch",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","qail",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","elq",auto_uido,auto_gidq,0755); c(auto_qmail,"bin","pinq",auto_uido,auto_gidq,0755); c(auto_qmail,"man/man5","addresses.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","addresses.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","envelopes.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","envelopes.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","maildir.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","maildir.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","mbox.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","mbox.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","dot-qmail.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","dot-qmail.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-control.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-control.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-header.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-header.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-log.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-log.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","qmail-users.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","qmail-users.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man5","tcp-environ.5",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat5","tcp-environ.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","forgeries.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","forgeries.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","qmail-limits.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","qmail-limits.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man7","qmail.7",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat7","qmail.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","forward.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","forward.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","condredirect.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","condredirect.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","bouncesaying.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","bouncesaying.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","except.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","except.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildirmake.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildirmake.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildir2mbox.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildir2mbox.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","maildirwatch.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","maildirwatch.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","mailsubj.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","mailsubj.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","qreceipt.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","qreceipt.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","qbiff.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","qbiff.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","preline.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","preline.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man1","tcp-env.1",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat1","tcp-env.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-local.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-local.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-lspawn.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-lspawn.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-getpw.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-getpw.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-remote.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-remote.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-rspawn.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-rspawn.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-clean.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-clean.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-send.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-send.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-start.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-start.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","splogger.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","splogger.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-queue.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-queue.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-inject.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-inject.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-showctl.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-showctl.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-newmrh.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-newmrh.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-newu.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-newu.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-pw2u.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-pw2u.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qread.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qread.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qstat.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qstat.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-tcpok.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-tcpok.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-tcpto.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-tcpto.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-pop3d.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-pop3d.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-popup.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-popup.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmqpc.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmqpc.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmqpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmqpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-qmtpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-qmtpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-smtpd.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-smtpd.0",auto_uido,auto_gidq,0644); c(auto_qmail,"man/man8","qmail-command.8",auto_uido,auto_gidq,0644); c(auto_qmail,"man/cat8","qmail-command.0",auto_uido,auto_gidq,0644); } netqmail-1.06/open_append.c0000644000076400007640000000023606541176434015307 0ustar nelsonnelson#include #include #include "open.h" int open_append(fn) char *fn; { return open(fn,O_WRONLY | O_NDELAY | O_APPEND | O_CREAT,0600); } netqmail-1.06/coe.h0000644000076400007640000000006706541176434013574 0ustar nelsonnelson#ifndef COE_H #define COE_H extern int coe(); #endif netqmail-1.06/token822.c0000644000076400007640000002622406541176434014400 0ustar nelsonnelson#include "stralloc.h" #include "alloc.h" #include "str.h" #include "token822.h" #include "gen_allocdefs.h" static struct token822 comma = { TOKEN822_COMMA }; void token822_reverse(ta) token822_alloc *ta; { int i; int n; struct token822 temp; n = ta->len - 1; for (i = 0;i + i < n;++i) { temp = ta->t[i]; ta->t[i] = ta->t[n - i]; ta->t[n - i] = temp; } } GEN_ALLOC_ready(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_ready) GEN_ALLOC_readyplus(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_readyplus) GEN_ALLOC_append(token822_alloc,struct token822,t,len,a,i,n,x,30,token822_readyplus,token822_append) static int needspace(t1,t2) int t1; int t2; { if (!t1) return 0; if (t1 == TOKEN822_COLON) return 1; if (t1 == TOKEN822_COMMA) return 1; if (t2 == TOKEN822_LEFT) return 1; switch(t1) { case TOKEN822_ATOM: case TOKEN822_LITERAL: case TOKEN822_QUOTE: case TOKEN822_COMMENT: switch(t2) { case TOKEN822_ATOM: case TOKEN822_LITERAL: case TOKEN822_QUOTE: case TOKEN822_COMMENT: return 1; } } return 0; } static int atomok(ch) char ch; { switch(ch) { case ' ': case '\t': case '\r': case '\n': case '(': case '[': case '"': case '<': case '>': case ';': case ':': case '@': case ',': case '.': return 0; } return 1; } static void atomcheck(t) struct token822 *t; { int i; char ch; for (i = 0;i < t->slen;++i) { ch = t->s[i]; if ((ch < 32) || (ch > 126) || (ch == ')') || (ch == ']') || (ch == '\\')) { t->type = TOKEN822_QUOTE; return; } } } int token822_unparse(sa,ta,linelen) stralloc *sa; token822_alloc *ta; unsigned int linelen; { struct token822 *t; int len; int ch; int i; int j; int lasttype; int newtype; char *s; char *lineb; char *linee; len = 0; lasttype = 0; for (i = 0;i < ta->len;++i) { t = ta->t + i; newtype = t->type; if (needspace(lasttype,newtype)) ++len; lasttype = newtype; switch(newtype) { case TOKEN822_COMMA: len += 3; break; case TOKEN822_AT: case TOKEN822_DOT: case TOKEN822_LEFT: case TOKEN822_RIGHT: case TOKEN822_SEMI: case TOKEN822_COLON: ++len; break; case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: case TOKEN822_COMMENT: if (t->type != TOKEN822_ATOM) len += 2; for (j = 0;j < t->slen;++j) switch(ch = t->s[j]) { case '"': case '[': case ']': case '(': case ')': case '\\': case '\r': case '\n': ++len; default: ++len; } break; } } len += 2; if (!stralloc_ready(sa,len)) return -1; s = sa->s; lineb = s; linee = 0; lasttype = 0; for (i = 0;i < ta->len;++i) { t = ta->t + i; newtype = t->type; if (needspace(lasttype,newtype)) *s++ = ' '; lasttype = newtype; switch(newtype) { case TOKEN822_COMMA: *s++ = ','; #define NSUW \ s[0] = '\n'; s[1] = ' '; \ if (linee && (!linelen || (s - lineb <= linelen))) \ { while (linee < s) { linee[0] = linee[2]; ++linee; } linee -= 2; } \ else { if (linee) lineb = linee + 1; linee = s; s += 2; } NSUW break; case TOKEN822_AT: *s++ = '@'; break; case TOKEN822_DOT: *s++ = '.'; break; case TOKEN822_LEFT: *s++ = '<'; break; case TOKEN822_RIGHT: *s++ = '>'; break; case TOKEN822_SEMI: *s++ = ';'; break; case TOKEN822_COLON: *s++ = ':'; break; case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: case TOKEN822_COMMENT: if (t->type == TOKEN822_QUOTE) *s++ = '"'; if (t->type == TOKEN822_LITERAL) *s++ = '['; if (t->type == TOKEN822_COMMENT) *s++ = '('; for (j = 0;j < t->slen;++j) switch(ch = t->s[j]) { case '"': case '[': case ']': case '(': case ')': case '\\': case '\r': case '\n': *s++ = '\\'; default: *s++ = ch; } if (t->type == TOKEN822_QUOTE) *s++ = '"'; if (t->type == TOKEN822_LITERAL) *s++ = ']'; if (t->type == TOKEN822_COMMENT) *s++ = ')'; break; } } NSUW --s; sa->len = s - sa->s; return 1; } int token822_unquote(sa,ta) stralloc *sa; token822_alloc *ta; { struct token822 *t; int len; int i; int j; char *s; len = 0; for (i = 0;i < ta->len;++i) { t = ta->t + i; switch(t->type) { case TOKEN822_COMMA: case TOKEN822_AT: case TOKEN822_DOT: case TOKEN822_LEFT: case TOKEN822_RIGHT: case TOKEN822_SEMI: case TOKEN822_COLON: ++len; break; case TOKEN822_LITERAL: len += 2; case TOKEN822_ATOM: case TOKEN822_QUOTE: len += t->slen; } } if (!stralloc_ready(sa,len)) return -1; s = sa->s; for (i = 0;i < ta->len;++i) { t = ta->t + i; switch(t->type) { case TOKEN822_COMMA: *s++ = ','; break; case TOKEN822_AT: *s++ = '@'; break; case TOKEN822_DOT: *s++ = '.'; break; case TOKEN822_LEFT: *s++ = '<'; break; case TOKEN822_RIGHT: *s++ = '>'; break; case TOKEN822_SEMI: *s++ = ';'; break; case TOKEN822_COLON: *s++ = ':'; break; case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: if (t->type == TOKEN822_LITERAL) *s++ = '['; for (j = 0;j < t->slen;++j) *s++ = t->s[j]; if (t->type == TOKEN822_LITERAL) *s++ = ']'; break; case TOKEN822_COMMENT: break; } } sa->len = s - sa->s; return 1; } int token822_parse(ta,sa,buf) token822_alloc *ta; stralloc *sa; stralloc *buf; { int i; int salen; int level; struct token822 *t; int numtoks; int numchars; char *cbuf; salen = sa->len; numchars = 0; numtoks = 0; for (i = 0;i < salen;++i) switch(sa->s[i]) { case '.': case ',': case '@': case '<': case '>': case ':': case ';': ++numtoks; break; case ' ': case '\t': case '\r': case '\n': break; case ')': case ']': return 0; /* other control chars and non-ASCII chars are also bad, in theory */ case '(': level = 1; while (level) { if (++i >= salen) return 0; switch(sa->s[i]) { case '(': ++level; break; case ')': --level; break; case '\\': if (++i >= salen) return 0; default: ++numchars; } } ++numtoks; break; case '"': level = 1; while (level) { if (++i >= salen) return 0; switch(sa->s[i]) { case '"': --level; break; case '\\': if (++i >= salen) return 0; default: ++numchars; } } ++numtoks; break; case '[': level = 1; while (level) { if (++i >= salen) return 0; switch(sa->s[i]) { case ']': --level; break; case '\\': if (++i >= salen) return 0; default: ++numchars; } } ++numtoks; break; default: do { if (sa->s[i] == '\\') if (++i >= salen) break; ++numchars; if (++i >= salen) break; } while (atomok(sa->s[i])); --i; ++numtoks; } if (!token822_ready(ta,numtoks)) return -1; if (!stralloc_ready(buf,numchars)) return -1; cbuf = buf->s; ta->len = numtoks; t = ta->t; for (i = 0;i < salen;++i) switch(sa->s[i]) { case '.': t->type = TOKEN822_DOT; ++t; break; case ',': t->type = TOKEN822_COMMA; ++t; break; case '@': t->type = TOKEN822_AT; ++t; break; case '<': t->type = TOKEN822_LEFT; ++t; break; case '>': t->type = TOKEN822_RIGHT; ++t; break; case ':': t->type = TOKEN822_COLON; ++t; break; case ';': t->type = TOKEN822_SEMI; ++t; break; case ' ': case '\t': case '\r': case '\n': break; case '(': t->type = TOKEN822_COMMENT; t->s = cbuf; t->slen = 0; level = 1; while (level) { ++i; /* assert: < salen */ switch(sa->s[i]) { case '(': ++level; break; case ')': --level; break; case '\\': ++i; /* assert: < salen */ default: *cbuf++ = sa->s[i]; ++t->slen; } } ++t; break; case '"': t->type = TOKEN822_QUOTE; t->s = cbuf; t->slen = 0; level = 1; while (level) { ++i; /* assert: < salen */ switch(sa->s[i]) { case '"': --level; break; case '\\': ++i; /* assert: < salen */ default: *cbuf++ = sa->s[i]; ++t->slen; } } ++t; break; case '[': t->type = TOKEN822_LITERAL; t->s = cbuf; t->slen = 0; level = 1; while (level) { ++i; /* assert: < salen */ switch(sa->s[i]) { case ']': --level; break; case '\\': ++i; /* assert: < salen */ default: *cbuf++ = sa->s[i]; ++t->slen; } } ++t; break; default: t->type = TOKEN822_ATOM; t->s = cbuf; t->slen = 0; do { if (sa->s[i] == '\\') if (++i >= salen) break; *cbuf++ = sa->s[i]; ++t->slen; if (++i >= salen) break; } while (atomok(sa->s[i])); atomcheck(t); --i; ++t; } return 1; } static int gotaddr(taout,taaddr,callback) token822_alloc *taout; token822_alloc *taaddr; int (*callback)(); { int i; if (callback(taaddr) != 1) return 0; if (!token822_readyplus(taout,taaddr->len)) return 0; for (i = 0;i < taaddr->len;++i) taout->t[taout->len++] = taaddr->t[i]; taaddr->len = 0; return 1; } int token822_addrlist(taout,taaddr,ta,callback) token822_alloc *taout; token822_alloc *taaddr; token822_alloc *ta; int (*callback)(); { struct token822 *t; struct token822 *beginning; int ingroup; int wordok; taout->len = 0; taaddr->len = 0; if (!token822_readyplus(taout,1)) return -1; if (!token822_readyplus(taaddr,1)) return -1; ingroup = 0; wordok = 1; beginning = ta->t + 2; t = ta->t + ta->len - 1; /* rfc 822 address lists are easy to parse from right to left */ #define FLUSH if (taaddr->len) if (!gotaddr(taout,taaddr,callback)) return -1; #define FLUSHCOMMA if (taaddr->len) { \ if (!gotaddr(taout,taaddr,callback)) return -1; \ if (!token822_append(taout,&comma)) return -1; } #define ADDRLEFT if (!token822_append(taaddr,t--)) return -1; #define OUTLEFT if (!token822_append(taout,t--)) return -1; while (t >= beginning) { switch(t->type) { case TOKEN822_SEMI: FLUSHCOMMA if (ingroup) return 0; ingroup = 1; wordok = 1; break; case TOKEN822_COLON: FLUSH if (!ingroup) return 0; ingroup = 0; while ((t >= beginning) && (t->type != TOKEN822_COMMA)) OUTLEFT if (t >= beginning) OUTLEFT wordok = 1; continue; case TOKEN822_RIGHT: FLUSHCOMMA OUTLEFT while ((t >= beginning) && (t->type != TOKEN822_LEFT)) ADDRLEFT /* important to use address here even if it's empty: <> */ if (!gotaddr(taout,taaddr,callback)) return -1; if (t < beginning) return 0; OUTLEFT while ((t >= beginning) && ((t->type == TOKEN822_COMMENT) || (t->type == TOKEN822_ATOM) || (t->type == TOKEN822_QUOTE) || (t->type == TOKEN822_AT) || (t->type == TOKEN822_DOT))) OUTLEFT wordok = 0; continue; case TOKEN822_ATOM: case TOKEN822_QUOTE: case TOKEN822_LITERAL: if (!wordok) FLUSHCOMMA wordok = 0; ADDRLEFT continue; case TOKEN822_COMMENT: /* comment is lexically a space; shouldn't affect wordok */ break; case TOKEN822_COMMA: FLUSH wordok = 1; break; default: wordok = 1; ADDRLEFT continue; } OUTLEFT } FLUSH ++t; while (t > ta->t) if (!token822_append(taout,--t)) return -1; token822_reverse(taout); return 1; } netqmail-1.06/FAQ0000644000076400007640000005577710724070436013222 0ustar nelsonnelsonSee http://cr.yp.to/qmail/faq.html for newer FAQs not included in this document, and http://qmail.org/ for qmail community contributions. 1. Controlling the appearance of outgoing messages 1.1. How do I set up host masquerading? 1.2. How do I set up user masquerading? 1.3. How do I set up Mail-Followup-To automatically? 2. Routing outgoing messages 2.1. How do I send local messages to another host? 2.2. How do I set up a null client? 2.3. How do I send outgoing mail through UUCP? 2.4. How do I set up a separate queue for a SLIP/PPP link? 2.5. How do I deal with ``CNAME lookup failed temporarily''? 3. Routing incoming messages by host 3.1. How do I receive mail for another host name? 3.2. How do I set up a virtual domain? 3.3. How do I set up several virtual domains for one user? 4. Routing incoming messages by user 4.1. How do I forward unrecognized usernames to another host? 4.2. How do I set up a mailing list? 4.3. How do I use majordomo with qmail? 4.4. How do I use procmail with qmail? 4.5. How do I use elm's filter with qmail? 4.6. How do I create aliases with dots? 4.7. How do I use sendmail's .forward files with qmail? 4.8. How do I use sendmail's /etc/aliases with qmail? 4.9. How do I make qmail defer messages during NFS or NIS outages? 4.10. How do I change which account controls an address? 5. Setting up servers 5.1. How do I run qmail-smtpd under tcpserver? 5.2. How do I set up qmail-qmtpd? 5.3. How do I set up qmail-pop3d? 5.4. How do I allow selected clients to use this host as a relay? 5.5. How do I fix up messages from broken SMTP clients? 5.6. How do I set up qmail-qmqpd? 6. Configuring MUAs to work with qmail 6.1. How do I make BSD mail generate a Date with the local time zone? 6.2. How do I make pine work with qmail? 6.3. How do I make MH work with qmail? 6.4. How do I stop Sun's dtcm from hanging? 7. Managing the mail system 7.1. How do I safely stop qmail-send? 7.2. How do I manually run the queue? 7.3. How do I rejuvenate a message? 7.4. How do I organize a big network? 7.5. How do I back up and restore the queue disk? 7.6. How do I run a supervised copy of qmail? 7.7. How do I avoid syslog? 8. Miscellany 8.1. How do I tell qmail to do more deliveries at once? 8.2. How do I keep a copy of all incoming and outgoing mail messages? 8.3. How do I switch slowly from sendmail to qmail? 1. Controlling the appearance of outgoing messages 1.1. How do I set up host masquerading? All the users on this host, zippy.af.mil, are users on af.mil. When joe sends a message to fred, the message should say ``From: joe@af.mil'' and ``To: fred@af.mil'', without ``zippy'' anywhere. Answer: echo af.mil > /var/qmail/control/defaulthost; chmod 644 /var/qmail/control/defaulthost. 1.2. How do I set up user masquerading? I'd like my own From lines to show boss@af.mil rather than god@heaven.af.mil. Answer: Add MAILHOST=af.mil and MAILUSER=boss to your environment. To override From lines supplied by your MUA, add QMAILINJECT=f to your environment. 1.3. How do I set up Mail-Followup-To automatically? When I send a message to the sos@heaven.af.mil mailing list, I'd like to include ``Mail-Followup-To: sos@heaven.af.mil''. Answer: Add QMAILMFTFILE=$HOME/.lists to your environment, and put sos@heaven.af.mil into ~/.lists. 2. Routing outgoing messages 2.1. How do I send local messages to another host? All the mail for af.mil should be delivered to our disk server, pokey.af.mil. I've set up an MX from af.mil to pokey.af.mil, but when a user on the af.mil host sends a message to boss@af.mil, af.mil tries to deliver it locally. How do I stop that? Answer: Remove af.mil from /var/qmail/control/locals. If qmail-send is running, give it a HUP. Make sure the MX is set up properly before you do this. Also make sure that pokey can receive mail for af.mil---see question 3.1. 2.2. How do I set up a null client? I'd like zippy.af.mil to send all mail to bigbang.af.mil. Answer: echo :bigbang.af.mil > /var/qmail/control/smtproutes; chmod 644 /var/qmail/control/smtproutes. Disable local delivery as in question 2.1. Turn off qmail-smtpd in /etc/inetd.conf. 2.3. How do I send outgoing mail through UUCP? I need qmail to send all outgoing mail via UUCP to my upstream UUCP site, gonzo. Answer: Put :alias-uucp into control/virtualdomains and |preline -df /usr/bin/uux - -r -gC -a"${SENDER:-MAILER-DAEMON}" gonzo!rmail "($DEFAULT@$HOST)" (all on one line) into ~alias/.qmail-uucp-default. (For some UUCP software you will need to use -d instead of -df.) If qmail-send is running, give it a HUP. 2.4. How do I set up a separate queue for a SLIP/PPP link? Answer: Use serialmail (http://pobox.com/~djb/serialmail.html). 2.5. How do I deal with ``CNAME lookup failed temporarily''? The log showed that a message was deferred for this reason. Why is qmail doing CNAME lookups, anyway? Answer: The SMTP standard does not permit aliased hostnames, so qmail has to do a CNAME lookup in DNS for every recipient host. If the relevant DNS server is down, qmail defers the message. It will try again soon. 3. Routing incoming messages by host 3.1. How do I receive mail for another host name? I'd like our disk server, pokey.af.mil, to receive mail addressed to af.mil. I've set up an MX from af.mil to pokey.af.mil, but how do I get pokey to treat af.mil as a name for the local host? Answer: Add af.mil to /var/qmail/control/locals and to /var/qmail/control/rcpthosts. If qmail-send is running, give it a HUP (or do svc -h /var/run/qmail if qmail is supervised). 3.2. How do I set up a virtual domain? I'd like any mail for nowhere.mil, including root@nowhere.mil and postmaster@nowhere.mil and so on, to be delivered to Bob. I've set up the MX already. Answer: Put nowhere.mil:bob into control/virtualdomains. Add nowhere.mil to control/rcpthosts. If qmail-send is running, give it a HUP (or do svc -h /var/run/qmail if qmail is supervised). Now mail for whatever@nowhere.mil will be delivered locally to bob-whatever. Bob can set up ~bob/.qmail-default to catch all the possible addresses, ~bob/.qmail-info to catch info@nowhere.mil, etc. 3.3. How do I set up several virtual domains for one user? Bob wants another virtual domain, everywhere.org, but he wants to handle nowhere.mil users and everywhere.org users differently. How can we do that without setting up a second account? Answer: Put two lines into control/virtualdomains: nowhere.mil:bob-nowhere everywhere.org:bob-everywhere Add nowhere.mil and everywhere.org to control/rcpthosts. If qmail-send is running, give it a HUP (or do svc -h /var/run/qmail if qmail is supervised). Now Bob can set up separate .qmail-nowhere-* and everywhere-* files. He can even set up .qmail-nowhere-default and .qmail-everywhere-default. 4. Routing incoming messages by user 4.1. How do I forward unrecognized usernames to another host? I'd like to set up a LUSER_RELAY pointing at bigbang.af.mil. Answer: Put | forward "$LOCAL"@bigbang.af.mil into ~alias/.qmail-default. 4.2. How do I set up a mailing list? I'd like me-sos@my.host.name to be forwarded to a bunch of people. Answer: Put a list of addresses into ~me/.qmail-sos, one per line. Then incoming mail for me-sos will be forwarded to each of those addresses. You should also touch ~me/.qmail-sos-owner so that bounces come back to you rather than the original sender. Alternative: ezmlm (http://pobox.com/~djb/ezmlm.html) is a modern mailing list manager, supporting automatic subscriptions, confirmations, archives, fully automatic bounce handling (including warnings to subscribers saying which messages they've missed), and more. 4.3. How do I use majordomo with qmail? Answer: See ftp://ftp.eyrie.org/pub/software/majordomo/mjqmail and http://www.qmail.org for various methods. majordomo 2.0 is expected to support qmail directly. Beware that majordomo's lists are not crashproof. 4.4. How do I use procmail with qmail? Answer: Put | preline procmail into ~/.qmail. You'll have to use a full path for procmail unless procmail is in the system's startup PATH. Note that procmail will try to deliver to /var/spool/mail/$USER by default; to change this, see INSTALL.mbox. 4.5. How do I use elm's filter with qmail? Answer: Put | preline filter into ~/.qmail. You'll have to use a full path for filter unless filter is in the system's startup PATH. 4.6. How do I create aliases with dots? I tried setting up ~alias/.qmail-P.D.Q.Bach, but it doesn't do anything. Answer: Use .qmail-p:d:q:bach. Dots are converted to colons, and uppercase is converted to lowercase. 4.7. How do I use sendmail's .forward files with qmail? Answer: Install the dot-forward package (http://pobox.com/~djb/dot-forward.html). 4.8. How do I use sendmail's /etc/aliases with qmail? Answer: Install the fastforward package (http://pobox.com/~djb/fastforward.html). 4.9. How do I make qmail defer messages during NFS or NIS outages? If ~joe suddenly disappears, I'd like mail for joe to be deferred. Answer: Build a qmail-users database, so that qmail no longer checks home directories and the password database. This takes three steps. First, put your complete user list (including local and NIS passwords) into /var/qmail/users/passwd. Second, run # qmail-pw2u -h < /var/qmail/users/passwd > /var/qmail/users/assign Here -h means that every user must have a home directory; if you happen to run qmail-pw2u during an NFS outage, it will print an error message and stop. Third, run # qmail-newu Make sure to rebuild the database whenever you change your user list. 4.10. How do I change which account controls an address? I set up ~alias/.qmail-www, but qmail is looking at ~www/.qmail instead. Answer: If you do # chown root ~www then qmail will no longer consider www to be a user; see qmail-getpw.0. For more precise control over address assignments, see qmail-users.0. 5. Setting up servers 5.1. How do I run qmail-smtpd under tcpserver? inetd is barfing at high loads, cutting off service for ten-minute stretches. I'd also like better connection logging. Answer: First, install the tcpserver program, part of the ucspi-tcp package (http://pobox.com/~djb/ucspi-tcp.html). Second, remove the smtp line from /etc/inetd.conf, and put the line tcpserver -u 7770 -g 2108 0 smtp /var/qmail/bin/qmail-smtpd & into your system startup files. Replace 7770 with your qmaild uid, and replace 2108 with your nofiles gid. Don't forget the &. The change will take effect at your next reboot. By default, tcpserver allows at most 40 simultaneous qmail-smtpd processes. To raise this limit to 400, use tcpserver -c 400. To keep track of who's connecting and for how long, run (on two lines) tcpserver -v -u 7770 -g 2108 0 smtp /var/qmail/bin/qmail-smtpd \ 2>&1 | /var/qmail/bin/splogger smtpd 3 & 5.2. How do I set up qmail-qmtpd? Answer: Two steps. First, put a qmtp 209/tcp line into /etc/services. Second, put (all on one line) qmtp stream tcp nowait qmaild /var/qmail/bin/tcp-env tcp-env /var/qmail/bin/qmail-qmtpd into /etc/inetd.conf, and give inetd a HUP. If you have tcpserver installed, skip the inetd step, and set up tcpserver -u 7770 -g 2108 0 qmtp /var/qmail/bin/qmail-qmtpd & replacing 7770 and 2108 with the qmaild uid and nofiles gid. See question 5.1 for more details on tcpserver. 5.3. How do I set up qmail-pop3d? My old POP server works with mbox delivery; I'd like to switch to maildir delivery. Answer: Four steps. First, install the checkpassword program (http://pobox.com/~djb/checkpwd.html). Second, make sure you have a pop3 110/tcp line in /etc/services. Third, put (all on one line, including qmail-popup twice) pop3 stream tcp nowait root /var/qmail/bin/qmail-popup qmail-popup YOURHOST /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir into /etc/inetd.conf, and give inetd a HUP; replace YOURHOST with your host's fully qualified domain name. Fourth, set up Maildir delivery for any user who wants to read mail via POP. If you have tcpserver installed, skip the inetd step, and set up (on two lines) tcpserver 0 pop3 /var/qmail/bin/qmail-popup YOURHOST \ /bin/checkpassword /var/qmail/bin/qmail-pop3d Maildir & replacing YOURHOST with your host's fully qualified domain name. See question 5.1 for more details on tcpserver. Security note: pop3d should be used only within a secure network; otherwise an eavesdropper can steal passwords. 5.4. How do I allow selected clients to use this host as a relay? I see that qmail-smtpd rejects messages to any host not listed in control/rcpthosts. Answer: Three steps. First, install tcp-wrappers, available separately, including hosts_options. Second, change your qmail-smtpd line in inetd.conf to smtp stream tcp nowait qmaild /usr/local/bin/tcpd /var/qmail/bin/tcp-env /var/qmail/bin/qmail-smtpd (all on one line) and give inetd a HUP. Third, in tcpd's hosts.allow, make a line setting the environment variable RELAYCLIENT to the empty string for the selected clients: tcp-env: 1.2.3.4, 1.2.3.5: setenv = RELAYCLIENT Here 1.2.3.4 and 1.2.3.5 are the clients' IP addresses. qmail-smtpd ignores control/rcpthosts when RELAYCLIENT is set. (It also appends RELAYCLIENT to each envelope recipient address. See question 5.5 for an application.) Alternative procedure, if you are using tcpserver 0.80 or above: Create /etc/tcp.smtp containing 1.2.3.6:allow,RELAYCLIENT="" 127.:allow,RELAYCLIENT="" to allow clients with IP addresses 1.2.3.6 and 127.*. Run tcprules /etc/tcp.smtp.cdb /etc/tcp.smtp.tmp < /etc/tcp.smtp Finally, insert -x /etc/tcp.smtp.cdb after tcpserver in your qmail-smtpd invocation. 5.5. How do I fix up messages from broken SMTP clients? Answer: Three steps. First, put | bouncesaying 'Permission denied' [ "@$HOST" != "@fixme" ] | qmail-inject -f "$SENDER" -- "$DEFAULT" into ~alias/.qmail-fixup-default. Second, put fixme:fixup into /var/qmail/control/virtualdomains, and give qmail-send a HUP. Third, follow the procedure in question 5.4, but set RELAYCLIENT to the string ``@fixme'': tcp-env: 1.2.3.6, 1.2.3.7: setenv = RELAYCLIENT @fixme Here 1.2.3.6 and 1.2.3.7 are the clients' IP addresses. If you are using tcpserver instead of inetd and tcpd, put 1.2.3.6:allow,RELAYCLIENT="@fixme" 1.2.3.7:allow,RELAYCLIENT="@fixme" into /etc/tcp.smtp, and run tcprules as in question 5.4. 5.6. How do I set up qmail-qmqpd? I'd like to allow fast queueing of outgoing mail from authorized clients. Answer: Make sure you have installed tcpserver 0.80 or above. Create /etc/qmqp.tcp in tcprules format to allow connections from authorized hosts. For example, if queueing is allowed from 1.2.3.*: 1.2.3.:allow :deny Convert /etc/qmqp.tcp to /etc/qmqp.cdb: tcprules /etc/qmqp.cdb /etc/qmqp.tmp < /etc/qmqp.tcp Finally, set up tcpserver -x /etc/qmqp.cdb -u 7770 -g 2108 0 628 /var/qmail/bin/qmail-qmqpd & replacing 7770 and 2108 with the qmaild uid and nofiles gid. See question 5.1 for more details on tcpserver. 6. Configuring MUAs to work with qmail 6.1. How do I make BSD mail generate a Date with the local time zone? When I send mail, I'd rather use the local time zone than GMT, since some MUAs don't know how to display Date in the receiver's time zone. Answer: Put set sendmail=/var/qmail/bin/datemail into your .mailrc or your system-wide Mail.rc. Beware that BSD mail is neither secure nor reliable. 6.2. How do I make pine work with qmail? Answer: Put sendmail-path=/usr/lib/sendmail -oem -oi -t into /usr/local/lib/pine.conf. (This will work with sendmail too.) Beware that pine is neither secure nor reliable. 6.3. How do I make MH work with qmail? Answer: Put postproc: /usr/mh/lib/spost into each user's .mh_profile. (This will work with sendmail too.) Beware that MH is neither secure nor reliable. 6.4. How do I stop Sun's dtcm from hanging? Answer: There is a novice programming error in dtcm, known as ``failure to close the output side of the pipe in the child.'' Sun has, at the time of this writing, not yet provided a patch. Sorry. 7. Managing the mail system 7.1. How do I safely stop qmail-send? Back when we were running sendmail, it was always tricky to kill sendmail without risking the loss of current deliveries; what should I do with qmail-send? Answer: Go ahead and kill the qmail-send process. It will shut down cleanly. Wait for ``exiting'' to show up in the log. To restart qmail, run /var/qmail/rc the same way it is run from your system boot scripts, with the proper PATH, resource limits, etc. Alternative, if qmail is supervised: svc -t /var/run/qmail. The supervise process will kill qmail, wait for it to stop, and restart it. Use -d instead of -t if you don't want qmail to restart automatically; to manually restart it, use -u. 7.2. How do I manually run the queue? I'd like qmail to try delivering all the remote messages right now. Answer: Give the qmail-send process an ALRM. (Do svc -a /var/run/qmail if qmail is supervised.) You may want to run qmail-tcpok first, to guarantee that qmail-remote will try all addresses. Normally, if an address fails repeatedly, qmail-remote leaves it alone for an hour. 7.3. How do I rejuvenate a message? Somebody broke into Eric's computer again; it's going to be down for at least another two days. I know Eric has been expecting an important message---in fact, I see it sitting here in /var/qmail/queue/mess/15/26902. It's been in the queue for six days; how can I make sure it isn't bounced tomorrow? Answer: Just touch /var/qmail/queue/info/15/26902. (This is the only form of queue modification that's safe while qmail is running.) 7.4. How do I organize a big network? I have a lot of machines, and I don't know where to start. Answer: First, choose the domain name where your users will receive mail. This is normally the shortest domain name you control. If you are in charge of *.movie.edu, you can use addresses like joe@movie.edu. Second, choose the machine that will know what to do with different users at movie.edu. Set up a host name in DNS for this machine: mailhost.movie.edu IN A 1.2.3.4 4.3.2.1.in-addr.arpa IN PTR mailhost.movie.edu Here 1.2.3.4 is the IP address of that machine. Third, make a list of machines where mail should end up. For example, if mail for Bob should end up on Bob's workstation, put Bob's workstation onto the list. For each of these machines, set up a host name in DNS: bobshost.movie.edu IN A 1.2.3.7 7.3.2.1.in-addr.arpa IN PTR bobshost.movie.edu Fourth, install qmail on bobshost.movie.edu. qmail will automatically configure itself to accept messages for bob@bobshost.movie.edu and deliver them to ~bob/Mailbox on bobshost. Do the same for the other machines where mail should end up. Fifth, install qmail on mailhost.movie.edu. Put movie.edu:alias-movie into control/virtualdomains on mailhost. Then forward bob@movie.edu to bob@bobshost.movie.edu, by putting bob@bobshost.movie.edu into ~alias/.qmail-movie-bob. Do the same for other users. Sixth, put movie.edu into control/rcpthosts on mailhost.movie.edu, so that mailhost.movie.edu will accept messages for users at movie.edu. Seventh, set up an MX record in DNS to deliver movie.edu messages to mailhost: movie.edu IN MX 10 mailhost.movie.edu Eighth, on all your machines, put movie.edu into control/defaulthost. 7.5. How do I back up and restore the queue disk? Answer: You can't. One difficulty is that you can't get a consistent snapshot of the queue while qmail-send is running. Another difficulty is that messages in the queue must have filenames that match their inode numbers. However, the big problem is that backups---even twice-daily backups--- are far too unreliable for mail. If your disk dies, there will be very little overlap between the messages saved in the last backup and the messages that were lost. There are several ways to add real reliability to a mail server. Battery backups will keep your server alive, letting you park the disk to avoid a head crash, when the power goes out. Solid-state disks have their own battery backups. RAID boxes let you replace dead disks without losing any data. 7.6. How do I run a supervised copy of qmail? svc sounds useful. Answer: Install daemontools (http://pobox.com/~djb/daemontools.html). Create a /var/run/qmail directory. Change /var/qmail/rc to supervise /var/run/qmail /var/qmail/rc in your boot scripts. Make sure that supervise is in the startup PATH. Now you can use svc to stop or restart qmail, and svstat to check whether qmail is running. 7.7. How do I avoid syslog? It chews up a lot of CPU time and isn't reliable. Answer: Install daemontools (http://pobox.com/~djb/daemontools.html). Make a /var/log/qmail directory, owned by qmaill, mode 2700. Do qmail-start ./Mailbox /usr/local/bin/accustamp \ | setuser qmaill /usr/local/bin/cyclog /var/log/qmail & in /var/qmail/rc. If you are logging tcpserver connections, make a /var/log/smtpd directory, and use cyclog /var/log/smtpd for tcpserver. You shouldn't run several copies of cyclog with the same log directory. By default, cyclog keeps 10 automatically rotated log files, each containing up to 100KB of log data. To keep 20 files with 1MB each, use cyclog -s 1000000 -n 20. 8. Miscellany 8.1. How do I tell qmail to do more deliveries at once? It's running only 20 parallel qmail-remote processes. Answer: Decide how many deliveries you want to allow at once. Put that number into control/concurrencyremote. Restart qmail-send as in question 7.1. If your system has resource limits, make sure you set the descriptors limit to at least double the concurrency plus 5; otherwise you'll get lots of unnecessary deferrals whenever a big burst of mail shows up. Note that qmail also imposes a compile-time concurrency limit, 120 by default; this is set in conf-spawn. 8.2. How do I keep a copy of all incoming and outgoing mail messages? Answer: Set QUEUE_EXTRA to "Tlog\0" and QUEUE_EXTRALEN to 5 in extra.h. Recompile qmail. Put ./msg-log into ~alias/.qmail-log. You can also use QUEUE_EXTRA to, e.g., record the Message-ID of every message: run | awk '/^$/ { exit } /^[mM][eE][sS][sS][aA][gG][eE]-/ { print }' from ~alias/.qmail-log. 8.3. How do I switch slowly from sendmail to qmail? I'm thinking of moving the heaven.af.mil network over to qmail, but first I'd like to give my users a chance to try out qmail without affecting current sendmail deliveries. We're using NFS. Answer: Find a host in your network, say pc.heaven.af.mil, that isn't running an SMTP server. (If addresses at pc.heaven.af.mil are used, you should already have an MX pointing pc.heaven.af.mil to your mail hub.) Set up a new MX record pointing lists.heaven.af.mil to pc.heaven.af.mil. Install qmail on pc.heaven.af.mil. Replace pc with lists in the control files. Make the qmail man pages available on all your machines. Now tell your users about qmail. A user can forward joe@heaven.af.mil to joe@lists.heaven.af.mil to get ~/Mailbox delivery; he can set up .qmail files; he can start running his own mailing lists @lists.heaven.af.mil. When you're ready to turn sendmail off, you can set up pc.heaven.af.mil as your new mail hub. Add heaven.af.mil to control/locals, and change the heaven.af.mil MX to point to pc.heaven.af.mil. Make sure you leave lists.heaven.af.mil in control/locals so that transition addresses will continue to work. netqmail-1.06/subfdins.c0000644000076400007640000000053206541176434014633 0ustar nelsonnelson#include "readwrite.h" #include "substdio.h" #include "subfd.h" int subfd_readsmall(fd,buf,len) int fd; char *buf; int len; { if (substdio_flush(subfdoutsmall) == -1) return -1; return read(fd,buf,len); } char subfd_inbufsmall[256]; static substdio it = SUBSTDIO_FDBUF(subfd_readsmall,0,subfd_inbufsmall,256); substdio *subfdinsmall = ⁢ netqmail-1.06/getln.c0000644000076400007640000000057606541176434014137 0ustar nelsonnelson#include "substdio.h" #include "byte.h" #include "stralloc.h" #include "getln.h" int getln(ss,sa,match,sep) register substdio *ss; register stralloc *sa; int *match; int sep; { char *cont; unsigned int clen; if (getln2(ss,sa,&cont,&clen,sep) == -1) return -1; if (!clen) { *match = 0; return 0; } if (!stralloc_catb(sa,cont,clen)) return -1; *match = 1; return 0; } netqmail-1.06/install.c0000644000076400007640000001056006541176434014466 0ustar nelsonnelson#include "substdio.h" #include "strerr.h" #include "error.h" #include "open.h" #include "readwrite.h" #include "exit.h" extern void hier(); #define FATAL "install: fatal: " int fdsourcedir = -1; void h(home,uid,gid,mode) char *home; int uid; int gid; int mode; { if (mkdir(home,0700) == -1) if (errno != error_exist) strerr_die4sys(111,FATAL,"unable to mkdir ",home,": "); if (chown(home,uid,gid) == -1) strerr_die4sys(111,FATAL,"unable to chown ",home,": "); if (chmod(home,mode) == -1) strerr_die4sys(111,FATAL,"unable to chmod ",home,": "); } void d(home,subdir,uid,gid,mode) char *home; char *subdir; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (mkdir(subdir,0700) == -1) if (errno != error_exist) strerr_die6sys(111,FATAL,"unable to mkdir ",home,"/",subdir,": "); if (chown(subdir,uid,gid) == -1) strerr_die6sys(111,FATAL,"unable to chown ",home,"/",subdir,": "); if (chmod(subdir,mode) == -1) strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",subdir,": "); } void p(home,fifo,uid,gid,mode) char *home; char *fifo; int uid; int gid; int mode; { if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (fifo_make(fifo,0700) == -1) if (errno != error_exist) strerr_die6sys(111,FATAL,"unable to mkfifo ",home,"/",fifo,": "); if (chown(fifo,uid,gid) == -1) strerr_die6sys(111,FATAL,"unable to chown ",home,"/",fifo,": "); if (chmod(fifo,mode) == -1) strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",fifo,": "); } char inbuf[SUBSTDIO_INSIZE]; char outbuf[SUBSTDIO_OUTSIZE]; substdio ssin; substdio ssout; void c(home,subdir,file,uid,gid,mode) char *home; char *subdir; char *file; int uid; int gid; int mode; { int fdin; int fdout; if (fchdir(fdsourcedir) == -1) strerr_die2sys(111,FATAL,"unable to switch back to source directory: "); fdin = open_read(file); if (fdin == -1) strerr_die4sys(111,FATAL,"unable to read ",file,": "); substdio_fdbuf(&ssin,read,fdin,inbuf,sizeof inbuf); if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); if (chdir(subdir) == -1) strerr_die6sys(111,FATAL,"unable to switch to ",home,"/",subdir,": "); fdout = open_trunc(file); if (fdout == -1) strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); switch(substdio_copy(&ssout,&ssin)) { case -2: strerr_die4sys(111,FATAL,"unable to read ",file,": "); case -3: strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); } close(fdin); if (substdio_flush(&ssout) == -1) strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); if (fsync(fdout) == -1) strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); if (close(fdout) == -1) /* NFS silliness */ strerr_die6sys(111,FATAL,"unable to write .../",subdir,"/",file,": "); if (chown(file,uid,gid) == -1) strerr_die6sys(111,FATAL,"unable to chown .../",subdir,"/",file,": "); if (chmod(file,mode) == -1) strerr_die6sys(111,FATAL,"unable to chmod .../",subdir,"/",file,": "); } void z(home,file,len,uid,gid,mode) char *home; char *file; int len; int uid; int gid; int mode; { int fdout; if (chdir(home) == -1) strerr_die4sys(111,FATAL,"unable to switch to ",home,": "); fdout = open_trunc(file); if (fdout == -1) strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); substdio_fdbuf(&ssout,write,fdout,outbuf,sizeof outbuf); while (len-- > 0) if (substdio_put(&ssout,"",1) == -1) strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); if (substdio_flush(&ssout) == -1) strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); if (fsync(fdout) == -1) strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); if (close(fdout) == -1) /* NFS silliness */ strerr_die6sys(111,FATAL,"unable to write ",home,"/",file,": "); if (chown(file,uid,gid) == -1) strerr_die6sys(111,FATAL,"unable to chown ",home,"/",file,": "); if (chmod(file,mode) == -1) strerr_die6sys(111,FATAL,"unable to chmod ",home,"/",file,": "); } void main() { fdsourcedir = open_read("."); if (fdsourcedir == -1) strerr_die2sys(111,FATAL,"unable to open current directory: "); umask(077); hier(); _exit(0); } netqmail-1.06/qmail-newmrh.c0000644000076400007640000000330606541176434015421 0ustar nelsonnelson#include "strerr.h" #include "stralloc.h" #include "substdio.h" #include "getln.h" #include "exit.h" #include "readwrite.h" #include "open.h" #include "auto_qmail.h" #include "cdbmss.h" #define FATAL "qmail-newmrh: fatal: " void die_read() { strerr_die2sys(111,FATAL,"unable to read control/morercpthosts: "); } void die_write() { strerr_die2sys(111,FATAL,"unable to write to control/morercpthosts.tmp: "); } char inbuf[1024]; substdio ssin; int fd; int fdtemp; struct cdbmss cdbmss; stralloc line = {0}; int match; void main() { umask(033); if (chdir(auto_qmail) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",auto_qmail,": "); fd = open_read("control/morercpthosts"); if (fd == -1) die_read(); substdio_fdbuf(&ssin,read,fd,inbuf,sizeof inbuf); fdtemp = open_trunc("control/morercpthosts.tmp"); if (fdtemp == -1) die_write(); if (cdbmss_start(&cdbmss,fdtemp) == -1) die_write(); for (;;) { if (getln(&ssin,&line,&match,'\n') != 0) die_read(); case_lowerb(line.s,line.len); while (line.len) { if (line.s[line.len - 1] == ' ') { --line.len; continue; } if (line.s[line.len - 1] == '\n') { --line.len; continue; } if (line.s[line.len - 1] == '\t') { --line.len; continue; } if (line.s[0] != '#') if (cdbmss_add(&cdbmss,line.s,line.len,"",0) == -1) die_write(); break; } if (!match) break; } if (cdbmss_finish(&cdbmss) == -1) die_write(); if (fsync(fdtemp) == -1) die_write(); if (close(fdtemp) == -1) die_write(); /* NFS stupidity */ if (rename("control/morercpthosts.tmp","control/morercpthosts.cdb") == -1) strerr_die2sys(111,FATAL,"unable to move control/morercpthosts.tmp to control/morercpthosts.cdb"); _exit(0); } netqmail-1.06/lock_exnb.c0000644000076400007640000000037406541176434014766 0ustar nelsonnelson#include #include #include #include "hasflock.h" #include "lock.h" #ifdef HASFLOCK int lock_exnb(fd) int fd; { return flock(fd,LOCK_EX | LOCK_NB); } #else int lock_exnb(fd) int fd; { return lockf(fd,2,0); } #endif netqmail-1.06/TEST.receive0000644000076400007640000000243506541176434015001 0ustar nelsonnelsonYou can do several tests of messages entering the qmail system: 1. SMTP server test: Forge some mail locally via SMTP. Replace ``me'' with your username and ``domain'' with your host's name. % telnet 127.0.0.1 25 Trying 127.0.0.1... Connected to 127.0.0.1. Escape character is '^]'. 220 domain ESMTP helo dude 250 domain mail 250 ok rcpt 250 ok data 354 go ahead Subject: testing This is a test. . 250 ok 812345679 qp 12345 quit 221 domain Connection closed by foreign host. % Look for the message in your mailbox. (Note for programmers: Most SMTP servers need more text after MAIL and RCPT. See RFC 821.) 2. Remote-local test: Send yourself some mail from another machine. Look for the message in your mailbox. 3. Remote-error test: Send some mail from another machine to nonexistent@domain. Look for a bounce message in the remote mailbox. 4. UA test: Try sending mail, first to a local account, then to a remote account, with your normal user agent. 5. Remote-postmaster test: Send mail from another machine to PoStMaStEr@domain. Look for the message in the alias mailbox, normally ~alias/Mailbox. netqmail-1.06/trysysel.c0000644000076400007640000000015606541176434014716 0ustar nelsonnelson#include #include #include /* SVR4 silliness */ void foo() { ; } netqmail-1.06/except.c0000644000076400007640000000140306541176434014304 0ustar nelsonnelson#include "fork.h" #include "strerr.h" #include "wait.h" #include "error.h" #include "exit.h" #define FATAL "except: fatal: " void main(argc,argv) int argc; char **argv; { int pid; int wstat; if (!argv[1]) strerr_die1x(100,"except: usage: except program [ arg ... ]"); pid = fork(); if (pid == -1) strerr_die2sys(111,FATAL,"unable to fork: "); if (pid == 0) { execvp(argv[1],argv + 1); if (error_temp(errno)) _exit(111); _exit(100); } if (wait_pid(&wstat,pid) == -1) strerr_die2x(111,FATAL,"wait failed"); if (wait_crashed(wstat)) strerr_die2x(111,FATAL,"child crashed"); switch(wait_exitcode(wstat)) { case 0: _exit(100); case 111: strerr_die2x(111,FATAL,"temporary child error"); default: _exit(0); } } netqmail-1.06/sig_misc.c0000644000076400007640000000047606541176434014622 0ustar nelsonnelson#include #include "sig.h" void sig_miscignore() { sig_catch(SIGVTALRM,SIG_IGN); sig_catch(SIGPROF,SIG_IGN); sig_catch(SIGQUIT,SIG_IGN); sig_catch(SIGINT,SIG_IGN); sig_catch(SIGHUP,SIG_IGN); #ifdef SIGXCPU sig_catch(SIGXCPU,SIG_IGN); #endif #ifdef SIGXFSZ sig_catch(SIGXFSZ,SIG_IGN); #endif } netqmail-1.06/stralloc.30000644000076400007640000000510006541176434014555 0ustar nelsonnelson.TH stralloc 3 .SH NAME stralloc \- dynamically allocated strings .SH SYNTAX .B #include int \fBstralloc_ready\fP(&\fIsa\fR,\fIlen\fR); .br int \fBstralloc_readyplus\fP(&\fIsa\fR,\fIlen\fR); int \fBstralloc_copy\fP(&\fIsa\fR,&\fIsa2\fR); .br int \fBstralloc_copys\fP(&\fIsa\fR,\fIbuf\fR); .br int \fBstralloc_copyb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR); int \fBstralloc_cat\fP(&\fIsa\fR,&\fIsa2\fR); .br int \fBstralloc_cats\fP(&\fIsa\fR,\fIbuf\fR); .br int \fBstralloc_catb\fP(&\fIsa\fR,\fIbuf\fR,\fIlen\fR); int \fBstralloc_append\fP(&\fIsa\fR,\fIbuf\fR); .br int \fBstralloc_0\fP(&\fIsa\fR); int \fBstralloc_starts\fP(&\fIsa\fR,\fIbuf\fR); stralloc \fIsa\fR = {0}; .br stralloc \fIsa2\fR = {0}; .br unsigned int \fIlen\fR; .br char *\fIbuf\fR; .SH DESCRIPTION A .B stralloc variable holds a string in dynamically allocated space. String length is limited only by memory. String contents are unrestricted. The .B stralloc structure has three components: .I sa\fB.s is a pointer to the string, or 0 if it is not allocated; .I sa\fB.len is the number of bytes in the string, if it is allocated; .I sa\fB.a is the number of bytes allocated for the string, if it is allocated. A .B stralloc variable should be initialized to {0}, meaning unallocated. .B stralloc_ready makes sure that .I sa has enough space allocated for .I len characters. It allocates extra space if necessary. .B stralloc_readyplus makes sure that .I sa has enough space allocated for .I len characters more than its current length. If .I sa is unallocated, .B stralloc_readyplus is the same as .BR stralloc_ready . .B stralloc_copy copies .I sa2 to .IR sa , allocating space if necessary. Here .I sa2 is an allocated .B stralloc variable. .B stralloc_copys copies a 0-terminated string, .IR buf , to .IR sa , without the 0. .B stralloc_copyb copies .I len characters from .I buf to .IR sa . .B stralloc_cat appends .I sa2 to .IR sa , allocating space if necessary. If .I sa is unallocated, .B stralloc_cat is the same as .BR stralloc_copy . .B stralloc_cats and .B stralloc_catb are analogous to .B stralloc_copys and .BR stralloc_copyb . .B stralloc_append adds a single character, .IR *buf , to .IR sa , allocating space if necessary. .B stralloc_0 adds a single 0 character to .IR sa . .B stralloc_starts returns 1 if the 0-terminated string .IR buf , without the 0, is a prefix of .IR sa . .SH "ERROR HANDLING" If a .B stralloc routine runs out of memory, it leaves .I sa alone and returns 0, setting .B errno appropriately. On success it returns 1; this guarantees that .I sa is allocated. .SH "SEE ALSO" alloc(3), error(3) netqmail-1.06/stralloc_arts.c0000644000076400007640000000030406541176434015667 0ustar nelsonnelson#include "byte.h" #include "str.h" #include "stralloc.h" int stralloc_starts(sa,s) stralloc *sa; char *s; { int len; len = str_len(s); return (sa->len >= len) && byte_equal(s,len,sa->s); } netqmail-1.06/auto_qmail.h0000644000076400007640000000011506541176434015153 0ustar nelsonnelson#ifndef AUTO_QMAIL_H #define AUTO_QMAIL_H extern char auto_qmail[]; #endif netqmail-1.06/forward.c0000644000076400007640000000247506541176434014472 0ustar nelsonnelson#include "sig.h" #include "readwrite.h" #include "exit.h" #include "env.h" #include "qmail.h" #include "strerr.h" #include "substdio.h" #include "fmt.h" #define FATAL "forward: fatal: " void die_nomem() { strerr_die2x(111,FATAL,"out of memory"); } struct qmail qqt; int mywrite(fd,buf,len) int fd; char *buf; int len; { qmail_put(&qqt,buf,len); return len; } char inbuf[SUBSTDIO_INSIZE]; char outbuf[1]; substdio ssin = SUBSTDIO_FDBUF(read,0,inbuf,sizeof inbuf); substdio ssout = SUBSTDIO_FDBUF(mywrite,-1,outbuf,sizeof outbuf); char num[FMT_ULONG]; void main(argc,argv) int argc; char **argv; { char *sender; char *dtline; char *qqx; sig_pipeignore(); sender = env_get("NEWSENDER"); if (!sender) strerr_die2x(100,FATAL,"NEWSENDER not set"); dtline = env_get("DTLINE"); if (!dtline) strerr_die2x(100,FATAL,"DTLINE not set"); if (qmail_open(&qqt) == -1) strerr_die2sys(111,FATAL,"unable to fork: "); qmail_puts(&qqt,dtline); if (substdio_copy(&ssout,&ssin) != 0) strerr_die2sys(111,FATAL,"unable to read message: "); substdio_flush(&ssout); num[fmt_ulong(num,qmail_qp(&qqt))] = 0; qmail_from(&qqt,sender); while (*++argv) qmail_to(&qqt,*argv); qqx = qmail_close(&qqt); if (*qqx) strerr_die2x(*qqx == 'D' ? 100 : 111,FATAL,qqx + 1); strerr_die2x(0,"forward: qp ",num); } netqmail-1.06/trigger.c0000644000076400007640000000114706541176434014464 0ustar nelsonnelson#include "select.h" #include "open.h" #include "trigger.h" #include "hasnpbg1.h" static int fd = -1; #ifdef HASNAMEDPIPEBUG1 static int fdw = -1; #endif void trigger_set() { if (fd != -1) close(fd); #ifdef HASNAMEDPIPEBUG1 if (fdw != -1) close(fdw); #endif fd = open_read("lock/trigger"); #ifdef HASNAMEDPIPEBUG1 fdw = open_write("lock/trigger"); #endif } void trigger_selprep(nfds,rfds) int *nfds; fd_set *rfds; { if (fd != -1) { FD_SET(fd,rfds); if (*nfds < fd + 1) *nfds = fd + 1; } } int trigger_pulled(rfds) fd_set *rfds; { if (fd != -1) if (FD_ISSET(fd,rfds)) return 1; return 0; } netqmail-1.06/cdbmake_pack.c0000644000076400007640000000026406541176434015404 0ustar nelsonnelson#include "cdbmake.h" void cdbmake_pack(buf,num) unsigned char *buf; uint32 num; { *buf++ = num; num >>= 8; *buf++ = num; num >>= 8; *buf++ = num; num >>= 8; *buf = num; } netqmail-1.06/uint32.h10000644000076400007640000000011006541176434014220 0ustar nelsonnelson#ifndef UINT32_H #define UINT32_H typedef unsigned int uint32; #endif netqmail-1.06/datetime_un.c0000644000076400007640000000124606541176434015317 0ustar nelsonnelson#include "datetime.h" /* roughly 100x faster than mktime() */ datetime_sec datetime_untai(dt) struct datetime *dt; { int year; int day; int mon; year = dt->year + 1900; mon = dt->mon; if (mon >= 2) { mon -= 2; } else { mon += 10; --year; } day = (dt->mday - 1) * 10 + 5 + 306 * mon; day /= 10; if (day == 365) { year -= 3; day = 1460; } else { day += 365 * (year % 4); } year /= 4; day += 1461 * (year % 25); year /= 25; if (day == 36524) { year -= 3; day = 146096; } else { day += 36524 * (year % 4); } year /= 4; day += 146097 * (year - 5); day += 11017; return ((day * 24 + dt->hour) * 60 + dt->min) * 60 + dt->sec; } netqmail-1.06/dnscname.c0000644000076400007640000000072406541176434014611 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "stralloc.h" #include "dns.h" #include "dnsdoe.h" #include "readwrite.h" #include "exit.h" stralloc sa = {0}; void main(argc,argv) int argc; char **argv; { if (!argv[1]) _exit(100); if (!stralloc_copys(&sa,argv[1])) { substdio_putsflush(subfderr,"out of memory\n"); _exit(111); } dns_init(0); dnsdoe(dns_cname(&sa)); substdio_putflush(subfdout,sa.s,sa.len); substdio_putsflush(subfdout,"\n"); _exit(0); } netqmail-1.06/trycpp.c0000644000076400007640000000014406541176434014336 0ustar nelsonnelsonvoid main() { #ifdef NeXT printf("nextstep\n"); exit(0); #endif printf("unknown\n"); exit(0); } netqmail-1.06/fmt.h0000644000076400007640000000124406541176434013612 0ustar nelsonnelson#ifndef FMT_H #define FMT_H #define FMT_ULONG 40 /* enough space to hold 2^128 - 1 in decimal, plus \0 */ #define FMT_LEN ((char *) 0) /* convenient abbreviation */ extern unsigned int fmt_uint(); extern unsigned int fmt_uint0(); extern unsigned int fmt_xint(); extern unsigned int fmt_nbbint(); extern unsigned int fmt_ushort(); extern unsigned int fmt_xshort(); extern unsigned int fmt_nbbshort(); extern unsigned int fmt_ulong(); extern unsigned int fmt_xlong(); extern unsigned int fmt_nbblong(); extern unsigned int fmt_plusminus(); extern unsigned int fmt_minus(); extern unsigned int fmt_0x(); extern unsigned int fmt_str(); extern unsigned int fmt_strn(); #endif netqmail-1.06/cdbmake_hash.c0000644000076400007640000000022006541176434015401 0ustar nelsonnelson#include "cdbmake.h" uint32 cdbmake_hashadd(h,c) uint32 h; unsigned int c; { h += (h << 5); h ^= (uint32) (unsigned char) c; return h; } netqmail-1.06/strerr_die.c0000644000076400007640000000154606541176434015166 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "exit.h" #include "strerr.h" void strerr_warn(x1,x2,x3,x4,x5,x6,se) char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; struct strerr *se; { strerr_sysinit(); if (x1) substdio_puts(subfderr,x1); if (x2) substdio_puts(subfderr,x2); if (x3) substdio_puts(subfderr,x3); if (x4) substdio_puts(subfderr,x4); if (x5) substdio_puts(subfderr,x5); if (x6) substdio_puts(subfderr,x6); while(se) { if (se->x) substdio_puts(subfderr,se->x); if (se->y) substdio_puts(subfderr,se->y); if (se->z) substdio_puts(subfderr,se->z); se = se->who; } substdio_puts(subfderr,"\n"); substdio_flush(subfderr); } void strerr_die(e,x1,x2,x3,x4,x5,x6,se) int e; char *x1; char *x2; char *x3; char *x4; char *x5; char *x6; struct strerr *se; { strerr_warn(x1,x2,x3,x4,x5,x6,se); _exit(e); } netqmail-1.06/mailsubj.sh0000644000076400007640000000015606541176434015016 0ustar nelsonnelsonsubject="$1" shift ( echo Subject: "$subject" echo To: ${1+"$@"} echo '' cat ) | QMAIL/bin/qmail-inject netqmail-1.06/maildirmake.c0000644000076400007640000000131106541176434015271 0ustar nelsonnelson#include "strerr.h" #include "exit.h" #define FATAL "maildirmake: fatal: " void main(argc,argv) int argc; char **argv; { umask(077); if (!argv[1]) strerr_die1x(100,"maildirmake: usage: maildirmake name"); if (mkdir(argv[1],0700) == -1) strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],": "); if (chdir(argv[1]) == -1) strerr_die4sys(111,FATAL,"unable to chdir to ",argv[1],": "); if (mkdir("tmp",0700) == -1) strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/tmp: "); if (mkdir("new",0700) == -1) strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/new: "); if (mkdir("cur",0700) == -1) strerr_die4sys(111,FATAL,"unable to mkdir ",argv[1],"/cur: "); _exit(0); } netqmail-1.06/README0000644000076400007640000003577210725610102013530 0ustar nelsonnelsonnetqmail 1.06 20071130 James Craig Burley claims copyright on the qmail-isoc patch. For more details, see COPYRIGHT. Apart from James' copyrights, no other copyright is claimed by the distributors of netqmail for changes from qmail 1.03 to netqmail 1.05. Daniel J. Bernstein has abandoned copyright for qmail 1.03. D. J. Bernstein did not participate in, nor has he been asked to approve of this distribution. With this distribution, we thank Daniel Bernstein for his dedication of qmail to the public domain. We have taken advantage of this event to remove the need to apply a patch. We will distribute a Netqmail 1.07 shortly which includes enhancements. Netqmail 1.06 is produced by this motley krewe: Russ Nelson Charles Cazabon Dave Sill Peter Samuel Henning Brauer Andrew Richards Richard Lyons John Levine Scott Gifford Kyle Wheeler Wayne Marshall qmail is a secure, reliable, efficient, simple message transfer agent. It is meant as a replacement for the entire sendmail-binmail system on typical Internet-connected UNIX hosts. See BLURB, BLURB2, BLURB3, and BLURB4 for more detailed advertisements. INSTALL says how to set up and test qmail. If you're upgrading from a previous version, read UPGRADE instead. See PIC.* for some ``end-to-end'' pictures of mail flowing through the qmail system. See http://pobox.com/~djb/qmail.html for other qmail-related software and a pointer to the qmail mailing list. Other documentation: http://pobox.com/~djb/proto.html shows solutions to several Internet mail problems; many of these solutions are implemented in qmail. CHANGES and THANKS show how qmail has changed since it was first released. SECURITY, INTERNALS, THOUGHTS, and TODO record many of the qmail design decisions. The rest of this file is a list of systypes where various versions of qmail have been reported to work. 0.96 was the final gamma version; 1.00 had exactly the same code as 0.96. To see your systype, make systype; cat systype. 1.00: a.ux-3.0-svr2-:-:-:mc68030-:- (tnx RF) 1.01: aix-3-2-:-:-:000000406300-:- (tnx DG) 1.01: aix-3-2-:-:-:000011216700-:- (tnx JLB) 1.01: aix-4-1-:-:-:000041574c00-:- (tnx M2H) 1.01: aix-4-1-:-:-:000088581000-:- (tnx HJB) 1.01: aix-4-1-:-:-:002b51134c00-:- (tnx MP) 1.00: aix-4-1-:-:-:00910033a000-:- (tnx KJJ) 1.01: aix-4-2-:-:-:000055247900-:- (tnx JLB) 1.01: aix-4-2-:-:-:000062295800-:- (tnx TD) 1.01: aix-4-2-:-:-:000136094c00-:- (tnx T2U) 1.00: aix-4-2-:-:-:000205254600-:- (tnx MGM) 1.01: aix-4-2-:-:-:005255bc4c00-:- (tnx DS) 1.01: aix-4-2-:-:-:006030944c00-:- 1.01: bsd.386-1.1-0-:i386-:-:i386-:- (tnx T2M) 1.01: bsd.os-2.0-:i386-:-:pentium-:- (tnx MSS) 1.01: bsd.os-2.0.1-:i386-:-:i486-:- (tnx KR) 0.96: bsd.os-2.1-:i386-:-:-:- (tnx DAR) 1.00: bsd.os-2.1-:i386-:-:i486-:- (tnx RJC) 0.96: bsd.os-2.1-:i386-:-:pentium-:- (tnx UO) 1.01: bsd.os-3.0-:i386-:-:-:- (tnx VU) 1.01: bsd.os-3.0-:i386-:-:pentium-:- (tnx RJO) 1.01: bsd.os-3.1-:i386-:-:pentium-:- (tnx ABC) 1.01: bsd.os-3.1-:i386-:-:pentium.ii-:- (tnx UO) 0.96: dgux-5.4r2.01-generic-:-:-:aviion-:- (tnx HWM) 1.01: freebsd-2.1.0-release-:i386-:-:i486-dx-:- (tnx VV) 1.01: freebsd-2.1.0-release-:i386-:-:i486.dx2-:- (tnx JLB) 1.00: freebsd-2.1.0-release-:i386-:-:i486dx-:- (tnx chrisj=???) 1.01: freebsd-2.1.0-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MBS) 1.01: freebsd-2.1.5-release-:i386-:-:i486-dx-:- (tnx B1F) 0.96: freebsd-2.1.5-release-:i386-:-:i486dx-:- (tnx FN) 1.01: freebsd-2.1.5-release-:i386-:-:unknown.-:- (tnx BMF) 1.00: freebsd-2.1.6-release-:i386-:-:-:- (tnx TM) 0.96: freebsd-2.1.6-release-:i386-:-:Pentium-Pro.150-:- (tnx CH) 1.01: freebsd-2.1.6-release-:i386-:-:cy486dlc-:- (tnx M3H) 0.96: freebsd-2.1.6.1-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx MF) 1.01: freebsd-2.1.7-release-:i386-:-:i486-dx-:- (tnx AAF) 1.00: freebsd-2.1.7-release-:i386-:-:pentium.735\90.or.815\100-:- (tnx JBB) 1.01: freebsd-2.1.7-release-:i386-:-:pentium.815\100-:- (tnx B1F) 1.01: freebsd-2.2-970422-releng-:i386-:-:-:- (tnx TM) 1.00: freebsd-2.2-release-:i386-:-:-:- (tnx MT) 1.01: freebsd-2.2-stable-:i386-:-:cyrix.5x86-:- (tnx A2B) 1.01: freebsd-2.2-stable-:i386-:-:pentium-:- (tnx gary@systemics=???) 1.01: freebsd-2.2.1-release-:i386-:-:-:- (tnx M2R) 1.01: freebsd-2.2.1-release-:i386-:-:i486-dx-:- (tnx PGR) 1.00: freebsd-2.2.1-release-:i386-:-:i486.dx2-:- (tnx BR) 1.01: freebsd-2.2.1-release-:i386-:-:pentium-:- (tnx REB) 1.01: freebsd-2.2.1-release-:i386-:-:pentium.pro-:- (tnx JS) 1.01: freebsd-2.2.2-release-:i386-:-:amd.am5x86.write-through-:- (tnx AGB) 1.01: freebsd-2.2.2-release-:i386-:-:i486-dx-:- (tnx A2L) 1.01: freebsd-2.2.2-release-:i386-:-:i486.dx2-:- (tnx D3S) 1.01: freebsd-2.2.2-release-:i386-:-:pentium-:- (tnx B2F) 1.01: freebsd-2.2.2-release-:i386-:-:pentium.pro-:- (tnx M2G) 1.01: freebsd-2.2.5-release-:i386-:-:i486-dx-:- (tnx R2N) 1.01: freebsd-2.2.5-release-:i386-:-:i486.dx2-:- (tnx AY) 1.01: freebsd-2.2.5-release-:i386-:-:pentium.pro-:- (tnx AI) 1.01: freebsd-2.2.5-stable-:i386-:-:i486.dx2-:- (tnx JK) 1.01: freebsd-2.2.5-stable-:i386-:-:pentium-:- (tnx root@defiant=???) 1.01: freebsd-2.2.6-release-:i386-:-:-:- (tnx TM) 1.01: freebsd-2.2.6-release-:i386-:-:amd.am5x86.write-through-:- (tnx root@skully=???) 1.00: freebsd-3.0-970209-snap-:i386-:-:-:- (tnx YF) 1.01: freebsd-3.0-970428-snap-:i386-:-:pentium-:- (tnx M3S) 1.01: freebsd-3.0-970807-snap-:i386-:-:amd.k6-:- (tnx KMD) 1.01: freebsd-3.0-980309-snap-:i386-:-:pentium-:- (tnx MM) 1.01: freebsd-3.0-current-:i386-:-:pentium-:- (tnx KB) 1.01: hp-ux-a.09.05-a-:-:-:9000.712-:- (tnx SV) 1.01: hp-ux-a.09.07-a-:-:-:9000.712-:- (tnx LB) 1.00: hp-ux-b.09.00-a-:-:-:9000.360-:- (tnx VV) 1.01: hp-ux-b.10.20-a-:-:-:9000.755-:- (tnx BCK) 1.01: irix-5.3-11091812-:-:-:ip22-:- (tnx JL) 1.01: irix-6.2-03131015-:-:-:ip22-:- (tnx DS) 1.01: irix64-6.2-03131016-:-:-:ip19-:- (tnx AH) 1.01: irix64-6.2-06101031-:-:-:ip28-:- (tnx DB) 1.01: linux-1.2.13-:i386-:-:i486-:- (tnx RF) 1.01: linux-1.2.13-:i386-:-:pentium-:- (tnx MEE) 1.01: linux-1.99.4-:i386-:-:pentium-:- (tnx C2H) 1.01: linux-2.0.0-:i386-:-:i486-:- (tnx kragen@gentle=???) 1.01: linux-2.0.0-:i386-:-:pentium-:- (tnx MJD) 1.01: linux-2.0.6-:i386-:-:pentium-:- 1.00: linux-2.0.6-:i386-:-:ppro-:- (tnx MR) 1.01: linux-2.0.7-:i386-:-:i486-:- (tnx TLM) 1.01: linux-2.0.9-:i386-:-:i486-:- (tnx VBM) 0.96: linux-2.0.13-:i386-:-:pentium-:- (tnx BW) 1.01: linux-2.0.15-:i386-:-:i486-:- (tnx JCD) 1.01: linux-2.0.18-:i386-:-:i486-:- (tnx tk@avalon=???) 1.01: linux-2.0.18-:i386-:-:pentium-:- (tnx root@webtvchat=???) 1.00: linux-2.0.22-:i386-:-:pentium-:- (tnx MDI) 1.00: linux-2.0.23-:i386-:-:i486-:- (tnx B2L) 1.01: linux-2.0.24-:i386-:-:i486-:- (tnx GLM) 1.00: linux-2.0.24-:i386-:-:pentium-:- (tnx VV) 0.96: linux-2.0.25-:i386-:-:i486-:- (tnx BDB) 1.01: linux-2.0.25-:i386-:-:pentium-:- (tnx KA) 0.93: linux-2.0.26-:i386-:-:i486-:- (tnx blynch@texas=???) 1.01: linux-2.0.26-:i386-:-:pentium-:- (tnx robbie@opus=???) 1.00: linux-2.0.27-:-:-:sparc-:- (tnx SVD) 1.00: linux-2.0.27-:i386-:-:i386-:- (tnx ECG) 1.01: linux-2.0.27-:i386-:-:i486-:- (tnx BN) 1.01: linux-2.0.27-:i386-:-:pentium-:- (tnx EK) 1.01: linux-2.0.27-:i386-:-:ppro-:- (tnx L3L) 1.01: linux-2.0.28-:i386-:-:i486-:- (tnx AAF) 1.00: linux-2.0.28-:i386-:-:pentium-:- (tnx root@duggy=???) 1.01: linux-2.0.28-:i386-:-:ppro-:- (tnx S3T) 1.01: linux-2.0.28-osfmach3-:-:-:ppc-:- (tnx CG) 1.01: linux-2.0.29-:alpha-:-:alpha-:- (tnx MB) 1.01: linux-2.0.29-:i386-:-:i386-:- (tnx AJK) 1.01: linux-2.0.29-:i386-:-:i486-:- (tnx FPL) 1.01: linux-2.0.29-:i386-:-:pentium-:- (tnx FW) 1.00: linux-2.0.29-:i386-:-:ppro-:- (tnx MMM) 1.01: linux-2.0.30-:-:-:sparc-:- (tnx J2P) 1.01: linux-2.0.30-:alpha-:-:alpha-:- (tnx WS) 1.01: linux-2.0.30-:i386-:-:i386-:- (tnx OK) 1.00: linux-2.0.30-:i386-:-:i486-:- (tnx KUT) 1.01: linux-2.0.30-:i386-:-:i486-:- (tnx PK) 1.01: linux-2.0.30-:i386-:-:pentium-:- (tnx AV) 1.00: linux-2.0.30-:i386-:-:ppro-:- (tnx root@gate=???) 1.01: linux-2.0.30-osfmach3-:-:-:ppc-:- (tnx PTW) 1.01: linux-2.0.30u11-:i386-:-:pentium-:- (tnx JTB) 1.01: linux-2.0.31-:i386-:-:i486-:- (tnx SAE) 1.01: linux-2.0.31-:i386-:-:pentium-:- (tnx B3W) 1.01: linux-2.0.31-:i386-:-:ppro-:- (tnx JAK) 1.01: linux-2.0.32-:-:-:ie86-:- (tnx root@vmlinuz=???) 1.01: linux-2.0.32-:alpha-:-:alpha-:- (tnx NR) 1.01: linux-2.0.32-:i386-:-:i486-:- (tnx SC) 1.01: linux-2.0.32-:i386-:-:pentium-:- (tnx HT) 1.01: linux-2.0.32-:i386-:-:ppro-:- (tnx RK) 1.01: linux-2.0.33-:i386-:-:i486-:- (tnx RAB) 1.01: linux-2.0.33-:i386-:-:pentium-:- (tnx AF) 1.01: linux-2.0.33-:i386-:-:ppro-:- (tnx B2W) 1.01: linux-2.1.9-:i386-:-:i486-:- (tnx SJB) 1.01: linux-2.1.10-:i386-:-:i486-:- (tnx JB) 0.96: linux-2.1.13-:i386-:-:i486-:- (tnx ML) 0.96: linux-2.1.14-:i386-:-:pentium-:- (tnx SCW) 0.96: linux-2.1.23-:i386-:-:pentium-:- (tnx JF) 1.01: linux-2.1.24-:-:-:ppc-:- (tnx meta=???) 0.96: linux-2.1.25-:i386-:-:i486-:- (tnx JBF) 0.96: linux-2.1.25-:i386-:-:pentium-:- (tnx UO) 1.00: linux-2.1.26-:i386-:-:i486-:- (tnx DK) 1.00: linux-2.1.27-:i386-:-:pentium-:- (tnx JF) 1.01: linux-2.1.28-:i386-:-:i486-:- (tnx HDG) 1.00: linux-2.1.28-:i386-:-:pentium-:- (tnx RGS) 1.00: linux-2.1.29-:i386-:-:i486-:- (tnx SJW) 1.01: linux-2.1.35-:i386-:-:pentium-:- (tnx JF) 1.01: linux-2.1.36-:i386-:-:i486-:- (tnx ML) 1.01: linux-2.1.42-:i386-:-:i486-:- (tnx wtanaka=???) 1.01: linux-2.1.46-:i386-:-:pentium-:- (tnx VR) 1.01: linux-2.1.51-:i386-:-:pentium-:- (tnx KO) 1.01: linux-2.1.61-:i386-:-:i486-:- (tnx RO) 1.01: linux-2.1.65-:i386-:-:i486-:- (tnx F2T) 1.01: linux-2.1.71-:i386-:-:ppro-:- (tnx MJG) 1.01: linux-2.1.78-:i386-:-:pentium-:- (tnx AS) 1.01: linux-2.1.82-:i386-:-:pentium-:- (tnx AY) 1.01: linux-2.1.85-:i386-:-:pentium-:- (tnx PJH) 1.00: machten-4-0.4-:-:-:powerpc-:- (tnx RAM) 1.01: netbsd-1.1-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GL) 1.01: netbsd-1.2-:hp300-:-:-:- (tnx ML) 1.01: netbsd-1.2-:i386-:-:i486dx.(genuineintel.486-class.cpu)-:- (tnx T2K) 0.96: netbsd-1.2-:i386-:-:pentium.(genuineintel.586-class.cpu)-:- (tnx GH) 1.01: netbsd-1.2.1-:mac68k-:-:apple.macintosh.se/30..(68030)-:- (tnx HM) 1.01: netbsd-1.2.1-:sparc-:-:fmi,mb86904.@.110.mhz,.on-chip.fpu-:- (tnx ZU) 0.96: netbsd-1.2c-:pmax-:-:-:- (tnx JLW) 1.01: netbsd-1.3-:hp300-:-:hp.9000/433.(33mhz.mc68040.cpu+mmu+fpu,.4k.on-chip.physical.i/d.caches)-:- (tnx TB) 1.01: netbsd-1.3.1-:sun3-:-:sun.3/60-:- (tnx MBS) 1.01: netbsd-1.3_alpha-:i386-:-:intel.pentium.(p54c).(586-class)-:- (tnx GL) 1.01: nextstep-3.1-:mc680x0-:-:68040-:- (tnx JRY) 1.01: nextstep-3.3-:hppa-:-:7100lc-:- 1.01: nextstep-3.3-:i386-:-:pentium-:- (tnx HM) 1.01: nextstep-3.3-:mc680x0-:-:68040-:- (tnx WEB) 1.01: nextstep-4.1-:mc680x0-:-:68040-:- (tnx FN) 1.00: openbsd-2.0-hoth#0-:openbsd.i386-:-:i386-:- (tnx MBS) 1.00: openbsd-2.0-mr_potatoe_head#2-:openbsd.i386-:-:i386-:- (tnx JJMK) 0.96: openbsd-2.0-puma#1-:openbsd.m68k-:-:mac68k-:- (tnx AKB) 1.01: openbsd-2.1-asgard#1-:openbsd.i386-:-:i386-:- (tnx ETT) 1.01: openbsd-2.1-generic#71-:openbsd.sparc-:-:sparc-:- (tnx MMM2) 1.01: openbsd-2.1-katana#2-:openbsd.i386-:-:i386-:- (tnx CHR) 1.01: openbsd-2.1-puma#0-:openbsd.m68k-:-:mac68k-:- (tnx AKB) 1.01: openbsd-2.2-ele#2-:openbsd.i386-:-:i386-:- (tnx RC) 1.01: openbsd-2.2-generic#424-:openbsd.i386-:-:i386-:- (tnx ETT) 1.01: osf1-v2.0-240-:-:-:alpha-:- (tnx JF) 1.00: osf1-v3.2-148-:-:-:alpha-:- (tnx DL) 1.01: osf1-v3.2-148-:-:-:alpha-:- (tnx RSK) 1.01: osf1-v3.2-41-:-:-:alpha-:- (tnx MSD) 1.01: osf1-v3.2-mp-4.2-:-:-:alpha-:- (tnx MSD) 1.01: osf1-v4.0-386-:-:-:alpha-:- (tnx TEE) 1.01: osf1-v4.0-464-:-:-:alpha-:- (tnx AWB) 1.01: osf1-v4.0-564-:-:-:alpha-:- (tnx A2P) 1.01: osf1-v4.0-564.32-:-:-:alpha-:- (tnx TLF) 1.01: osf1-v4.0-878-:-:-:alpha-:- (tnx BJM) 1.01: sco_sv-3.2-2-:-:-:i386-:- (tnx PW) 1.01: sinix-l-5.41-d0005-:-:-:mx300i-:- (tnx IH) 1.01: sunos-4.1.1-1-:mc68020-:sun3-:sun3-:sun3- (tnx JWB) 1.01: sunos-4.1.1-1-:mc68020-:sun3-:sun3x-:sun3x- (tnx TT) 1.01: sunos-4.1.3-jl-2-:sparc-:sun4-:sun4c-:sun4c- (tnx T2K) 1.01: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4c-:sun4c- (tnx MBS) 1.01: sunos-4.1.3_u1-1-:sparc-:sun4-:sun4m-:sun4m- (tnx RSK) 1.01: sunos-4.1.3_u1-10-:sparc-:sun4-:sun4m-:sun4m- (tnx aoki=???) 1.00: sunos-4.1.3_u1-4-:unknown-:sun4-:sun4m-:sun4m- (tnx J2B) 1.01: sunos-4.1.3_u1-6-:sparc-:sun4-:sun4m-:sun4m- (tnx RD) 1.01: sunos-4.1.4-1-:unknown-:sun4-:sun4m-:sun4m- (tnx M3S) 1.01: sunos-4.1.4-2-:sparc-:sun4-:sun4m-:sun4m- 1.01: sunos-5.3-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx JDJ) 1.01: sunos-5.4-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx jimo=???) 0.96: sunos-5.4-generic_101945-10-:sparc-:sun4-:sun4m-:sun4m- (tnx W2K) 1.00: sunos-5.4-generic_101945-34-:sparc-:sun4-:sun4m-:sun4m- (tnx ACB) 0.96: sunos-5.4-generic_101946-35-:i386-:i86pc-:i86pc-:i86pc- (tnx CK) 1.01: sunos-5.5-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx seong=???) 1.01: sunos-5.5-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx SPM) 1.01: sunos-5.5-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM) 1.01: sunos-5.5-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx YC) 1.01: sunos-5.5-generic_103093-02-:sparc-:sun4-:sun4m-:sun4m- (tnx RF) 0.96: sunos-5.5-generic_103093-03-:sparc-:sun4-:sun4m-:sun4m- (tnx RDM) 1.01: sunos-5.5-generic_103093-06-:sparc-:sun4-:sun4m-:sun4m- (tnx ERH) 1.01: sunos-5.5-generic_103093-10-:sparc-:sun4-:sun4d-:sun4d- (tnx KT) 1.01: sunos-5.5-generic_103094-05-:i386-:i86pc-:i86pc-:i86pc- (tnx M2G) 1.01: sunos-5.5.1-generic-:i386-:i86pc-:i86pc-:i86pc- (tnx cro=???) 1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx CG) 1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx MBS) 1.01: sunos-5.5.1-generic-:sparc-:sun4-:sun4u-:sun4u- 0.96: sunos-5.5.1-generic_103640-02-:sparc-:sun4-:sun4m-:sun4m- (tnx SGC) 1.00: sunos-5.5.1-generic_103640-03-:sparc-:sun4-:sun4u-:sun4u- (tnx EG) 1.00: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4m-:sun4m- (tnx L2L) 1.01: sunos-5.5.1-generic_103640-05-:sparc-:sun4-:sun4u-:sun4u- (tnx KY) 1.01: sunos-5.5.1-generic_103640-06-:sparc-:sun4-:sun4u-:sun4u- (tnx RA) 1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4c-:sun4c- (tnx RA) 1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4d-:sun4d- (tnx MS) 1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4m-:sun4m- (tnx S2P) 1.01: sunos-5.5.1-generic_103640-08-:sparc-:sun4-:sun4u-:sun4u- (tnx CM) 1.01: sunos-5.5.1-generic_103640-12-:sparc-:sun4-:sun4m-:sun4m- (tnx IK) 1.01: sunos-5.5.1-generic_103640-18-:sparc-:sun4-:sun4u-:sun4u- (tnx PMH) 1.01: sunos-5.5.1-generic_103641-08-:i386-:i86pc-:i86pc-:i86pc- (tnx TL) 1.01: sunos-5.5.1-generic_103641-12-:i386-:i86pc-:i86pc-:i86pc- (tnx JS) 1.01: sunos-5.5.1-generic_105428-01-:sparc-:sun4-:sun4u-:sun4u- (tnx BCM) 0.96: sunos-5.5.1-generic_patch-:i386-:i86pc-:i86pc-:i86pc- (tnx D2K) 1.01: sunos-5.6-generic-:sparc-:sun4-:sun4c-:sun4c- (tnx DS) 1.01: sunos-5.6-generic-:sparc-:sun4-:sun4m-:sun4m- (tnx BDM) 1.01: sunos-5.6-generic-:sparc-:sun4-:sun4u-:sun4u- (tnx RPS) 1.01: sunos-5.6-generic_105182-01-:i386-:i86pc-:i86pc-:i86pc- (tnx JFK) 1.01: sunos-5.6-generic_105182-04-:i386-:i86pc-:i86pc-:i86pc- (tnx YC) 0.96: ultrix-4.3-1-:pmax-:-:risc-:- (tnx YF) 1.01: ultrix-4.4-0-:-:-:risc-:- (tnx RSK) 1.01: unix_sv-4.2mp-2.1.2-:i386-:-:i386-:- (tnx J2W) netqmail-1.06/qmail-rspawn.c0000644000076400007640000000346106541176434015435 0ustar nelsonnelson#include "fd.h" #include "wait.h" #include "substdio.h" #include "exit.h" #include "fork.h" #include "error.h" #include "tcpto.h" void initialize(argc,argv) int argc; char **argv; { tcpto_clean(); } int truncreport = 0; void report(ss,wstat,s,len) substdio *ss; int wstat; char *s; int len; { int j; int k; int result; int orr; if (wait_crashed(wstat)) { substdio_puts(ss,"Zqmail-remote crashed.\n"); return; } switch(wait_exitcode(wstat)) { case 0: break; case 111: substdio_puts(ss,"ZUnable to run qmail-remote.\n"); return; default: substdio_puts(ss,"DUnable to run qmail-remote.\n"); return; } if (!len) { substdio_puts(ss,"Zqmail-remote produced no output.\n"); return; } result = -1; j = 0; for (k = 0;k < len;++k) if (!s[k]) { if (s[j] == 'K') { result = 1; break; } if (s[j] == 'Z') { result = 0; break; } if (s[j] == 'D') break; j = k + 1; } orr = result; switch(s[0]) { case 's': orr = 0; break; case 'h': orr = -1; } switch(orr) { case 1: substdio_put(ss,"K",1); break; case 0: substdio_put(ss,"Z",1); break; case -1: substdio_put(ss,"D",1); break; } for (k = 1;k < len;) if (!s[k++]) { substdio_puts(ss,s + 1); if (result <= orr) if (k < len) switch(s[k]) { case 'Z': case 'D': case 'K': substdio_puts(ss,s + k + 1); } break; } } int spawn(fdmess,fdout,s,r,at) int fdmess; int fdout; char *s; char *r; int at; { int f; char *(args[5]); args[0] = "qmail-remote"; args[1] = r + at + 1; args[2] = s; args[3] = r; args[4] = 0; if (!(f = vfork())) { if (fd_move(0,fdmess) == -1) _exit(111); if (fd_move(1,fdout) == -1) _exit(111); if (fd_copy(2,1) == -1) _exit(111); execvp(*args,args); if (error_temp(errno)) _exit(111); _exit(100); } return f; } netqmail-1.06/mbox.50000644000076400007640000001126406541176434013711 0ustar nelsonnelson.TH mbox 5 .SH "NAME" mbox \- file containing mail messages .SH "INTRODUCTION" The most common format for storage of mail messages is .I mbox format. An .I mbox is a single file containing zero or more mail messages. .SH "MESSAGE FORMAT" A message encoded in .I mbox format begins with a .B From_ line, continues with a series of .B \fRnon-\fBFrom_ lines, and ends with a blank line. A .B From_ line means any line that begins with the characters F, r, o, m, space: .EX From god@heaven.af.mil Sat Jan 3 01:05:34 1996 .br Return-Path: .br Delivered-To: djb@silverton.berkeley.edu .br Date: 3 Jan 1996 01:05:34 -0000 .br From: God .br To: djb@silverton.berkeley.edu (D. J. Bernstein) .br .br How's that mail system project coming along? .br .EE The final line is a completely blank line (no spaces or tabs). Notice that blank lines may also appear elsewhere in the message. The .B From_ line always looks like .B From .I envsender .I date .IR moreinfo . .I envsender is one word, without spaces or tabs; it is usually the envelope sender of the message. .I date is the delivery date of the message. It always contains exactly 24 characters in .B asctime format. .I moreinfo is optional; it may contain arbitrary information. Between the .B From_ line and the blank line is a message in RFC 822 format, as described in .BR qmail-header(5) , subject to .B >From quoting as described below. .SH "HOW A MESSAGE IS DELIVERED" Here is how a program appends a message to an .I mbox file. It first creates a .B From_ line given the message's envelope sender and the current date. If the envelope sender is empty (i.e., if this is a bounce message), the program uses .B MAILER-DAEMON instead. If the envelope sender contains spaces, tabs, or newlines, the program replaces them with hyphens. The program then copies the message, applying .B >From quoting to each line. .B >From quoting ensures that the resulting lines are not .B From_ lines: the program prepends a .B > to any .B From_ line, .B >From_ line, .B >>From_ line, .B >>>From_ line, etc. Finally the program appends a blank line to the message. If the last line of the message was a partial line, it writes two newlines; otherwise it writes one. .SH "HOW A MESSAGE IS READ" A reader scans through an .I mbox file looking for .B From_ lines. Any .B From_ line marks the beginning of a message. The reader should not attempt to take advantage of the fact that every .B From_ line (past the beginning of the file) is preceded by a blank line. Once the reader finds a message, it extracts a (possibly corrupted) envelope sender and delivery date out of the .B From_ line. It then reads until the next .B From_ line or end of file, whichever comes first. It strips off the final blank line and deletes the quoting of .B >From_ lines and .B >>From_ lines and so on. The result is an RFC 822 message. .SH "COMMON MBOX VARIANTS" There are many variants of .I mbox format. The variant described above is .I mboxrd format, popularized by Rahul Dhesi in June 1995. The original .I mboxo format quotes only .B From_ lines, not .B >From_ lines. As a result it is impossible to tell whether .EX From: djb@silverton.berkeley.edu (D. J. Bernstein) .br To: god@heaven.af.mil .br .br >From now through August I'll be doing beta testing. .br Thanks for your interest. .EE was quoted in the original message. An .I mboxrd reader will always strip off the quoting. .I mboxcl format is like .I mboxo format, but includes a Content-Length field with the number of bytes in the message. .I mboxcl2 format is like .I mboxcl but has no .B >From quoting. These formats are used by SVR4 mailers. .I mboxcl2 cannot be read safely by .I mboxrd readers. .SH "UNSPECIFIED DETAILS" There are many locking mechanisms for .I mbox files. .B qmail-local always uses .B flock on systems that have it, otherwise .BR lockf . The delivery date in a .B From_ line does not specify a time zone. .B qmail-local always creates the delivery date in GMT so that .I mbox files can be safely transported from one time zone to another. If the mtime on a nonempty .I mbox file is greater than the atime, the file has new mail. If the mtime is smaller than the atime, the new mail has been read. If the atime equals the mtime, there is no way to tell whether the file has new mail, since .B qmail-local takes much less than a second to run. One solution is for a mail reader to artificially set the atime to the mtime plus 1. Then the file has new mail if and only if the atime is less than or equal to the mtime. Some mail readers place .B Status fields in each message to indicate which messages have been read. .SH "SEE ALSO" maildir(5), qmail-header(5), qmail-local(8) netqmail-1.06/sig.h0000644000076400007640000000164606541176434013614 0ustar nelsonnelson#ifndef SIG_H #define SIG_H extern void sig_catch(); extern void sig_block(); extern void sig_unblock(); extern void sig_blocknone(); extern void sig_pause(); extern void sig_dfl(); extern void sig_miscignore(); extern void sig_bugcatch(); extern void sig_pipeignore(); extern void sig_pipedefault(); extern void sig_contblock(); extern void sig_contunblock(); extern void sig_contcatch(); extern void sig_contdefault(); extern void sig_termblock(); extern void sig_termunblock(); extern void sig_termcatch(); extern void sig_termdefault(); extern void sig_alarmblock(); extern void sig_alarmunblock(); extern void sig_alarmcatch(); extern void sig_alarmdefault(); extern void sig_childblock(); extern void sig_childunblock(); extern void sig_childcatch(); extern void sig_childdefault(); extern void sig_hangupblock(); extern void sig_hangupunblock(); extern void sig_hangupcatch(); extern void sig_hangupdefault(); #endif netqmail-1.06/warn-auto.sh0000644000076400007640000000010006541176434015112 0ustar nelsonnelson#!/bin/sh # WARNING: This file was auto-generated. Do not edit! netqmail-1.06/INSTALL.alias0000644000076400007640000000400106541176434014766 0ustar nelsonnelsonqmail lets each user control all addresses of the form user-anything. Addresses that don't start with a username are controlled by a special user, alias. Delivery instructions for foo go into ~alias/.qmail-foo; delivery instructions for user-foo go into ~user/.qmail-foo. See dot-qmail.0 for the full story. qmail doesn't have any built-in support for /etc/aliases. If you have a big /etc/aliases and you'd like to keep it, install the fastforward package, available separately. /etc/aliases should already include the aliases discussed below---Postmaster, MAILER-DAEMON, and root. If you don't have a big /etc/aliases, you'll find it easier to use qmail's native alias mechanism. Here's a checklist of aliases you should set up right now. * Postmaster. You're not an Internet citizen if this address doesn't work. Simply touch (and chmod 644) ~alias/.qmail-postmaster; any mail for Postmaster will be delivered to ~alias/Mailbox. * MAILER-DAEMON. Not required, but users sometimes respond to bounce messages. Touch (and chmod 644) ~alias/.qmail-mailer-daemon. * root. Under qmail, root never receives mail. Your system may generate mail messages to root every night; if you don't have an alias for root, those messages will bounce. (They'll end up double-bouncing to the postmaster.) Set up an alias for root in ~alias/.qmail-root. .qmail files are similar to .forward files, but beware that they are strictly line-oriented---see dot-qmail.0 for details. * Other non-user accounts. Under qmail, non-user accounts don't get mail; ``user'' means a non-root account that owns ~account. Set up aliases for any non-user accounts that normally receive mail. Note that special accounts such as ftp, www, and uucp should always have home directories owned by root. * Default. If you want, you can touch ~alias/.qmail-default to catch everything else. Beware: this will also catch typos and other addresses that should probably be bounced instead. It won't catch addresses that start with a user name---the user can set up his own ~/.qmail-default. netqmail-1.06/subfdout.c0000644000076400007640000000031406541176434014647 0ustar nelsonnelson#include "readwrite.h" #include "substdio.h" #include "subfd.h" char subfd_outbuf[SUBSTDIO_OUTSIZE]; static substdio it = SUBSTDIO_FDBUF(write,1,subfd_outbuf,SUBSTDIO_OUTSIZE); substdio *subfdout = ⁢ netqmail-1.06/sig_bug.c0000644000076400007640000000043106541176434014433 0ustar nelsonnelson#include #include "sig.h" void sig_bugcatch(f) void (*f)(); { sig_catch(SIGILL,f); sig_catch(SIGABRT,f); sig_catch(SIGFPE,f); sig_catch(SIGBUS,f); sig_catch(SIGSEGV,f); #ifdef SIGSYS sig_catch(SIGSYS,f); #endif #ifdef SIGEMT sig_catch(SIGEMT,f); #endif } netqmail-1.06/byte.h0000644000076400007640000000040106541176434013761 0ustar nelsonnelson#ifndef BYTE_H #define BYTE_H extern unsigned int byte_chr(); extern unsigned int byte_rchr(); extern void byte_copy(); extern void byte_copyr(); extern int byte_diff(); extern void byte_zero(); #define byte_equal(s,n,t) (!byte_diff((s),(n),(t))) #endif netqmail-1.06/str_len.c0000644000076400007640000000035706541176434014471 0ustar nelsonnelson#include "str.h" unsigned int str_len(s) register char *s; { register char *t; t = s; for (;;) { if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; if (!*t) return t - s; ++t; } } netqmail-1.06/INSTALL0000644000076400007640000000004610724070436013674 0ustar nelsonnelsonSee http://lifewithqmail.org/lwq.html netqmail-1.06/Makefile0000644000076400007640000017036210724070436014314 0ustar nelsonnelson# Don't edit Makefile! Use conf-* for configuration. SHELL=/bin/sh default: it addresses.0: \ addresses.5 nroff -man addresses.5 > addresses.0 alloc.a: \ makelib alloc.o alloc_re.o ./makelib alloc.a alloc.o alloc_re.o alloc.o: \ compile alloc.c alloc.h error.h ./compile alloc.c alloc_re.o: \ compile alloc_re.c alloc.h byte.h ./compile alloc_re.c auto-ccld.sh: \ conf-cc conf-ld warn-auto.sh ( cat warn-auto.sh; \ echo CC=\'`head -1 conf-cc`\'; \ echo LD=\'`head -1 conf-ld`\' \ ) > auto-ccld.sh auto-gid: \ load auto-gid.o substdio.a error.a str.a fs.a ./load auto-gid substdio.a error.a str.a fs.a auto-gid.o: \ compile auto-gid.c subfd.h substdio.h substdio.h readwrite.h exit.h \ scan.h fmt.h ./compile auto-gid.c auto-int: \ load auto-int.o substdio.a error.a str.a fs.a ./load auto-int substdio.a error.a str.a fs.a auto-int.o: \ compile auto-int.c substdio.h readwrite.h exit.h scan.h fmt.h ./compile auto-int.c auto-int8: \ load auto-int8.o substdio.a error.a str.a fs.a ./load auto-int8 substdio.a error.a str.a fs.a auto-int8.o: \ compile auto-int8.c substdio.h readwrite.h exit.h scan.h fmt.h ./compile auto-int8.c auto-str: \ load auto-str.o substdio.a error.a str.a ./load auto-str substdio.a error.a str.a auto-str.o: \ compile auto-str.c substdio.h readwrite.h exit.h ./compile auto-str.c auto-uid: \ load auto-uid.o substdio.a error.a str.a fs.a ./load auto-uid substdio.a error.a str.a fs.a auto-uid.o: \ compile auto-uid.c subfd.h substdio.h substdio.h readwrite.h exit.h \ scan.h fmt.h ./compile auto-uid.c auto_break.c: \ auto-str conf-break ./auto-str auto_break \ "`head -1 conf-break`" > auto_break.c auto_break.o: \ compile auto_break.c ./compile auto_break.c auto_patrn.c: \ auto-int8 conf-patrn ./auto-int8 auto_patrn `head -1 conf-patrn` > auto_patrn.c auto_patrn.o: \ compile auto_patrn.c ./compile auto_patrn.c auto_qmail.c: \ auto-str conf-qmail ./auto-str auto_qmail `head -1 conf-qmail` > auto_qmail.c auto_qmail.o: \ compile auto_qmail.c ./compile auto_qmail.c auto_spawn.c: \ auto-int conf-spawn ./auto-int auto_spawn `head -1 conf-spawn` > auto_spawn.c auto_spawn.o: \ compile auto_spawn.c ./compile auto_spawn.c auto_split.c: \ auto-int conf-split ./auto-int auto_split `head -1 conf-split` > auto_split.c auto_split.o: \ compile auto_split.c ./compile auto_split.c auto_uids.c: \ auto-uid auto-gid conf-users conf-groups ( ./auto-uid auto_uida `head -1 conf-users` \ &&./auto-uid auto_uidd `head -2 conf-users | tail -1` \ &&./auto-uid auto_uidl `head -3 conf-users | tail -1` \ &&./auto-uid auto_uido `head -4 conf-users | tail -1` \ &&./auto-uid auto_uidp `head -5 conf-users | tail -1` \ &&./auto-uid auto_uidq `head -6 conf-users | tail -1` \ &&./auto-uid auto_uidr `head -7 conf-users | tail -1` \ &&./auto-uid auto_uids `head -8 conf-users | tail -1` \ &&./auto-gid auto_gidq `head -1 conf-groups` \ &&./auto-gid auto_gidn `head -2 conf-groups | tail -1` \ ) > auto_uids.c.tmp && mv auto_uids.c.tmp auto_uids.c auto_uids.o: \ compile auto_uids.c ./compile auto_uids.c auto_usera.c: \ auto-str conf-users ./auto-str auto_usera `head -1 conf-users` > auto_usera.c auto_usera.o: \ compile auto_usera.c ./compile auto_usera.c binm1: \ binm1.sh conf-qmail cat binm1.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm1 chmod 755 binm1 binm1+df: \ binm1+df.sh conf-qmail cat binm1+df.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm1+df chmod 755 binm1+df binm2: \ binm2.sh conf-qmail cat binm2.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm2 chmod 755 binm2 binm2+df: \ binm2+df.sh conf-qmail cat binm2+df.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm2+df chmod 755 binm2+df binm3: \ binm3.sh conf-qmail cat binm3.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm3 chmod 755 binm3 binm3+df: \ binm3+df.sh conf-qmail cat binm3+df.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > binm3+df chmod 755 binm3+df bouncesaying: \ load bouncesaying.o strerr.a error.a substdio.a str.a wait.a ./load bouncesaying strerr.a error.a substdio.a str.a \ wait.a bouncesaying.0: \ bouncesaying.1 nroff -man bouncesaying.1 > bouncesaying.0 bouncesaying.o: \ compile bouncesaying.c fork.h strerr.h error.h wait.h sig.h exit.h ./compile bouncesaying.c byte_chr.o: \ compile byte_chr.c byte.h ./compile byte_chr.c byte_copy.o: \ compile byte_copy.c byte.h ./compile byte_copy.c byte_cr.o: \ compile byte_cr.c byte.h ./compile byte_cr.c byte_diff.o: \ compile byte_diff.c byte.h ./compile byte_diff.c byte_rchr.o: \ compile byte_rchr.c byte.h ./compile byte_rchr.c byte_zero.o: \ compile byte_zero.c byte.h ./compile byte_zero.c case.a: \ makelib case_diffb.o case_diffs.o case_lowerb.o case_lowers.o \ case_starts.o ./makelib case.a case_diffb.o case_diffs.o case_lowerb.o \ case_lowers.o case_starts.o case_diffb.o: \ compile case_diffb.c case.h ./compile case_diffb.c case_diffs.o: \ compile case_diffs.c case.h ./compile case_diffs.c case_lowerb.o: \ compile case_lowerb.c case.h ./compile case_lowerb.c case_lowers.o: \ compile case_lowers.c case.h ./compile case_lowers.c case_starts.o: \ compile case_starts.c case.h ./compile case_starts.c cdb.a: \ makelib cdb_hash.o cdb_unpack.o cdb_seek.o ./makelib cdb.a cdb_hash.o cdb_unpack.o cdb_seek.o cdb_hash.o: \ compile cdb_hash.c cdb.h uint32.h ./compile cdb_hash.c cdb_seek.o: \ compile cdb_seek.c cdb.h uint32.h ./compile cdb_seek.c cdb_unpack.o: \ compile cdb_unpack.c cdb.h uint32.h ./compile cdb_unpack.c cdbmake.a: \ makelib cdbmake_pack.o cdbmake_hash.o cdbmake_add.o ./makelib cdbmake.a cdbmake_pack.o cdbmake_hash.o \ cdbmake_add.o cdbmake_add.o: \ compile cdbmake_add.c cdbmake.h alloc.h uint32.h ./compile cdbmake_add.c cdbmake_hash.o: \ compile cdbmake_hash.c cdbmake.h uint32.h ./compile cdbmake_hash.c cdbmake_pack.o: \ compile cdbmake_pack.c cdbmake.h uint32.h ./compile cdbmake_pack.c cdbmss.o: \ compile cdbmss.c readwrite.h seek.h alloc.h cdbmss.h cdbmake.h \ uint32.h substdio.h ./compile cdbmss.c check: \ it man ./instcheck chkshsgr: \ load chkshsgr.o ./load chkshsgr chkshsgr.o: \ compile chkshsgr.c exit.h ./compile chkshsgr.c chkspawn: \ load chkspawn.o substdio.a error.a str.a fs.a auto_spawn.o ./load chkspawn substdio.a error.a str.a fs.a auto_spawn.o chkspawn.o: \ compile chkspawn.c substdio.h subfd.h substdio.h fmt.h select.h \ exit.h auto_spawn.h ./compile chkspawn.c clean: \ TARGETS rm -f `cat TARGETS` coe.o: \ compile coe.c coe.h ./compile coe.c commands.o: \ compile commands.c commands.h substdio.h stralloc.h gen_alloc.h str.h \ case.h ./compile commands.c compile: \ make-compile warn-auto.sh systype ( cat warn-auto.sh; ./make-compile "`cat systype`" ) > \ compile chmod 755 compile condredirect: \ load condredirect.o qmail.o strerr.a fd.a sig.a wait.a seek.a env.a \ substdio.a error.a str.a fs.a auto_qmail.o ./load condredirect qmail.o strerr.a fd.a sig.a wait.a \ seek.a env.a substdio.a error.a str.a fs.a auto_qmail.o condredirect.0: \ condredirect.1 nroff -man condredirect.1 > condredirect.0 condredirect.o: \ compile condredirect.c sig.h readwrite.h exit.h env.h error.h fork.h \ wait.h seek.h qmail.h substdio.h strerr.h substdio.h fmt.h ./compile condredirect.c config: \ warn-auto.sh config.sh conf-qmail conf-break conf-split cat warn-auto.sh config.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > config chmod 755 config config-fast: \ warn-auto.sh config-fast.sh conf-qmail conf-break conf-split cat warn-auto.sh config-fast.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > config-fast chmod 755 config-fast constmap.o: \ compile constmap.c constmap.h alloc.h case.h ./compile constmap.c control.o: \ compile control.c readwrite.h open.h getln.h stralloc.h gen_alloc.h \ substdio.h error.h control.h alloc.h scan.h ./compile control.c date822fmt.o: \ compile date822fmt.c datetime.h fmt.h date822fmt.h ./compile date822fmt.c datemail: \ warn-auto.sh datemail.sh conf-qmail conf-break conf-split cat warn-auto.sh datemail.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > datemail chmod 755 datemail datetime.a: \ makelib datetime.o datetime_un.o ./makelib datetime.a datetime.o datetime_un.o datetime.o: \ compile datetime.c datetime.h ./compile datetime.c datetime_un.o: \ compile datetime_un.c datetime.h ./compile datetime_un.c direntry.h: \ compile trydrent.c direntry.h1 direntry.h2 ( ./compile trydrent.c >/dev/null 2>&1 \ && cat direntry.h2 || cat direntry.h1 ) > direntry.h rm -f trydrent.o dns.lib: \ tryrsolv.c compile load socket.lib dns.o ipalloc.o ip.o stralloc.a \ alloc.a error.a fs.a str.a ( ( ./compile tryrsolv.c && ./load tryrsolv dns.o \ ipalloc.o ip.o stralloc.a alloc.a error.a fs.a str.a \ -lresolv `cat socket.lib` ) >/dev/null 2>&1 \ && echo -lresolv || exit 0 ) > dns.lib rm -f tryrsolv.o tryrsolv dns.o: \ compile dns.c ip.h ipalloc.h ip.h gen_alloc.h fmt.h alloc.h str.h \ stralloc.h gen_alloc.h dns.h case.h ./compile dns.c dnscname: \ load dnscname.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a dns.lib socket.lib ./load dnscname dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \ socket.lib` dnscname.o: \ compile dnscname.c substdio.h subfd.h substdio.h stralloc.h \ gen_alloc.h dns.h dnsdoe.h readwrite.h exit.h ./compile dnscname.c dnsdoe.o: \ compile dnsdoe.c substdio.h subfd.h substdio.h exit.h dns.h dnsdoe.h ./compile dnsdoe.c dnsfq: \ load dnsfq.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a dns.lib socket.lib ./load dnsfq dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \ socket.lib` dnsfq.o: \ compile dnsfq.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h ./compile dnsfq.c dnsip: \ load dnsip.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a dns.lib socket.lib ./load dnsip dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \ socket.lib` dnsip.o: \ compile dnsip.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h exit.h ./compile dnsip.c dnsmxip: \ load dnsmxip.o dns.o dnsdoe.o ip.o ipalloc.o now.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a dns.lib socket.lib ./load dnsmxip dns.o dnsdoe.o ip.o ipalloc.o now.o \ stralloc.a alloc.a substdio.a error.a str.a fs.a `cat \ dns.lib` `cat socket.lib` dnsmxip.o: \ compile dnsmxip.c substdio.h subfd.h substdio.h stralloc.h \ gen_alloc.h fmt.h dns.h dnsdoe.h ip.h ipalloc.h ip.h gen_alloc.h \ now.h datetime.h exit.h ./compile dnsmxip.c dnsptr: \ load dnsptr.o dns.o dnsdoe.o ip.o ipalloc.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a dns.lib socket.lib ./load dnsptr dns.o dnsdoe.o ip.o ipalloc.o stralloc.a \ alloc.a substdio.a error.a str.a fs.a `cat dns.lib` `cat \ socket.lib` dnsptr.o: \ compile dnsptr.c substdio.h subfd.h substdio.h stralloc.h gen_alloc.h \ str.h scan.h dns.h dnsdoe.h ip.h exit.h ./compile dnsptr.c dot-qmail.0: \ dot-qmail.5 nroff -man dot-qmail.5 > dot-qmail.0 dot-qmail.5: \ dot-qmail.9 conf-break conf-spawn cat dot-qmail.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > dot-qmail.5 elq: \ warn-auto.sh elq.sh conf-qmail conf-break conf-split cat warn-auto.sh elq.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > elq chmod 755 elq env.a: \ makelib env.o envread.o ./makelib env.a env.o envread.o env.o: \ compile env.c str.h alloc.h env.h ./compile env.c envelopes.0: \ envelopes.5 nroff -man envelopes.5 > envelopes.0 envread.o: \ compile envread.c env.h str.h ./compile envread.c error.a: \ makelib error.o error_str.o error_temp.o ./makelib error.a error.o error_str.o error_temp.o error.o: \ compile error.c error.h ./compile error.c error_str.o: \ compile error_str.c error.h ./compile error_str.c error_temp.o: \ compile error_temp.c error.h ./compile error_temp.c except: \ load except.o strerr.a error.a substdio.a str.a wait.a ./load except strerr.a error.a substdio.a str.a wait.a except.0: \ except.1 nroff -man except.1 > except.0 except.o: \ compile except.c fork.h strerr.h wait.h error.h exit.h ./compile except.c fd.a: \ makelib fd_copy.o fd_move.o ./makelib fd.a fd_copy.o fd_move.o fd_copy.o: \ compile fd_copy.c fd.h ./compile fd_copy.c fd_move.o: \ compile fd_move.c fd.h ./compile fd_move.c fifo.o: \ compile fifo.c hasmkffo.h fifo.h ./compile fifo.c find-systype: \ find-systype.sh auto-ccld.sh cat auto-ccld.sh find-systype.sh > find-systype chmod 755 find-systype fmt_str.o: \ compile fmt_str.c fmt.h ./compile fmt_str.c fmt_strn.o: \ compile fmt_strn.c fmt.h ./compile fmt_strn.c fmt_uint.o: \ compile fmt_uint.c fmt.h ./compile fmt_uint.c fmt_uint0.o: \ compile fmt_uint0.c fmt.h ./compile fmt_uint0.c fmt_ulong.o: \ compile fmt_ulong.c fmt.h ./compile fmt_ulong.c fmtqfn.o: \ compile fmtqfn.c fmtqfn.h fmt.h auto_split.h ./compile fmtqfn.c forgeries.0: \ forgeries.7 nroff -man forgeries.7 > forgeries.0 fork.h: \ compile load tryvfork.c fork.h1 fork.h2 ( ( ./compile tryvfork.c && ./load tryvfork ) >/dev/null \ 2>&1 \ && cat fork.h2 || cat fork.h1 ) > fork.h rm -f tryvfork.o tryvfork forward: \ load forward.o qmail.o strerr.a alloc.a fd.a wait.a sig.a env.a \ substdio.a error.a str.a fs.a auto_qmail.o ./load forward qmail.o strerr.a alloc.a fd.a wait.a sig.a \ env.a substdio.a error.a str.a fs.a auto_qmail.o forward.0: \ forward.1 nroff -man forward.1 > forward.0 forward.o: \ compile forward.c sig.h readwrite.h exit.h env.h qmail.h substdio.h \ strerr.h substdio.h fmt.h ./compile forward.c fs.a: \ makelib fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o fmt_ulong.o \ scan_ulong.o scan_8long.o ./makelib fs.a fmt_str.o fmt_strn.o fmt_uint.o fmt_uint0.o \ fmt_ulong.o scan_ulong.o scan_8long.o getln.a: \ makelib getln.o getln2.o ./makelib getln.a getln.o getln2.o getln.o: \ compile getln.c substdio.h byte.h stralloc.h gen_alloc.h getln.h ./compile getln.c getln2.o: \ compile getln2.c substdio.h stralloc.h gen_alloc.h byte.h getln.h ./compile getln2.c getopt.a: \ makelib subgetopt.o sgetopt.o ./makelib getopt.a subgetopt.o sgetopt.o gfrom.o: \ compile gfrom.c str.h gfrom.h ./compile gfrom.c hasflock.h: \ tryflock.c compile load ( ( ./compile tryflock.c && ./load tryflock ) >/dev/null \ 2>&1 \ && echo \#define HASFLOCK 1 || exit 0 ) > hasflock.h rm -f tryflock.o tryflock hasmkffo.h: \ trymkffo.c compile load ( ( ./compile trymkffo.c && ./load trymkffo ) >/dev/null \ 2>&1 \ && echo \#define HASMKFIFO 1 || exit 0 ) > hasmkffo.h rm -f trymkffo.o trymkffo hasnpbg1.h: \ trynpbg1.c compile load open.h open.a fifo.h fifo.o select.h ( ( ./compile trynpbg1.c \ && ./load trynpbg1 fifo.o open.a && ./trynpbg1 ) \ >/dev/null 2>&1 \ && echo \#define HASNAMEDPIPEBUG1 1 || exit 0 ) > \ hasnpbg1.h rm -f trynpbg1.o trynpbg1 hassalen.h: \ trysalen.c compile ( ./compile trysalen.c >/dev/null 2>&1 \ && echo \#define HASSALEN 1 || exit 0 ) > hassalen.h rm -f trysalen.o hassgact.h: \ trysgact.c compile load ( ( ./compile trysgact.c && ./load trysgact ) >/dev/null \ 2>&1 \ && echo \#define HASSIGACTION 1 || exit 0 ) > hassgact.h rm -f trysgact.o trysgact hassgprm.h: \ trysgprm.c compile load ( ( ./compile trysgprm.c && ./load trysgprm ) >/dev/null \ 2>&1 \ && echo \#define HASSIGPROCMASK 1 || exit 0 ) > hassgprm.h rm -f trysgprm.o trysgprm hasshsgr.h: \ chkshsgr warn-shsgr tryshsgr.c compile load ./chkshsgr || ( cat warn-shsgr; exit 1 ) ( ( ./compile tryshsgr.c \ && ./load tryshsgr && ./tryshsgr ) >/dev/null 2>&1 \ && echo \#define HASSHORTSETGROUPS 1 || exit 0 ) > \ hasshsgr.h rm -f tryshsgr.o tryshsgr haswaitp.h: \ trywaitp.c compile load ( ( ./compile trywaitp.c && ./load trywaitp ) >/dev/null \ 2>&1 \ && echo \#define HASWAITPID 1 || exit 0 ) > haswaitp.h rm -f trywaitp.o trywaitp headerbody.o: \ compile headerbody.c stralloc.h gen_alloc.h substdio.h getln.h \ hfield.h headerbody.h ./compile headerbody.c hfield.o: \ compile hfield.c hfield.h ./compile hfield.c hier.o: \ compile hier.c auto_qmail.h auto_split.h auto_uids.h fmt.h fifo.h ./compile hier.c home: \ home.sh conf-qmail cat home.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > home chmod 755 home home+df: \ home+df.sh conf-qmail cat home+df.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > home+df chmod 755 home+df hostname: \ load hostname.o substdio.a error.a str.a dns.lib socket.lib ./load hostname substdio.a error.a str.a `cat dns.lib` \ `cat socket.lib` hostname.o: \ compile hostname.c substdio.h subfd.h substdio.h readwrite.h exit.h ./compile hostname.c idedit: \ load idedit.o strerr.a substdio.a error.a str.a fs.a wait.a open.a \ seek.a ./load idedit strerr.a substdio.a error.a str.a fs.a \ wait.a open.a seek.a idedit.o: \ compile idedit.c readwrite.h exit.h scan.h fmt.h strerr.h open.h \ seek.h fork.h ./compile idedit.c install: \ load install.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ strerr.a substdio.a open.a error.a str.a fs.a ./load install fifo.o hier.o auto_qmail.o auto_split.o \ auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a install-big: \ load install-big.o fifo.o install.o auto_qmail.o auto_split.o \ auto_uids.o strerr.a substdio.a open.a error.a str.a fs.a ./load install-big fifo.o install.o auto_qmail.o \ auto_split.o auto_uids.o strerr.a substdio.a open.a error.a \ str.a fs.a install-big.o: \ compile install-big.c auto_qmail.h auto_split.h auto_uids.h fmt.h \ fifo.h ./compile install-big.c install.o: \ compile install.c substdio.h strerr.h error.h open.h readwrite.h \ exit.h ./compile install.c instcheck: \ load instcheck.o fifo.o hier.o auto_qmail.o auto_split.o auto_uids.o \ strerr.a substdio.a error.a str.a fs.a ./load instcheck fifo.o hier.o auto_qmail.o auto_split.o \ auto_uids.o strerr.a substdio.a error.a str.a fs.a instcheck.o: \ compile instcheck.c strerr.h error.h readwrite.h exit.h ./compile instcheck.c ip.o: \ compile ip.c fmt.h scan.h ip.h ./compile ip.c ipalloc.o: \ compile ipalloc.c alloc.h gen_allocdefs.h ip.h ipalloc.h ip.h \ gen_alloc.h ./compile ipalloc.c ipme.o: \ compile ipme.c hassalen.h byte.h ip.h ipalloc.h ip.h gen_alloc.h \ stralloc.h gen_alloc.h ipme.h ip.h ipalloc.h ./compile ipme.c ipmeprint: \ load ipmeprint.o ipme.o ip.o ipalloc.o stralloc.a alloc.a substdio.a \ error.a str.a fs.a socket.lib ./load ipmeprint ipme.o ip.o ipalloc.o stralloc.a alloc.a \ substdio.a error.a str.a fs.a `cat socket.lib` ipmeprint.o: \ compile ipmeprint.c subfd.h substdio.h substdio.h ip.h ipme.h ip.h \ ipalloc.h ip.h gen_alloc.h exit.h ./compile ipmeprint.c it: \ qmail-local qmail-lspawn qmail-getpw qmail-remote qmail-rspawn \ qmail-clean qmail-send qmail-start splogger qmail-queue qmail-inject \ predate datemail mailsubj qmail-upq qmail-showctl qmail-newu \ qmail-pw2u qmail-qread qmail-qstat qmail-tcpto qmail-tcpok \ qmail-pop3d qmail-popup qmail-qmqpc qmail-qmqpd qmail-qmtpd \ qmail-smtpd sendmail tcp-env qmail-newmrh config config-fast dnscname \ dnsptr dnsip dnsmxip dnsfq hostname ipmeprint qreceipt qsmhook qbiff \ forward preline condredirect bouncesaying except maildirmake \ maildir2mbox maildirwatch qail elq pinq idedit install-big install \ instcheck home home+df proc proc+df binm1 binm1+df binm2 binm2+df \ binm3 binm3+df load: \ make-load warn-auto.sh systype ( cat warn-auto.sh; ./make-load "`cat systype`" ) > load chmod 755 load lock.a: \ makelib lock_ex.o lock_exnb.o lock_un.o ./makelib lock.a lock_ex.o lock_exnb.o lock_un.o lock_ex.o: \ compile lock_ex.c hasflock.h lock.h ./compile lock_ex.c lock_exnb.o: \ compile lock_exnb.c hasflock.h lock.h ./compile lock_exnb.c lock_un.o: \ compile lock_un.c hasflock.h lock.h ./compile lock_un.c maildir.0: \ maildir.5 nroff -man maildir.5 > maildir.0 maildir.o: \ compile maildir.c prioq.h datetime.h gen_alloc.h env.h stralloc.h \ gen_alloc.h direntry.h datetime.h now.h datetime.h str.h maildir.h \ strerr.h ./compile maildir.c maildir2mbox: \ load maildir2mbox.o maildir.o prioq.o now.o myctime.o gfrom.o lock.a \ getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \ str.a fs.a datetime.a ./load maildir2mbox maildir.o prioq.o now.o myctime.o \ gfrom.o lock.a getln.a env.a open.a strerr.a stralloc.a \ alloc.a substdio.a error.a str.a fs.a datetime.a maildir2mbox.0: \ maildir2mbox.1 nroff -man maildir2mbox.1 > maildir2mbox.0 maildir2mbox.o: \ compile maildir2mbox.c readwrite.h prioq.h datetime.h gen_alloc.h \ env.h stralloc.h gen_alloc.h subfd.h substdio.h substdio.h getln.h \ error.h open.h lock.h gfrom.h str.h exit.h myctime.h maildir.h \ strerr.h ./compile maildir2mbox.c maildirmake: \ load maildirmake.o strerr.a substdio.a error.a str.a ./load maildirmake strerr.a substdio.a error.a str.a maildirmake.0: \ maildirmake.1 nroff -man maildirmake.1 > maildirmake.0 maildirmake.o: \ compile maildirmake.c strerr.h exit.h ./compile maildirmake.c maildirwatch: \ load maildirwatch.o hfield.o headerbody.o maildir.o prioq.o now.o \ getln.a env.a open.a strerr.a stralloc.a alloc.a substdio.a error.a \ str.a ./load maildirwatch hfield.o headerbody.o maildir.o \ prioq.o now.o getln.a env.a open.a strerr.a stralloc.a \ alloc.a substdio.a error.a str.a maildirwatch.0: \ maildirwatch.1 nroff -man maildirwatch.1 > maildirwatch.0 maildirwatch.o: \ compile maildirwatch.c getln.h substdio.h subfd.h substdio.h prioq.h \ datetime.h gen_alloc.h stralloc.h gen_alloc.h str.h exit.h hfield.h \ readwrite.h open.h headerbody.h maildir.h strerr.h ./compile maildirwatch.c mailsubj: \ warn-auto.sh mailsubj.sh conf-qmail conf-break conf-split cat warn-auto.sh mailsubj.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > mailsubj chmod 755 mailsubj mailsubj.0: \ mailsubj.1 nroff -man mailsubj.1 > mailsubj.0 make-compile: \ make-compile.sh auto-ccld.sh cat auto-ccld.sh make-compile.sh > make-compile chmod 755 make-compile make-load: \ make-load.sh auto-ccld.sh cat auto-ccld.sh make-load.sh > make-load chmod 755 make-load make-makelib: \ make-makelib.sh auto-ccld.sh cat auto-ccld.sh make-makelib.sh > make-makelib chmod 755 make-makelib makelib: \ make-makelib warn-auto.sh systype ( cat warn-auto.sh; ./make-makelib "`cat systype`" ) > \ makelib chmod 755 makelib man: \ qmail-local.0 qmail-lspawn.0 qmail-getpw.0 qmail-remote.0 \ qmail-rspawn.0 qmail-clean.0 qmail-send.0 qmail-start.0 splogger.0 \ qmail-queue.0 qmail-inject.0 mailsubj.0 qmail-showctl.0 qmail-newu.0 \ qmail-pw2u.0 qmail-qread.0 qmail-qstat.0 qmail-tcpto.0 qmail-tcpok.0 \ qmail-pop3d.0 qmail-popup.0 qmail-qmqpc.0 qmail-qmqpd.0 qmail-qmtpd.0 \ qmail-smtpd.0 tcp-env.0 qmail-newmrh.0 qreceipt.0 qbiff.0 forward.0 \ preline.0 condredirect.0 bouncesaying.0 except.0 maildirmake.0 \ maildir2mbox.0 maildirwatch.0 qmail.0 qmail-limits.0 qmail-log.0 \ qmail-control.0 qmail-header.0 qmail-users.0 dot-qmail.0 \ qmail-command.0 tcp-environ.0 maildir.0 mbox.0 addresses.0 \ envelopes.0 forgeries.0 mbox.0: \ mbox.5 nroff -man mbox.5 > mbox.0 myctime.o: \ compile myctime.c datetime.h fmt.h myctime.h ./compile myctime.c ndelay.a: \ makelib ndelay.o ndelay_off.o ./makelib ndelay.a ndelay.o ndelay_off.o ndelay.o: \ compile ndelay.c ndelay.h ./compile ndelay.c ndelay_off.o: \ compile ndelay_off.c ndelay.h ./compile ndelay_off.c newfield.o: \ compile newfield.c fmt.h datetime.h stralloc.h gen_alloc.h \ date822fmt.h newfield.h stralloc.h ./compile newfield.c now.o: \ compile now.c datetime.h now.h datetime.h ./compile now.c open.a: \ makelib open_append.o open_excl.o open_read.o open_trunc.o \ open_write.o ./makelib open.a open_append.o open_excl.o open_read.o \ open_trunc.o open_write.o open_append.o: \ compile open_append.c open.h ./compile open_append.c open_excl.o: \ compile open_excl.c open.h ./compile open_excl.c open_read.o: \ compile open_read.c open.h ./compile open_read.c open_trunc.o: \ compile open_trunc.c open.h ./compile open_trunc.c open_write.o: \ compile open_write.c open.h ./compile open_write.c pinq: \ warn-auto.sh pinq.sh conf-qmail conf-break conf-split cat warn-auto.sh pinq.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > pinq chmod 755 pinq predate: \ load predate.o datetime.a strerr.a sig.a fd.a wait.a substdio.a \ error.a str.a fs.a ./load predate datetime.a strerr.a sig.a fd.a wait.a \ substdio.a error.a str.a fs.a predate.o: \ compile predate.c datetime.h fork.h wait.h fd.h fmt.h strerr.h \ substdio.h subfd.h substdio.h readwrite.h exit.h ./compile predate.c preline: \ load preline.o strerr.a fd.a wait.a sig.a env.a getopt.a substdio.a \ error.a str.a ./load preline strerr.a fd.a wait.a sig.a env.a getopt.a \ substdio.a error.a str.a preline.0: \ preline.1 nroff -man preline.1 > preline.0 preline.o: \ compile preline.c fd.h sgetopt.h subgetopt.h readwrite.h strerr.h \ substdio.h exit.h fork.h wait.h env.h sig.h error.h ./compile preline.c prioq.o: \ compile prioq.c alloc.h gen_allocdefs.h prioq.h datetime.h \ gen_alloc.h ./compile prioq.c proc: \ proc.sh conf-qmail cat proc.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > proc chmod 755 proc proc+df: \ proc+df.sh conf-qmail cat proc+df.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ > proc+df chmod 755 proc+df prot.o: \ compile prot.c hasshsgr.h prot.h ./compile prot.c qail: \ warn-auto.sh qail.sh conf-qmail conf-break conf-split cat warn-auto.sh qail.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > qail chmod 755 qail qbiff: \ load qbiff.o headerbody.o hfield.o getln.a env.a open.a stralloc.a \ alloc.a substdio.a error.a str.a ./load qbiff headerbody.o hfield.o getln.a env.a open.a \ stralloc.a alloc.a substdio.a error.a str.a qbiff.0: \ qbiff.1 nroff -man qbiff.1 > qbiff.0 qbiff.o: \ compile qbiff.c readwrite.h stralloc.h gen_alloc.h substdio.h subfd.h \ substdio.h open.h byte.h str.h headerbody.h hfield.h env.h exit.h ./compile qbiff.c qmail-clean: \ load qmail-clean.o fmtqfn.o now.o getln.a sig.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o ./load qmail-clean fmtqfn.o now.o getln.a sig.a stralloc.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ auto_split.o qmail-clean.0: \ qmail-clean.8 nroff -man qmail-clean.8 > qmail-clean.0 qmail-clean.o: \ compile qmail-clean.c readwrite.h sig.h now.h datetime.h str.h \ direntry.h getln.h stralloc.h gen_alloc.h substdio.h subfd.h \ substdio.h byte.h scan.h fmt.h error.h exit.h fmtqfn.h auto_qmail.h ./compile qmail-clean.c qmail-command.0: \ qmail-command.8 nroff -man qmail-command.8 > qmail-command.0 qmail-control.0: \ qmail-control.5 nroff -man qmail-control.5 > qmail-control.0 qmail-control.5: \ qmail-control.9 conf-break conf-spawn cat qmail-control.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-control.5 qmail-getpw: \ load qmail-getpw.o case.a substdio.a error.a str.a fs.a auto_break.o \ auto_usera.o ./load qmail-getpw case.a substdio.a error.a str.a fs.a \ auto_break.o auto_usera.o qmail-getpw.0: \ qmail-getpw.8 nroff -man qmail-getpw.8 > qmail-getpw.0 qmail-getpw.8: \ qmail-getpw.9 conf-break conf-spawn cat qmail-getpw.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-getpw.8 qmail-getpw.o: \ compile qmail-getpw.c readwrite.h substdio.h subfd.h substdio.h \ error.h exit.h byte.h str.h case.h fmt.h auto_usera.h auto_break.h \ qlx.h ./compile qmail-getpw.c qmail-header.0: \ qmail-header.5 nroff -man qmail-header.5 > qmail-header.0 qmail-inject: \ load qmail-inject.o headerbody.o hfield.o newfield.o quote.o now.o \ control.o date822fmt.o constmap.o qmail.o case.a fd.a wait.a open.a \ getln.a sig.a getopt.a datetime.a token822.o env.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o ./load qmail-inject headerbody.o hfield.o newfield.o \ quote.o now.o control.o date822fmt.o constmap.o qmail.o \ case.a fd.a wait.a open.a getln.a sig.a getopt.a datetime.a \ token822.o env.a stralloc.a alloc.a substdio.a error.a \ str.a fs.a auto_qmail.o qmail-inject.0: \ qmail-inject.8 nroff -man qmail-inject.8 > qmail-inject.0 qmail-inject.o: \ compile qmail-inject.c sig.h substdio.h stralloc.h gen_alloc.h \ subfd.h substdio.h sgetopt.h subgetopt.h getln.h alloc.h str.h fmt.h \ hfield.h token822.h gen_alloc.h control.h env.h gen_alloc.h \ gen_allocdefs.h error.h qmail.h substdio.h now.h datetime.h exit.h \ quote.h headerbody.h auto_qmail.h newfield.h stralloc.h constmap.h ./compile qmail-inject.c qmail-limits.0: \ qmail-limits.7 nroff -man qmail-limits.7 > qmail-limits.0 qmail-limits.7: \ qmail-limits.9 conf-break conf-spawn cat qmail-limits.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-limits.7 qmail-local: \ load qmail-local.o qmail.o quote.o now.o gfrom.o myctime.o \ slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a lock.a fd.a \ wait.a env.a stralloc.a alloc.a strerr.a substdio.a error.a str.a \ fs.a datetime.a auto_qmail.o auto_patrn.o socket.lib ./load qmail-local qmail.o quote.o now.o gfrom.o myctime.o \ slurpclose.o case.a getln.a getopt.a sig.a open.a seek.a \ lock.a fd.a wait.a env.a stralloc.a alloc.a strerr.a \ substdio.a error.a str.a fs.a datetime.a auto_qmail.o \ auto_patrn.o `cat socket.lib` qmail-local.0: \ qmail-local.8 nroff -man qmail-local.8 > qmail-local.0 qmail-local.o: \ compile qmail-local.c readwrite.h sig.h env.h byte.h exit.h fork.h \ open.h wait.h lock.h seek.h substdio.h getln.h strerr.h subfd.h \ substdio.h sgetopt.h subgetopt.h alloc.h error.h stralloc.h \ gen_alloc.h fmt.h str.h now.h datetime.h case.h quote.h qmail.h \ substdio.h slurpclose.h myctime.h gfrom.h auto_patrn.h ./compile qmail-local.c qmail-log.0: \ qmail-log.5 nroff -man qmail-log.5 > qmail-log.0 qmail-lspawn: \ load qmail-lspawn.o spawn.o prot.o slurpclose.o coe.o sig.a wait.a \ case.a cdb.a fd.a open.a stralloc.a alloc.a substdio.a error.a str.a \ fs.a auto_qmail.o auto_uids.o auto_spawn.o ./load qmail-lspawn spawn.o prot.o slurpclose.o coe.o \ sig.a wait.a case.a cdb.a fd.a open.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o auto_uids.o \ auto_spawn.o qmail-lspawn.0: \ qmail-lspawn.8 nroff -man qmail-lspawn.8 > qmail-lspawn.0 qmail-lspawn.o: \ compile qmail-lspawn.c fd.h wait.h prot.h substdio.h stralloc.h \ gen_alloc.h scan.h exit.h fork.h error.h cdb.h uint32.h case.h \ slurpclose.h auto_qmail.h auto_uids.h qlx.h ./compile qmail-lspawn.c qmail-newmrh: \ load qmail-newmrh.o cdbmss.o getln.a open.a cdbmake.a seek.a case.a \ stralloc.a alloc.a strerr.a substdio.a error.a str.a auto_qmail.o ./load qmail-newmrh cdbmss.o getln.a open.a cdbmake.a \ seek.a case.a stralloc.a alloc.a strerr.a substdio.a \ error.a str.a auto_qmail.o qmail-newmrh.0: \ qmail-newmrh.8 nroff -man qmail-newmrh.8 > qmail-newmrh.0 qmail-newmrh.8: \ qmail-newmrh.9 conf-break conf-spawn cat qmail-newmrh.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-newmrh.8 qmail-newmrh.o: \ compile qmail-newmrh.c strerr.h stralloc.h gen_alloc.h substdio.h \ getln.h exit.h readwrite.h open.h auto_qmail.h cdbmss.h cdbmake.h \ uint32.h substdio.h ./compile qmail-newmrh.c qmail-newu: \ load qmail-newu.o cdbmss.o getln.a open.a seek.a cdbmake.a case.a \ stralloc.a alloc.a substdio.a error.a str.a auto_qmail.o ./load qmail-newu cdbmss.o getln.a open.a seek.a cdbmake.a \ case.a stralloc.a alloc.a substdio.a error.a str.a \ auto_qmail.o qmail-newu.0: \ qmail-newu.8 nroff -man qmail-newu.8 > qmail-newu.0 qmail-newu.8: \ qmail-newu.9 conf-break conf-spawn cat qmail-newu.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-newu.8 qmail-newu.o: \ compile qmail-newu.c stralloc.h gen_alloc.h subfd.h substdio.h \ getln.h substdio.h cdbmss.h cdbmake.h uint32.h substdio.h exit.h \ readwrite.h open.h error.h case.h auto_qmail.h ./compile qmail-newu.c qmail-pop3d: \ load qmail-pop3d.o commands.o case.a timeoutread.o timeoutwrite.o \ maildir.o prioq.o now.o env.a strerr.a sig.a open.a getln.a \ stralloc.a alloc.a substdio.a error.a str.a fs.a socket.lib ./load qmail-pop3d commands.o case.a timeoutread.o \ timeoutwrite.o maildir.o prioq.o now.o env.a strerr.a sig.a \ open.a getln.a stralloc.a alloc.a substdio.a error.a str.a \ fs.a `cat socket.lib` qmail-pop3d.0: \ qmail-pop3d.8 nroff -man qmail-pop3d.8 > qmail-pop3d.0 qmail-pop3d.o: \ compile qmail-pop3d.c commands.h sig.h getln.h stralloc.h gen_alloc.h \ substdio.h alloc.h open.h prioq.h datetime.h gen_alloc.h scan.h fmt.h \ str.h exit.h maildir.h strerr.h readwrite.h timeoutread.h \ timeoutwrite.h ./compile qmail-pop3d.c qmail-popup: \ load qmail-popup.o commands.o timeoutread.o timeoutwrite.o now.o \ case.a fd.a sig.a wait.a stralloc.a alloc.a substdio.a error.a str.a \ fs.a socket.lib ./load qmail-popup commands.o timeoutread.o timeoutwrite.o \ now.o case.a fd.a sig.a wait.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a `cat socket.lib` qmail-popup.0: \ qmail-popup.8 nroff -man qmail-popup.8 > qmail-popup.0 qmail-popup.o: \ compile qmail-popup.c commands.h fd.h sig.h stralloc.h gen_alloc.h \ substdio.h alloc.h wait.h str.h byte.h now.h datetime.h fmt.h exit.h \ readwrite.h timeoutread.h timeoutwrite.h ./compile qmail-popup.c qmail-pw2u: \ load qmail-pw2u.o constmap.o control.o open.a getln.a case.a getopt.a \ stralloc.a alloc.a substdio.a error.a str.a fs.a auto_usera.o \ auto_break.o auto_qmail.o ./load qmail-pw2u constmap.o control.o open.a getln.a \ case.a getopt.a stralloc.a alloc.a substdio.a error.a str.a \ fs.a auto_usera.o auto_break.o auto_qmail.o qmail-pw2u.0: \ qmail-pw2u.8 nroff -man qmail-pw2u.8 > qmail-pw2u.0 qmail-pw2u.8: \ qmail-pw2u.9 conf-break conf-spawn cat qmail-pw2u.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-pw2u.8 qmail-pw2u.o: \ compile qmail-pw2u.c substdio.h readwrite.h subfd.h substdio.h \ sgetopt.h subgetopt.h control.h constmap.h stralloc.h gen_alloc.h \ fmt.h str.h scan.h open.h error.h getln.h auto_break.h auto_qmail.h \ auto_usera.h ./compile qmail-pw2u.c qmail-qmqpc: \ load qmail-qmqpc.o slurpclose.o timeoutread.o timeoutwrite.o \ timeoutconn.o ip.o control.o auto_qmail.o sig.a ndelay.a open.a \ getln.a substdio.a stralloc.a alloc.a error.a str.a fs.a socket.lib ./load qmail-qmqpc slurpclose.o timeoutread.o \ timeoutwrite.o timeoutconn.o ip.o control.o auto_qmail.o \ sig.a ndelay.a open.a getln.a substdio.a stralloc.a alloc.a \ error.a str.a fs.a `cat socket.lib` qmail-qmqpc.0: \ qmail-qmqpc.8 nroff -man qmail-qmqpc.8 > qmail-qmqpc.0 qmail-qmqpc.o: \ compile qmail-qmqpc.c substdio.h getln.h readwrite.h exit.h \ stralloc.h gen_alloc.h slurpclose.h error.h sig.h ip.h timeoutconn.h \ timeoutread.h timeoutwrite.h auto_qmail.h control.h fmt.h ./compile qmail-qmqpc.c qmail-qmqpd: \ load qmail-qmqpd.o received.o now.o date822fmt.o qmail.o auto_qmail.o \ env.a substdio.a sig.a error.a wait.a fd.a str.a datetime.a fs.a ./load qmail-qmqpd received.o now.o date822fmt.o qmail.o \ auto_qmail.o env.a substdio.a sig.a error.a wait.a fd.a \ str.a datetime.a fs.a qmail-qmqpd.0: \ qmail-qmqpd.8 nroff -man qmail-qmqpd.8 > qmail-qmqpd.0 qmail-qmqpd.o: \ compile qmail-qmqpd.c auto_qmail.h qmail.h substdio.h received.h \ sig.h substdio.h readwrite.h exit.h now.h datetime.h fmt.h env.h ./compile qmail-qmqpd.c qmail-qmtpd: \ load qmail-qmtpd.o rcpthosts.o control.o constmap.o received.o \ date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a open.a \ getln.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a \ str.a fs.a auto_qmail.o ./load qmail-qmtpd rcpthosts.o control.o constmap.o \ received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ datetime.a open.a getln.a sig.a case.a env.a stralloc.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o qmail-qmtpd.0: \ qmail-qmtpd.8 nroff -man qmail-qmtpd.8 > qmail-qmtpd.0 qmail-qmtpd.o: \ compile qmail-qmtpd.c stralloc.h gen_alloc.h substdio.h qmail.h \ substdio.h now.h datetime.h str.h fmt.h env.h sig.h rcpthosts.h \ auto_qmail.h readwrite.h control.h received.h ./compile qmail-qmtpd.c qmail-qread: \ load qmail-qread.o fmtqfn.o readsubdir.o date822fmt.o datetime.a \ open.a getln.a stralloc.a alloc.a substdio.a error.a str.a fs.a \ auto_qmail.o auto_split.o ./load qmail-qread fmtqfn.o readsubdir.o date822fmt.o \ datetime.a open.a getln.a stralloc.a alloc.a substdio.a \ error.a str.a fs.a auto_qmail.o auto_split.o qmail-qread.0: \ qmail-qread.8 nroff -man qmail-qread.8 > qmail-qread.0 qmail-qread.o: \ compile qmail-qread.c stralloc.h gen_alloc.h substdio.h subfd.h \ substdio.h fmt.h str.h getln.h fmtqfn.h readsubdir.h direntry.h \ auto_qmail.h open.h datetime.h date822fmt.h readwrite.h error.h \ exit.h ./compile qmail-qread.c qmail-qstat: \ warn-auto.sh qmail-qstat.sh conf-qmail conf-break conf-split cat warn-auto.sh qmail-qstat.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > qmail-qstat chmod 755 qmail-qstat qmail-qstat.0: \ qmail-qstat.8 nroff -man qmail-qstat.8 > qmail-qstat.0 qmail-queue: \ load qmail-queue.o triggerpull.o fmtqfn.o now.o date822fmt.o \ datetime.a seek.a ndelay.a open.a sig.a alloc.a substdio.a error.a \ str.a fs.a auto_qmail.o auto_split.o auto_uids.o ./load qmail-queue triggerpull.o fmtqfn.o now.o \ date822fmt.o datetime.a seek.a ndelay.a open.a sig.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ auto_split.o auto_uids.o qmail-queue.0: \ qmail-queue.8 nroff -man qmail-queue.8 > qmail-queue.0 qmail-queue.o: \ compile qmail-queue.c readwrite.h sig.h exit.h open.h seek.h fmt.h \ alloc.h substdio.h datetime.h now.h datetime.h triggerpull.h extra.h \ auto_qmail.h auto_uids.h date822fmt.h fmtqfn.h ./compile qmail-queue.c qmail-remote: \ load qmail-remote.o control.o constmap.o timeoutread.o timeoutwrite.o \ timeoutconn.o tcpto.o now.o dns.o ip.o ipalloc.o ipme.o quote.o \ ndelay.a case.a sig.a open.a lock.a seek.a getln.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o dns.lib socket.lib ./load qmail-remote control.o constmap.o timeoutread.o \ timeoutwrite.o timeoutconn.o tcpto.o now.o dns.o ip.o \ ipalloc.o ipme.o quote.o ndelay.a case.a sig.a open.a \ lock.a seek.a getln.a stralloc.a alloc.a substdio.a error.a \ str.a fs.a auto_qmail.o `cat dns.lib` `cat socket.lib` qmail-remote.0: \ qmail-remote.8 nroff -man qmail-remote.8 > qmail-remote.0 qmail-remote.o: \ compile qmail-remote.c sig.h stralloc.h gen_alloc.h substdio.h \ subfd.h substdio.h scan.h case.h error.h auto_qmail.h control.h dns.h \ alloc.h quote.h ip.h ipalloc.h ip.h gen_alloc.h ipme.h ip.h ipalloc.h \ gen_alloc.h gen_allocdefs.h str.h now.h datetime.h exit.h constmap.h \ tcpto.h readwrite.h timeoutconn.h timeoutread.h timeoutwrite.h ./compile qmail-remote.c qmail-rspawn: \ load qmail-rspawn.o spawn.o tcpto_clean.o now.o coe.o sig.a open.a \ seek.a lock.a wait.a fd.a stralloc.a alloc.a substdio.a error.a str.a \ auto_qmail.o auto_uids.o auto_spawn.o ./load qmail-rspawn spawn.o tcpto_clean.o now.o coe.o \ sig.a open.a seek.a lock.a wait.a fd.a stralloc.a alloc.a \ substdio.a error.a str.a auto_qmail.o auto_uids.o \ auto_spawn.o qmail-rspawn.0: \ qmail-rspawn.8 nroff -man qmail-rspawn.8 > qmail-rspawn.0 qmail-rspawn.o: \ compile qmail-rspawn.c fd.h wait.h substdio.h exit.h fork.h error.h \ tcpto.h ./compile qmail-rspawn.c qmail-send: \ load qmail-send.o qsutil.o control.o constmap.o newfield.o prioq.o \ trigger.o fmtqfn.o quote.o now.o readsubdir.o qmail.o date822fmt.o \ datetime.a case.a ndelay.a getln.a wait.a seek.a fd.a sig.a open.a \ lock.a stralloc.a alloc.a substdio.a error.a str.a fs.a auto_qmail.o \ auto_split.o env.a ./load qmail-send qsutil.o control.o constmap.o newfield.o \ prioq.o trigger.o fmtqfn.o quote.o now.o readsubdir.o \ qmail.o date822fmt.o datetime.a case.a ndelay.a getln.a \ wait.a seek.a fd.a sig.a open.a lock.a stralloc.a alloc.a \ substdio.a error.a str.a fs.a auto_qmail.o auto_split.o env.a qmail-send.0: \ qmail-send.8 nroff -man qmail-send.8 > qmail-send.0 qmail-send.8: \ qmail-send.9 conf-break conf-spawn cat qmail-send.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-send.8 qmail-send.o: \ compile qmail-send.c readwrite.h sig.h direntry.h control.h select.h \ open.h seek.h exit.h lock.h ndelay.h now.h datetime.h getln.h \ substdio.h alloc.h error.h stralloc.h gen_alloc.h str.h byte.h fmt.h \ scan.h case.h auto_qmail.h trigger.h newfield.h stralloc.h quote.h \ qmail.h substdio.h qsutil.h prioq.h datetime.h gen_alloc.h constmap.h \ fmtqfn.h readsubdir.h direntry.h ./compile qmail-send.c qmail-showctl: \ load qmail-showctl.o auto_uids.o control.o open.a getln.a stralloc.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o auto_break.o \ auto_patrn.o auto_spawn.o auto_split.o ./load qmail-showctl auto_uids.o control.o open.a getln.a \ stralloc.a alloc.a substdio.a error.a str.a fs.a \ auto_qmail.o auto_break.o auto_patrn.o auto_spawn.o \ auto_split.o qmail-showctl.0: \ qmail-showctl.8 nroff -man qmail-showctl.8 > qmail-showctl.0 qmail-showctl.o: \ compile qmail-showctl.c substdio.h subfd.h substdio.h exit.h fmt.h \ str.h control.h constmap.h stralloc.h gen_alloc.h direntry.h \ auto_uids.h auto_qmail.h auto_break.h auto_patrn.h auto_spawn.h \ auto_split.h ./compile qmail-showctl.c qmail-smtpd: \ load qmail-smtpd.o rcpthosts.o commands.o timeoutread.o \ timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o received.o \ date822fmt.o now.o qmail.o cdb.a fd.a wait.a datetime.a getln.a \ open.a sig.a case.a env.a stralloc.a alloc.a substdio.a error.a str.a \ fs.a auto_qmail.o socket.lib ./load qmail-smtpd rcpthosts.o commands.o timeoutread.o \ timeoutwrite.o ip.o ipme.o ipalloc.o control.o constmap.o \ received.o date822fmt.o now.o qmail.o cdb.a fd.a wait.a \ datetime.a getln.a open.a sig.a case.a env.a stralloc.a \ alloc.a substdio.a error.a str.a fs.a auto_qmail.o `cat \ socket.lib` qmail-smtpd.0: \ qmail-smtpd.8 nroff -man qmail-smtpd.8 > qmail-smtpd.0 qmail-smtpd.o: \ compile qmail-smtpd.c sig.h readwrite.h stralloc.h gen_alloc.h \ substdio.h alloc.h auto_qmail.h control.h received.h constmap.h \ error.h ipme.h ip.h ipalloc.h ip.h gen_alloc.h ip.h qmail.h \ substdio.h str.h fmt.h scan.h byte.h case.h env.h now.h datetime.h \ exit.h rcpthosts.h timeoutread.h timeoutwrite.h commands.h ./compile qmail-smtpd.c qmail-start: \ load qmail-start.o prot.o fd.a auto_uids.o ./load qmail-start prot.o fd.a auto_uids.o qmail-start.0: \ qmail-start.8 nroff -man qmail-start.8 > qmail-start.0 qmail-start.8: \ qmail-start.9 conf-break conf-spawn cat qmail-start.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-start.8 qmail-start.o: \ compile qmail-start.c fd.h prot.h exit.h fork.h auto_uids.h ./compile qmail-start.c qmail-tcpok: \ load qmail-tcpok.o open.a lock.a strerr.a substdio.a error.a str.a \ auto_qmail.o ./load qmail-tcpok open.a lock.a strerr.a substdio.a \ error.a str.a auto_qmail.o qmail-tcpok.0: \ qmail-tcpok.8 nroff -man qmail-tcpok.8 > qmail-tcpok.0 qmail-tcpok.o: \ compile qmail-tcpok.c strerr.h substdio.h lock.h open.h readwrite.h \ auto_qmail.h exit.h ./compile qmail-tcpok.c qmail-tcpto: \ load qmail-tcpto.o ip.o now.o open.a lock.a substdio.a error.a str.a \ fs.a auto_qmail.o ./load qmail-tcpto ip.o now.o open.a lock.a substdio.a \ error.a str.a fs.a auto_qmail.o qmail-tcpto.0: \ qmail-tcpto.8 nroff -man qmail-tcpto.8 > qmail-tcpto.0 qmail-tcpto.o: \ compile qmail-tcpto.c substdio.h subfd.h substdio.h auto_qmail.h \ fmt.h ip.h lock.h error.h exit.h datetime.h now.h datetime.h ./compile qmail-tcpto.c qmail-upq: \ warn-auto.sh qmail-upq.sh conf-qmail conf-break conf-split cat warn-auto.sh qmail-upq.sh \ | sed s}QMAIL}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPLIT}"`head -1 conf-split`"}g \ > qmail-upq chmod 755 qmail-upq qmail-users.0: \ qmail-users.5 nroff -man qmail-users.5 > qmail-users.0 qmail-users.5: \ qmail-users.9 conf-break conf-spawn cat qmail-users.9 \ | sed s}QMAILHOME}"`head -1 conf-qmail`"}g \ | sed s}BREAK}"`head -1 conf-break`"}g \ | sed s}SPAWN}"`head -1 conf-spawn`"}g \ > qmail-users.5 qmail.0: \ qmail.7 nroff -man qmail.7 > qmail.0 qmail.o: \ compile qmail.c substdio.h readwrite.h wait.h exit.h fork.h fd.h \ qmail.h substdio.h auto_qmail.h ./compile qmail.c qreceipt: \ load qreceipt.o headerbody.o hfield.o quote.o token822.o qmail.o \ getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a substdio.a error.a \ str.a auto_qmail.o ./load qreceipt headerbody.o hfield.o quote.o token822.o \ qmail.o getln.a fd.a wait.a sig.a env.a stralloc.a alloc.a \ substdio.a error.a str.a auto_qmail.o qreceipt.0: \ qreceipt.1 nroff -man qreceipt.1 > qreceipt.0 qreceipt.o: \ compile qreceipt.c sig.h env.h substdio.h stralloc.h gen_alloc.h \ subfd.h substdio.h getln.h alloc.h str.h hfield.h token822.h \ gen_alloc.h error.h gen_alloc.h gen_allocdefs.h headerbody.h exit.h \ open.h quote.h qmail.h substdio.h ./compile qreceipt.c qsmhook: \ load qsmhook.o sig.a case.a fd.a wait.a getopt.a env.a stralloc.a \ alloc.a substdio.a error.a str.a ./load qsmhook sig.a case.a fd.a wait.a getopt.a env.a \ stralloc.a alloc.a substdio.a error.a str.a qsmhook.o: \ compile qsmhook.c fd.h stralloc.h gen_alloc.h readwrite.h sgetopt.h \ subgetopt.h wait.h env.h byte.h str.h alloc.h exit.h fork.h case.h \ subfd.h substdio.h error.h substdio.h sig.h ./compile qsmhook.c qsutil.o: \ compile qsutil.c stralloc.h gen_alloc.h readwrite.h substdio.h \ qsutil.h ./compile qsutil.c quote.o: \ compile quote.c stralloc.h gen_alloc.h str.h quote.h ./compile quote.c rcpthosts.o: \ compile rcpthosts.c cdb.h uint32.h byte.h open.h error.h control.h \ constmap.h stralloc.h gen_alloc.h rcpthosts.h ./compile rcpthosts.c readsubdir.o: \ compile readsubdir.c readsubdir.h direntry.h fmt.h scan.h str.h \ auto_split.h ./compile readsubdir.c received.o: \ compile received.c fmt.h qmail.h substdio.h now.h datetime.h \ datetime.h date822fmt.h received.h ./compile received.c remoteinfo.o: \ compile remoteinfo.c byte.h substdio.h ip.h fmt.h timeoutconn.h \ timeoutread.h timeoutwrite.h remoteinfo.h ./compile remoteinfo.c scan_8long.o: \ compile scan_8long.c scan.h ./compile scan_8long.c scan_ulong.o: \ compile scan_ulong.c scan.h ./compile scan_ulong.c seek.a: \ makelib seek_cur.o seek_end.o seek_set.o seek_trunc.o ./makelib seek.a seek_cur.o seek_end.o seek_set.o \ seek_trunc.o seek_cur.o: \ compile seek_cur.c seek.h ./compile seek_cur.c seek_end.o: \ compile seek_end.c seek.h ./compile seek_end.c seek_set.o: \ compile seek_set.c seek.h ./compile seek_set.c seek_trunc.o: \ compile seek_trunc.c seek.h ./compile seek_trunc.c select.h: \ compile trysysel.c select.h1 select.h2 ( ./compile trysysel.c >/dev/null 2>&1 \ && cat select.h2 || cat select.h1 ) > select.h rm -f trysysel.o trysysel sendmail: \ load sendmail.o env.a getopt.a alloc.a substdio.a error.a str.a \ auto_qmail.o ./load sendmail env.a getopt.a alloc.a substdio.a error.a \ str.a auto_qmail.o sendmail.o: \ compile sendmail.c sgetopt.h subgetopt.h substdio.h subfd.h \ substdio.h alloc.h auto_qmail.h exit.h env.h str.h ./compile sendmail.c setup: \ it man ./install sgetopt.o: \ compile sgetopt.c substdio.h subfd.h substdio.h sgetopt.h subgetopt.h \ subgetopt.h ./compile sgetopt.c shar: \ FILES BLURB BLURB2 BLURB3 BLURB4 README FAQ INSTALL INSTALL.alias \ INSTALL.ctl INSTALL.ids INSTALL.maildir INSTALL.mbox INSTALL.vsm \ REMOVE.sendmail REMOVE.binmail TEST.deliver TEST.receive UPGRADE \ THOUGHTS TODO THANKS CHANGES SECURITY INTERNALS SENDMAIL \ PIC.local2alias PIC.local2ext PIC.local2local PIC.local2rem \ PIC.local2virt PIC.nullclient PIC.relaybad PIC.relaygood \ PIC.rem2local FILES VERSION SYSDEPS TARGETS Makefile BIN.README \ BIN.Makefile BIN.setup idedit.c conf-break auto_break.h conf-spawn \ auto_spawn.h chkspawn.c conf-split auto_split.h conf-patrn \ auto_patrn.h conf-users conf-groups auto_uids.h auto_usera.h extra.h \ addresses.5 except.1 bouncesaying.1 condredirect.1 dot-qmail.9 \ envelopes.5 forgeries.7 forward.1 maildir2mbox.1 maildirmake.1 \ maildirwatch.1 mailsubj.1 mbox.5 preline.1 qbiff.1 qmail-clean.8 \ qmail-command.8 qmail-control.9 qmail-getpw.9 qmail-header.5 \ qmail-inject.8 qmail-limits.9 qmail-local.8 qmail-log.5 \ qmail-lspawn.8 qmail-newmrh.9 qmail-newu.9 qmail-pop3d.8 \ qmail-popup.8 qmail-pw2u.9 qmail-qmqpc.8 qmail-qmqpd.8 qmail-qmtpd.8 \ qmail-qread.8 qmail-qstat.8 qmail-queue.8 qmail-remote.8 \ qmail-rspawn.8 qmail-send.9 qmail-showctl.8 qmail-smtpd.8 \ qmail-start.9 qmail-tcpok.8 qmail-tcpto.8 qmail-users.9 qmail.7 \ qreceipt.1 splogger.8 tcp-env.1 config.sh config-fast.sh \ qmail-clean.c qmail-getpw.c qmail-inject.c qmail-local.c \ qmail-lspawn.c qmail-newmrh.c qmail-newu.c qmail-pop3d.c \ qmail-popup.c qmail-pw2u.c qmail-qmqpc.c qmail-qmqpd.c qmail-qmtpd.c \ qmail-qread.c qmail-qstat.sh qmail-queue.c qmail-remote.c \ qmail-rspawn.c qmail-send.c qmail-showctl.c qmail-smtpd.c \ qmail-start.c qmail-tcpok.c qmail-tcpto.c spawn.c dnscname.c dnsfq.c \ dnsip.c dnsmxip.c dnsptr.c hostname.c ipmeprint.c tcp-env.c \ sendmail.c qreceipt.c qsmhook.c qbiff.c forward.c preline.c predate.c \ except.c bouncesaying.c condredirect.c maildirmake.c maildir2mbox.c \ maildirwatch.c splogger.c qail.sh elq.sh pinq.sh qmail-upq.sh \ datemail.sh mailsubj.sh qlx.h rcpthosts.h rcpthosts.c commands.h \ commands.c dnsdoe.h dnsdoe.c fmtqfn.h fmtqfn.c gfrom.h gfrom.c \ myctime.h myctime.c newfield.h newfield.c qsutil.h qsutil.c \ readsubdir.h readsubdir.c received.h received.c tcpto.h tcpto.c \ tcpto_clean.c trigger.h trigger.c triggerpull.h triggerpull.c \ trynpbg1.c trysyslog.c conf-cc conf-ld home.sh home+df.sh proc.sh \ proc+df.sh binm1.sh binm2.sh binm3.sh binm1+df.sh binm2+df.sh \ binm3+df.sh find-systype.sh make-compile.sh make-load.sh \ make-makelib.sh trycpp.c warn-auto.sh auto-str.c auto-int.c \ auto-int8.c auto-gid.c auto-uid.c hier.c install.c instcheck.c \ install-big.c alloc.3 alloc.h alloc.c alloc_re.c case.3 case.h \ case_diffb.c case_diffs.c case_lowerb.c case_lowers.c case_starts.c \ cdb.3 cdb.h cdb_hash.c cdb_seek.c cdb_unpack.c cdbmake.h \ cdbmake_add.c cdbmake_hash.c cdbmake_pack.c cdbmss.h cdbmss.c coe.3 \ coe.h coe.c fd.h fd_copy.3 fd_copy.c fd_move.3 fd_move.c fifo_make.3 \ fifo.h fifo.c trymkffo.c fork.h1 fork.h2 tryvfork.c now.3 now.h now.c \ open.h open_append.c open_excl.c open_read.c open_trunc.c \ open_write.c seek.h seek_cur.c seek_end.c seek_set.c seek_trunc.c \ conf-qmail auto_qmail.h qmail.h qmail.c gen_alloc.h gen_allocdefs.h \ stralloc.3 stralloc.h stralloc_eady.c stralloc_pend.c stralloc_copy.c \ stralloc_opyb.c stralloc_opys.c stralloc_cat.c stralloc_catb.c \ stralloc_cats.c stralloc_arts.c strerr.h strerr_sys.c strerr_die.c \ substdio.h substdio.c substdi.c substdo.c substdio_copy.c subfd.h \ subfderr.c subfdouts.c subfdout.c subfdins.c subfdin.c readwrite.h \ exit.h timeoutconn.h timeoutconn.c timeoutread.h timeoutread.c \ timeoutwrite.h timeoutwrite.c remoteinfo.h remoteinfo.c uint32.h1 \ uint32.h2 tryulong32.c wait.3 wait.h wait_pid.c wait_nohang.c \ trywaitp.c sig.h sig_alarm.c sig_block.c sig_catch.c sig_pause.c \ sig_pipe.c sig_child.c sig_term.c sig_hup.c sig_misc.c sig_bug.c \ trysgact.c trysgprm.c env.3 env.h env.c envread.c byte.h byte_chr.c \ byte_copy.c byte_cr.c byte_diff.c byte_rchr.c byte_zero.c str.h \ str_chr.c str_cpy.c str_diff.c str_diffn.c str_len.c str_rchr.c \ str_start.c lock.h lock_ex.c lock_exnb.c lock_un.c tryflock.c getln.3 \ getln.h getln.c getln2.3 getln2.c sgetopt.3 sgetopt.h sgetopt.c \ subgetopt.3 subgetopt.h subgetopt.c error.3 error_str.3 error_temp.3 \ error.h error.c error_str.c error_temp.c fmt.h fmt_str.c fmt_strn.c \ fmt_uint.c fmt_uint0.c fmt_ulong.c scan.h scan_ulong.c scan_8long.c \ slurpclose.h slurpclose.c quote.h quote.c hfield.h hfield.c \ headerbody.h headerbody.c token822.h token822.c control.h control.c \ datetime.3 datetime.h datetime.c datetime_un.c prioq.h prioq.c \ date822fmt.h date822fmt.c dns.h dns.c trylsock.c tryrsolv.c ip.h ip.c \ ipalloc.h ipalloc.c select.h1 select.h2 trysysel.c ndelay.h ndelay.c \ ndelay_off.c direntry.3 direntry.h1 direntry.h2 trydrent.c prot.h \ prot.c chkshsgr.c warn-shsgr tryshsgr.c ipme.h ipme.c trysalen.c \ maildir.5 maildir.h maildir.c tcp-environ.5 constmap.h constmap.c shar -m `cat FILES` > shar chmod 400 shar sig.a: \ makelib sig_alarm.o sig_block.o sig_catch.o sig_pause.o sig_pipe.o \ sig_child.o sig_hup.o sig_term.o sig_bug.o sig_misc.o ./makelib sig.a sig_alarm.o sig_block.o sig_catch.o \ sig_pause.o sig_pipe.o sig_child.o sig_hup.o sig_term.o \ sig_bug.o sig_misc.o sig_alarm.o: \ compile sig_alarm.c sig.h ./compile sig_alarm.c sig_block.o: \ compile sig_block.c sig.h hassgprm.h ./compile sig_block.c sig_bug.o: \ compile sig_bug.c sig.h ./compile sig_bug.c sig_catch.o: \ compile sig_catch.c sig.h hassgact.h ./compile sig_catch.c sig_child.o: \ compile sig_child.c sig.h ./compile sig_child.c sig_hup.o: \ compile sig_hup.c sig.h ./compile sig_hup.c sig_misc.o: \ compile sig_misc.c sig.h ./compile sig_misc.c sig_pause.o: \ compile sig_pause.c sig.h hassgprm.h ./compile sig_pause.c sig_pipe.o: \ compile sig_pipe.c sig.h ./compile sig_pipe.c sig_term.o: \ compile sig_term.c sig.h ./compile sig_term.c slurpclose.o: \ compile slurpclose.c stralloc.h gen_alloc.h readwrite.h slurpclose.h \ error.h ./compile slurpclose.c socket.lib: \ trylsock.c compile load ( ( ./compile trylsock.c && \ ./load trylsock -lsocket -lnsl ) >/dev/null 2>&1 \ && echo -lsocket -lnsl || exit 0 ) > socket.lib rm -f trylsock.o trylsock spawn.o: \ compile chkspawn spawn.c sig.h wait.h substdio.h byte.h str.h \ stralloc.h gen_alloc.h select.h exit.h alloc.h coe.h open.h error.h \ auto_qmail.h auto_uids.h auto_spawn.h ./chkspawn ./compile spawn.c splogger: \ load splogger.o substdio.a error.a str.a fs.a syslog.lib socket.lib ./load splogger substdio.a error.a str.a fs.a `cat \ syslog.lib` `cat socket.lib` splogger.0: \ splogger.8 nroff -man splogger.8 > splogger.0 splogger.o: \ compile splogger.c error.h substdio.h subfd.h substdio.h exit.h str.h \ scan.h fmt.h ./compile splogger.c str.a: \ makelib str_len.o str_diff.o str_diffn.o str_cpy.o str_chr.o \ str_rchr.o str_start.o byte_chr.o byte_rchr.o byte_diff.o byte_copy.o \ byte_cr.o byte_zero.o ./makelib str.a str_len.o str_diff.o str_diffn.o str_cpy.o \ str_chr.o str_rchr.o str_start.o byte_chr.o byte_rchr.o \ byte_diff.o byte_copy.o byte_cr.o byte_zero.o str_chr.o: \ compile str_chr.c str.h ./compile str_chr.c str_cpy.o: \ compile str_cpy.c str.h ./compile str_cpy.c str_diff.o: \ compile str_diff.c str.h ./compile str_diff.c str_diffn.o: \ compile str_diffn.c str.h ./compile str_diffn.c str_len.o: \ compile str_len.c str.h ./compile str_len.c str_rchr.o: \ compile str_rchr.c str.h ./compile str_rchr.c str_start.o: \ compile str_start.c str.h ./compile str_start.c stralloc.a: \ makelib stralloc_eady.o stralloc_pend.o stralloc_copy.o \ stralloc_opys.o stralloc_opyb.o stralloc_cat.o stralloc_cats.o \ stralloc_catb.o stralloc_arts.o ./makelib stralloc.a stralloc_eady.o stralloc_pend.o \ stralloc_copy.o stralloc_opys.o stralloc_opyb.o \ stralloc_cat.o stralloc_cats.o stralloc_catb.o \ stralloc_arts.o stralloc_arts.o: \ compile stralloc_arts.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_arts.c stralloc_cat.o: \ compile stralloc_cat.c byte.h stralloc.h gen_alloc.h ./compile stralloc_cat.c stralloc_catb.o: \ compile stralloc_catb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_catb.c stralloc_cats.o: \ compile stralloc_cats.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_cats.c stralloc_copy.o: \ compile stralloc_copy.c byte.h stralloc.h gen_alloc.h ./compile stralloc_copy.c stralloc_eady.o: \ compile stralloc_eady.c alloc.h stralloc.h gen_alloc.h \ gen_allocdefs.h ./compile stralloc_eady.c stralloc_opyb.o: \ compile stralloc_opyb.c stralloc.h gen_alloc.h byte.h ./compile stralloc_opyb.c stralloc_opys.o: \ compile stralloc_opys.c byte.h str.h stralloc.h gen_alloc.h ./compile stralloc_opys.c stralloc_pend.o: \ compile stralloc_pend.c alloc.h stralloc.h gen_alloc.h \ gen_allocdefs.h ./compile stralloc_pend.c strerr.a: \ makelib strerr_sys.o strerr_die.o ./makelib strerr.a strerr_sys.o strerr_die.o strerr_die.o: \ compile strerr_die.c substdio.h subfd.h substdio.h exit.h strerr.h ./compile strerr_die.c strerr_sys.o: \ compile strerr_sys.c error.h strerr.h ./compile strerr_sys.c subfderr.o: \ compile subfderr.c readwrite.h substdio.h subfd.h substdio.h ./compile subfderr.c subfdin.o: \ compile subfdin.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdin.c subfdins.o: \ compile subfdins.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdins.c subfdout.o: \ compile subfdout.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdout.c subfdouts.o: \ compile subfdouts.c readwrite.h substdio.h subfd.h substdio.h ./compile subfdouts.c subgetopt.o: \ compile subgetopt.c subgetopt.h ./compile subgetopt.c substdi.o: \ compile substdi.c substdio.h byte.h error.h ./compile substdi.c substdio.a: \ makelib substdio.o substdi.o substdo.o subfderr.o subfdout.o \ subfdouts.o subfdin.o subfdins.o substdio_copy.o ./makelib substdio.a substdio.o substdi.o substdo.o \ subfderr.o subfdout.o subfdouts.o subfdin.o subfdins.o \ substdio_copy.o substdio.o: \ compile substdio.c substdio.h ./compile substdio.c substdio_copy.o: \ compile substdio_copy.c substdio.h ./compile substdio_copy.c substdo.o: \ compile substdo.c substdio.h str.h byte.h error.h ./compile substdo.c syslog.lib: \ trysyslog.c compile load ( ( ./compile trysyslog.c && \ ./load trysyslog -lgen ) >/dev/null 2>&1 \ && echo -lgen || exit 0 ) > syslog.lib rm -f trysyslog.o trysyslog systype: \ find-systype trycpp.c ./find-systype > systype tcp-env: \ load tcp-env.o dns.o remoteinfo.o timeoutread.o timeoutwrite.o \ timeoutconn.o ip.o ipalloc.o case.a ndelay.a sig.a env.a getopt.a \ stralloc.a alloc.a substdio.a error.a str.a fs.a dns.lib socket.lib ./load tcp-env dns.o remoteinfo.o timeoutread.o \ timeoutwrite.o timeoutconn.o ip.o ipalloc.o case.a ndelay.a \ sig.a env.a getopt.a stralloc.a alloc.a substdio.a error.a \ str.a fs.a `cat dns.lib` `cat socket.lib` tcp-env.0: \ tcp-env.1 nroff -man tcp-env.1 > tcp-env.0 tcp-env.o: \ compile tcp-env.c sig.h stralloc.h gen_alloc.h str.h env.h fmt.h \ scan.h subgetopt.h ip.h dns.h byte.h remoteinfo.h exit.h case.h ./compile tcp-env.c tcp-environ.0: \ tcp-environ.5 nroff -man tcp-environ.5 > tcp-environ.0 tcpto.o: \ compile tcpto.c tcpto.h open.h lock.h seek.h now.h datetime.h ip.h \ byte.h datetime.h readwrite.h ./compile tcpto.c tcpto_clean.o: \ compile tcpto_clean.c tcpto.h open.h substdio.h readwrite.h ./compile tcpto_clean.c timeoutconn.o: \ compile timeoutconn.c ndelay.h select.h error.h readwrite.h ip.h \ byte.h timeoutconn.h ./compile timeoutconn.c timeoutread.o: \ compile timeoutread.c timeoutread.h select.h error.h readwrite.h ./compile timeoutread.c timeoutwrite.o: \ compile timeoutwrite.c timeoutwrite.h select.h error.h readwrite.h ./compile timeoutwrite.c token822.o: \ compile token822.c stralloc.h gen_alloc.h alloc.h str.h token822.h \ gen_alloc.h gen_allocdefs.h ./compile token822.c trigger.o: \ compile trigger.c select.h open.h trigger.h hasnpbg1.h ./compile trigger.c triggerpull.o: \ compile triggerpull.c ndelay.h open.h triggerpull.h ./compile triggerpull.c uint32.h: \ tryulong32.c compile load uint32.h1 uint32.h2 ( ( ./compile tryulong32.c && ./load tryulong32 && \ ./tryulong32 ) >/dev/null 2>&1 \ && cat uint32.h2 || cat uint32.h1 ) > uint32.h rm -f tryulong32.o tryulong32 wait.a: \ makelib wait_pid.o wait_nohang.o ./makelib wait.a wait_pid.o wait_nohang.o wait_nohang.o: \ compile wait_nohang.c haswaitp.h ./compile wait_nohang.c wait_pid.o: \ compile wait_pid.c error.h haswaitp.h ./compile wait_pid.c netqmail-1.06/byte_diff.c0000644000076400007640000000070506541176434014753 0ustar nelsonnelson#include "byte.h" int byte_diff(s,n,t) register char *s; register unsigned int n; register char *t; { for (;;) { if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; if (!n) return 0; if (*s != *t) break; ++s; ++t; --n; } return ((int)(unsigned int)(unsigned char) *s) - ((int)(unsigned int)(unsigned char) *t); } netqmail-1.06/open_read.c0000644000076400007640000000020206541176434014744 0ustar nelsonnelson#include #include #include "open.h" int open_read(fn) char *fn; { return open(fn,O_RDONLY | O_NDELAY); } netqmail-1.06/find-systype.sh0000644000076400007640000000650306541176434015650 0ustar nelsonnelson# oper-:arch-:syst-:chip-:kern- # oper = operating system type; e.g., sunos-4.1.4 # arch = machine language; e.g., sparc # syst = which binaries can run; e.g., sun4 # chip = chip model; e.g., micro-2-80 # kern = kernel version; e.g., sun4m # dependence: arch --- chip # \ \ # oper --- syst --- kern # so, for example, syst is interpreted in light of oper, but chip is not. # anyway, no slashes, no extra colons, no uppercase letters. # the point of the extra -'s is to ease parsing: can add hierarchies later. # e.g., *:i386-*:*:pentium-*:* would handle pentium-100 as well as pentium, # and i386-486 (486s do have more instructions, you know) as well as i386. # the idea here is to include ALL useful available information. exec 2>/dev/null sys="`uname -s | tr '/:[A-Z]' '..[a-z]'`" if [ x"$sys" != x ] then unamer="`uname -r | tr /: ..`" unamem="`uname -m | tr /: ..`" unamev="`uname -v | tr /: ..`" case "$sys" in bsd.os) # in bsd 4.4, uname -v does not have useful info. # in bsd 4.4, uname -m is arch, not chip. oper="$sys-$unamer" arch="$unamem" syst="" chip="`sysctl -n hw.model`" kern="" ;; freebsd) # see above about bsd 4.4 oper="$sys-$unamer" arch="$unamem" syst="" chip="`sysctl -n hw.model`" # hopefully kern="" ;; netbsd) # see above about bsd 4.4 oper="$sys-$unamer" arch="$unamem" syst="" chip="`sysctl -n hw.model`" # hopefully kern="" ;; linux) # as in bsd 4.4, uname -v does not have useful info. oper="$sys-$unamer" syst="" chip="$unamem" kern="" case "$chip" in i386|i486|i586|i686) arch="i386" ;; alpha) arch="alpha" ;; esac ;; aix) # naturally IBM has to get uname -r and uname -v backwards. dorks. oper="$sys-$unamev-$unamer" arch="`arch | tr /: ..`" syst="" chip="$unamem" kern="" ;; sunos) oper="$sys-$unamer-$unamev" arch="`(uname -p || mach) | tr /: ..`" syst="`arch | tr /: ..`" chip="$unamem" # this is wrong; is there any way to get the real info? kern="`arch -k | tr /: ..`" ;; unix_sv) oper="$sys-$unamer-$unamev" arch="`uname -m`" syst="" chip="$unamem" kern="" ;; *) oper="$sys-$unamer-$unamev" arch="`arch | tr /: ..`" syst="" chip="$unamem" kern="" ;; esac else $CC -c trycpp.c $LD -o trycpp trycpp.o case `./trycpp` in nextstep) oper="nextstep-`hostinfo | sed -n 's/^[ ]*NeXT Mach \([^:]*\):.*$/\1/p'`" arch="`hostinfo | sed -n 's/^Processor type: \(.*\) (.*)$/\1/p' | tr /: ..`" syst="" chip="`hostinfo | sed -n 's/^Processor type: .* (\(.*\))$/\1/p' | tr ' /:' '...'`" kern="" ;; *) oper="unknown" arch="" syst="" chip="" kern="" ;; esac rm -f trycpp.o trycpp fi case "$chip" in 80486) # let's try to be consistent here. (BSD/OS) chip=i486 ;; i486DX) # respect the hyphen hierarchy. (FreeBSD) chip=i486-dx ;; i486.DX2) # respect the hyphen hierarchy. (FreeBSD) chip=i486-dx2 ;; Intel.586) # no, you nitwits, there is no such chip. (NeXTStep) chip=pentium ;; i586) # no, you nitwits, there is no such chip. (Linux) chip=pentium ;; i686) # STOP SAYING THAT! (Linux) chip=ppro esac echo "$oper-:$arch-:$syst-:$chip-:$kern-" | tr ' [A-Z]' '.[a-z]' netqmail-1.06/uint32.h20000644000076400007640000000011106541176434014222 0ustar nelsonnelson#ifndef UINT32_H #define UINT32_H typedef unsigned long uint32; #endif netqmail-1.06/ipme.c0000644000076400007640000000463010724070436013744 0ustar nelsonnelson#include #include #include #include #include #include #include #ifndef SIOCGIFCONF /* whatever works */ #include #endif #include "hassalen.h" #include "byte.h" #include "ip.h" #include "ipalloc.h" #include "stralloc.h" #include "ipme.h" static int ipmeok = 0; ipalloc ipme = {0}; int ipme_is(ip) struct ip_address *ip; { int i; if (ipme_init() != 1) return -1; for (i = 0;i < ipme.len;++i) if (byte_equal(&ipme.ix[i].ip,4,ip)) return 1; return 0; } static stralloc buf = {0}; int ipme_init() { struct ifconf ifc; char *x; struct ifreq *ifr; struct sockaddr_in *sin; int len; int s; struct ip_mx ix; if (ipmeok) return 1; if (!ipalloc_readyplus(&ipme,0)) return 0; ipme.len = 0; ix.pref = 0; /* 0.0.0.0 is a special address which always refers to * "this host, this network", according to RFC 1122, Sec. 3.2.1.3a. */ byte_copy(&ix.ip,4,"\0\0\0\0"); if (!ipalloc_append(&ipme,&ix)) { return 0; } if ((s = socket(AF_INET,SOCK_STREAM,0)) == -1) return -1; len = 256; for (;;) { if (!stralloc_ready(&buf,len)) { close(s); return 0; } buf.len = 0; ifc.ifc_buf = buf.s; ifc.ifc_len = len; if (ioctl(s,SIOCGIFCONF,&ifc) >= 0) /* > is for System V */ if (ifc.ifc_len + sizeof(*ifr) + 64 < len) { /* what a stupid interface */ buf.len = ifc.ifc_len; break; } if (len > 200000) { close(s); return -1; } len += 100 + (len >> 2); } x = buf.s; while (x < buf.s + buf.len) { ifr = (struct ifreq *) x; #ifdef HASSALEN len = sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len; if (len < sizeof(*ifr)) len = sizeof(*ifr); if (ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *) &ifr->ifr_addr; byte_copy(&ix.ip,4,&sin->sin_addr); if (ioctl(s,SIOCGIFFLAGS,x) == 0) if (ifr->ifr_flags & IFF_UP) if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } } #else len = sizeof(*ifr); if (ioctl(s,SIOCGIFFLAGS,x) == 0) if (ifr->ifr_flags & IFF_UP) if (ioctl(s,SIOCGIFADDR,x) == 0) if (ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *) &ifr->ifr_addr; byte_copy(&ix.ip,4,&sin->sin_addr); if (!ipalloc_append(&ipme,&ix)) { close(s); return 0; } } #endif x += len; } close(s); ipmeok = 1; return 1; } netqmail-1.06/fifo.h0000644000076400007640000000007706541176434013752 0ustar nelsonnelson#ifndef FIFO_H #define FIFO_H extern int fifo_make(); #endif netqmail-1.06/hfield.h0000644000076400007640000000142406541176434014257 0ustar nelsonnelson#ifndef HFIELD_H #define HFIELD_H extern unsigned int hfield_skipname(); extern int hfield_known(); extern int hfield_valid(); #define H_SENDER 1 #define H_FROM 2 #define H_REPLYTO 3 #define H_TO 4 #define H_CC 5 #define H_BCC 6 #define H_DATE 7 #define H_MESSAGEID 8 #define H_SUBJECT 9 #define H_R_SENDER 10 #define H_R_FROM 11 #define H_R_REPLYTO 12 #define H_R_TO 13 #define H_R_CC 14 #define H_R_BCC 15 #define H_R_DATE 16 #define H_R_MESSAGEID 17 #define H_RETURNRECEIPTTO 18 #define H_ERRORSTO 19 #define H_APPARENTLYTO 20 #define H_RECEIVED 21 #define H_RETURNPATH 22 #define H_DELIVEREDTO 23 #define H_CONTENTLENGTH 24 #define H_CONTENTTYPE 25 #define H_CONTENTTRANSFERENCODING 26 #define H_NOTICEREQUESTEDUPONDELIVERYTO 27 #define H_MAILFOLLOWUPTO 28 #define H_NUM 29 #endif netqmail-1.06/BIN.Makefile0000644000076400007640000000150606541176434014723 0ustar nelsonnelsonSHELL=/bin/sh # Files are edited in the installation directory, then copied. # There are 40 arguments to idedit after the filename, # showing the positions of each byte in the following ten ints: # uida, uidd, uidl, uido, uidp, uidq, uidr, uids, gidq, gidn. # Normal little-endian positions are n n+1 n+2 ... n+39 for some n. # Normal big-endian positions are n+3 n+2 n+1 n n+7 ... n+36 for some n. setup: mkdir /var/qmail ./idedit install-big XXX ./idedit qmail-lspawn XXX ./idedit qmail-queue XXX ./idedit qmail-rspawn XXX ./idedit qmail-showctl XXX ./idedit qmail-start XXX ./install-big cp /var/qmail/boot/binm1+df /var/qmail/rc chmod 755 /var/qmail/rc echo '|fastforward -d /etc/aliases.cdb' > /var/qmail/alias/.qmail-default chmod 644 /var/qmail/alias/.qmail-default hostname | grep -q '\.' ./config-fast `hostname` netqmail-1.06/home.sh0000644000076400007640000000030706541176434014136 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using qmail-local to deliver messages to ~/Mailbox by default. exec env - PATH="QMAIL/bin:$PATH" \ qmail-start ./Mailbox splogger qmail netqmail-1.06/fifo_make.30000644000076400007640000000055406541176434014662 0ustar nelsonnelson.TH fifo_make 3 .SH NAME fifo_make \- create a named pipe .SH SYNTAX .B #include int \fBfifo_make\fP(\fIfn\fR,\fImode\fR); char *\fIfn\fR; .br int \fImode\fR; .SH DESCRIPTION .B fifo_make creates a new named pipe with name .I fn and mode .I mode (modified by the process umask). .B fifo_make returns 0 on success, -1 on error. .SH "SEE ALSO" mkfifo(2) netqmail-1.06/mailsubj.10000644000076400007640000000102006541176434014533 0ustar nelsonnelson.TH mailsubj 1 .SH NAME mailsubj \- send a mail message with a subject line .SH SYNOPSIS .B mailsubj .I subject .I recip ... .SH DESCRIPTION .B mailsubj inserts .I subject and the list of .IR recip s into a mail message: .EX Subject: subject .br To: recip ... .br .br body .EE .B mailsubj reads the body of the message from its standard input. Then it sends the message. Note that .I subject and .I recip must be quoted properly for the message header. .SH "SEE ALSO" addresses(5), qmail-header(8), qmail-inject(8) netqmail-1.06/qmail-qread.c0000644000076400007640000000726306541176434015223 0ustar nelsonnelson#include #include #include "stralloc.h" #include "substdio.h" #include "subfd.h" #include "fmt.h" #include "str.h" #include "getln.h" #include "fmtqfn.h" #include "readsubdir.h" #include "auto_qmail.h" #include "open.h" #include "datetime.h" #include "date822fmt.h" #include "readwrite.h" #include "error.h" #include "exit.h" readsubdir rs; void die(n) int n; { substdio_flush(subfdout); _exit(n); } void warn(s1,s2) char *s1; char *s2; { char *x; x = error_str(errno); substdio_puts(subfdout,s1); substdio_puts(subfdout,s2); substdio_puts(subfdout,": "); substdio_puts(subfdout,x); substdio_puts(subfdout,"\n"); } void die_nomem() { substdio_puts(subfdout,"fatal: out of memory\n"); die(111); } void die_chdir() { warn("fatal: unable to chdir",""); die(111); } void die_opendir(fn) char *fn; { warn("fatal: unable to opendir ",fn); die(111); } void err(id) unsigned long id; { char foo[FMT_ULONG]; foo[fmt_ulong(foo,id)] = 0; warn("warning: trouble with #",foo); } char fnmess[FMTQFN]; char fninfo[FMTQFN]; char fnlocal[FMTQFN]; char fnremote[FMTQFN]; char fnbounce[FMTQFN]; char inbuf[1024]; stralloc sender = {0}; unsigned long id; datetime_sec qtime; int flagbounce; unsigned long size; unsigned int fmtstats(s) char *s; { struct datetime dt; unsigned int len; unsigned int i; len = 0; datetime_tai(&dt,qtime); i = date822fmt(s,&dt) - 7/*XXX*/; len += i; if (s) s += i; i = fmt_str(s," GMT #"); len += i; if (s) s += i; i = fmt_ulong(s,id); len += i; if (s) s += i; i = fmt_str(s," "); len += i; if (s) s += i; i = fmt_ulong(s,size); len += i; if (s) s += i; i = fmt_str(s," <"); len += i; if (s) s += i; i = fmt_str(s,sender.s + 1); len += i; if (s) s += i; i = fmt_str(s,"> "); len += i; if (s) s += i; if (flagbounce) { i = fmt_str(s," bouncing"); len += i; if (s) s += i; } return len; } stralloc stats = {0}; void out(s,n) char *s; unsigned int n; { while (n > 0) { substdio_put(subfdout,((*s >= 32) && (*s <= 126)) ? s : "_",1); --n; ++s; } } void outs(s) char *s; { out(s,str_len(s)); } void outok(s) char *s; { substdio_puts(subfdout,s); } void putstats() { if (!stralloc_ready(&stats,fmtstats(FMT_LEN))) die_nomem(); stats.len = fmtstats(stats.s); out(stats.s,stats.len); outok("\n"); } stralloc line = {0}; void main() { int channel; int match; struct stat st; int fd; substdio ss; int x; if (chdir(auto_qmail) == -1) die_chdir(); if (chdir("queue") == -1) die_chdir(); readsubdir_init(&rs,"info",die_opendir); while (x = readsubdir_next(&rs,&id)) if (x > 0) { fmtqfn(fnmess,"mess/",id,1); fmtqfn(fninfo,"info/",id,1); fmtqfn(fnlocal,"local/",id,1); fmtqfn(fnremote,"remote/",id,1); fmtqfn(fnbounce,"bounce/",id,0); if (stat(fnmess,&st) == -1) { err(id); continue; } size = st.st_size; flagbounce = !stat(fnbounce,&st); fd = open_read(fninfo); if (fd == -1) { err(id); continue; } substdio_fdbuf(&ss,read,fd,inbuf,sizeof(inbuf)); if (getln(&ss,&sender,&match,0) == -1) die_nomem(); if (fstat(fd,&st) == -1) { close(fd); err(id); continue; } close(fd); qtime = st.st_mtime; putstats(); for (channel = 0;channel < 2;++channel) { fd = open_read(channel ? fnremote : fnlocal); if (fd == -1) { if (errno != error_noent) err(id); } else { for (;;) { if (getln(&ss,&line,&match,0) == -1) die_nomem(); if (!match) break; switch(line.s[0]) { case 'D': outok(" done"); case 'T': outok(channel ? "\tremote\t" : "\tlocal\t"); outs(line.s + 1); outok("\n"); break; } } close(fd); } } } die(0); } netqmail-1.06/qlx.h0000644000076400007640000000051606541176434013631 0ustar nelsonnelson#ifndef QLX_H #define QLX_H /* 0, 111, 100 are qmail-local success, soft, hard */ #define QLX_USAGE 112 #define QLX_BUG 101 #define QLX_ROOT 113 #define QLX_NFS 115 #define QLX_NOALIAS 116 #define QLX_CDB 117 #define QLX_SYS 118 #define QLX_NOMEM 119 #define QLX_EXECSOFT 120 #define QLX_EXECPW 121 #define QLX_EXECHARD 126 #endif netqmail-1.06/CHANGES0000644000076400007640000024277510724074311013653 0ustar nelsonnelson20071130 version: netqmail 1.06 20071130 legal: qmail-1.03 is now in the public domain 20051103 doc: dot-qmail.9 updated for changed (19980613) conf-patrn default, tnx ADM 20040121 version: netqmail 1.05 20040121 code: qmail-smtpd is protected from exceedingly long (eg 2GB) header lines 20040121 code: qmail_lspawn, qmail-newmrh, qmail-newu, and qmail-rspawn are protected from misbehaving on hosts where the size of an integer is not the same as the size of a character pointer (eg 64 bit hosts with 32 bit ints) 20031027 version: netqmail 1.04. 20031027 doc: INSTALL points to http://lifewithqmail.org/lwq.html 20031027 doc: qmail.7 identifies installation as netqmail and points to http://qmail.org/ 20031027 doc: qmail-queue.8 adds explanation of $QMAILQUEUE 20031027 doc: qmail-log.5 adds reference to errors from $QMAILQUEUE script 20031027 doc: FAQ also points to http://cr.yp.to/qmail/faq.html and http://qmail.org/ 20031027 code: qmail-smtpd identifies itself as netqmail 20031027 code: if $QMAILQUEUE is set, it's invoked instead of qmail-queue 20031024 code: changed errno from int to #include. 20031024 code: fixed .qmail parsing bug. 20031024 code: recognize 0.0.0.0 as a local address. 20031024 code: sendmail's -f flag now overrides environment variables. 19980615 version: qmail 1.03. 19980614 doc: eliminated BIN.setup in favor of a web page. 19980614 code: added other auto* to qmail-showctl output. 19980614 doc: added pointer to immhf.html in qmail-header.5. 19980614 doc: added note to TEST.receive about SMTP command format. 19980614 doc: added FAQ 5.6 on qmail-qmqpd. 19980614 code: removed unused variables in idedit.c. 19980613 code: changed conf-patrn to 002. 19980613 doc: moved SENDMAIL lower in INSTALL. 19980612 code: added install-big. 19980612 code: added BIN.Makefile. 19980612 doc: added BIN.README, BIN.setup. 19980612 code: switched to new install. 19980611 code: added idedit. 19980611 doc: added FAQ 1.3 on $QMAILMFTFILE. 19980611 doc: used bouncesaying in FAQ 5.5. 19980611 code: added except. 19980611 code: added bouncesaying. 19980611 code: allowed unbracketed IP addresses in dns_ipplus() and dns_mxip(). 19980611 code: allowed spaces after colon in non-bracketed addresses in qmail-smtpd. 19980611 doc: cleaned up UPGRADE. 19980528 bug: qmail-smtpd skips first character in rcpthosts() call. tnx NND. impact: qmail-smtpd crashes on empty address; and it allows relaying to ""@any.host. fix: use addr.s. 19980515 doc: expanded flock discussion in INSTALL.mbox. 19980515 doc: eliminated flock warning from INSTALL.maildir. 19980515 doc: split REMOVE.binmail out of INSTALL. 19980515 doc: split REMOVE.sendmail out of INSTALL. 19980515 doc: split TEST.deliver and TEST.receive out of INSTALL and UPGRADE. 19980515 doc: integrated INSTALL.boot into INSTALL. 19980515 code: cleaned up final output in qmail-qmqpd.c. 19980514 doc: updated procmail notes in INSTALL.mbox. tnx JRM. 19980514 doc: changed FAQ 4.4 to point to INSTALL.mbox for procmail. tnx JRM. 19980514 code: separated HELO and EHLO; single-line response for HELO. tnx to various people. 19980430 version: qmail 1.02. 19980430 doc: updated SECURITY. 19980430 doc: fixed FAQ 4.9. tnx KB. 19980430 code: changed quote2() to avoid quoting <>. 19980429 code: changed quote_need() to quote empty local parts. tnx HHO. 19980428 doc: added status notes to INSTALL and UPGRADE. 19980428 code: skip setting environment in sendmail.c if PROTO is set. 19980428 code: eliminated recipientmap. 19980428 code: added virtual users to qmail-send.c. tnx RN. 19980428 code: eliminated domain from rewrite() in qmail-send.c. 19980428 code: added binm1, binm1+df, binm2, binm2+df, binm3, binm3+df. 19980428 doc: eliminated most Mailbox references from INSTALL, UPGRADE. 19980428 code: added config-fast. 19980428 code: renamed qmail-config as config. 19980428 code: supported QMAILMFTFILE in qmail-inject.c. 19980428 code: recognized Mail-Followup-To in hfield.c. 19980428 code: replaced rwrecip() with rwappend() in qmail-inject.c. 19980428 code: cleaned up doheaderfile() in qmail-inject.c. 19980426 code: eliminated -type test from qmail-qstat to speed it up. tnx FT. 19980421 doc: eliminated remove-rcpthosts comments from FAQ. 19980421 doc: updated FAQ 4.3 to point to Russ Allbery's FAQ. 19980421 doc: took account of /var/qmail/boot in INSTALL, UPGRADE, and INSTALL.vsm. 19980421 code: added /var/qmail/boot, with home, home+df, proc, proc+df. 19980421 doc: skipped make and make man in INSTALL. 19980420 doc: cleaned up mbox description in SENDMAIL. 19980420 code: changed QMQP port to official port 628. 19980402 doc: updated qmsmac references to fastforward. 19980402 doc: replaced qmail-upgrade man page with doc/SENDMAIL. 19980402 code: added qmqpservers output to qmail-showctl. 19980402 code: added qmail-qmqpd. 19980402 code: added qmail-qmqpc. 19980304 code: eliminated del_saywhynoexit in qmail-send.c. 19980304 code: eliminated concurrencynodel in qmail-send.c. 19980222 code: added status() to qmail-send.c. 19980222 code: added concurrencyused to qmail-send.c. 19980128 doc: added note to qmail-getpw.9 about ETXTBSY. 19980127 code: eliminated err_seenmail() in qmail-smtpd.c. tnx PO. 19980126 doc: used $DEFAULT in FAQ where possible. 19980126 code: added DEFAULT in qmail-local. 19980126 code: added -/ to qmail-pw2u. 19980126 code: revamped qmeopen() as qmesearch() with more sensible semantics, separating dash from ext cleanly. 19980126 code: split qmeexists() out of qmeopen() in qmail-local.c. 19980126 code: introduced safeext in qmail-local.c. 19980126 code: changed ~alias to mode 2755, to put files into group qmail rather than group nofiles under System V. 19980126 doc: switched to /var/qmail/rc in INSTALL*, UPGRADE, FAQ. 19980126 code: added rc. 19980119 doc: added .qmail creation warning to condredirect.1. 19980118 code: made auto_uids.c creation atomic in Makefile. tnx HHO. 19980118 doc: added PIC.*. 19980117 portability problem: Solaris 2.5.1 incorrectly converts O_NDELAY into O_NONBLOCK for sockets, so that ndelay_off() fails to undo ndelay_on(). impact: none, since all the network readers here use select() via timeoutread(). fix: use O_NONBLOCK if it is defined. 19980115 code: reformatted qmail-qmtpd.c. 19980115 doc: changed tcpcontrol references in FAQ. 19980115 doc: documented morercpthosts in qmail-qmtpd.9. 19980115 code: eliminated unused datetime in qmail-qmtpd.c. 19980115 code: eliminated sigalrm() in qmail-qmtpd.c. 19980115 code: used rcpthosts() in qmail-smtpd.c, qmail-qmtpd.c. 19980115 code: introduced rcpthosts.c. 19980115 code: added morercpthosts.cdb support to qmail-showctl. 19980115 code: added morercpthosts support to qmail-showctl. 19980115 code: do_lst now returns file-exists in qmail-showctl. 19980112 doc: documented morercpthosts in qmail-smtpd.9. 19980112 code: added qmail-newmrh. 19980112 code: used commands.c in qmail-popup. 19980112 code: used commands.c in qmail-pop3d. 19980112 code: introduced fakehelo in qmail-smtpd. 19980112 code: moved flagbarf setting out of bmfcheck(). 19980112 code: allowed more address misformatting in qmail-smtpd. 19980112 code: eliminated qmail@pobox.com help address in qmail-smtpd. 19980112 code: reorganized qmail-smtpd. 19980112 code: reformatted qmail-smtpd. 19980112 code: used commands.c in qmail-smtpd. 19980112 code: switched from 0 to "" for no arg in commands(). 19980112 code: added commands.c. 19971230 doc: added -s to FreeBSD commands in INSTALL.ids. tnx TM. 19971224 doc: added pointer to qmail pictures in README. 19971223 doc: added note in FAQ about qmail-pop3d using maildir. 19971219 code: added HOST2, HOST3, HOST4. 19971219 code: renamed extx as x in qmail-local.c. 19971219 doc: partitioned qmail-command.0. 19971219 doc: updated FAQ 4.3 to point to newer majordomo patches. 19971219 doc: eliminated qlist2 from FAQ. 19971219 doc: eliminated qlist discussion from SECURITY. 19971219 code: moved qlist, qlist2 to separate package. 19971213 doc: added FAQ 4.10 on qmail-users generally. 19971213 doc: added FAQ 4.9 on dealing with NFS outages. 19971031 doc: added Linux and FreeBSD commands to INSTALL.ids. tnx TM. 19971026 doc: added note about smtplf in qmail-smtpd.8. tnx S2S. 19971014 doc: some tweaks to THOUGHTS. 19971012 doc: used MAILER-DAEMON in UUCP example in INSTALL. 19971003 code: eliminated dataline and getln() from qmail-remote.c. 19971003 code: revamped blast() in qmail-remote.c. 19971002 doc: added FAQ entries for .forward and /etc/aliases. 19971002 doc: rewrote INSTALL.mbox and INSTALL.vsm. 19971002 doc: renamed INSTALL.qsmhook as INSTALL.vsm. 19971002 doc: emphasized the qmail-popup argv0 in FAQ. 19971001 doc: added dot-forward note to BLURB3. 19971001 doc: added more configuration notes to qmail-upgrade.9. 19971001 doc: added note in INSTALL.qsmhook about dot-forward. 19970930 code: token822_parse() now supports backslash as a quoting character in atoms. 19970929 doc: suggested symbolic links in INSTALL.mbox. 19970925 doc: added note to INTERNALS about bounce stability. 19970925 doc: added section to THOUGHTS discussing CNAME lookups. 19970925 code: qmail-remote no longer does CNAME lookup on sender. tnx C2F. 19970923 portability problem: under SCO OSR5, splogger needs socket libraries. impact: couldn't compile. fix: socket.lib. tnx RB. 19970906 portability problem: under RISC/OS, Mail invokes sendmail -bm. impact: can't send mail using Mail on RISC/OS. fix: ignore -bm. tnx NW. 19970813 code: implemented databytes in qmail-qmtpd. 19970813 code: implemented databytes. tnx M4S for sample code. 19970813 code: replaced execvp() with execv() for sh in qmail-local. 19970813 doc: said in qmail-control.9 that recipientmap allows comments. 19970813 code: used strerr in qmail-local.c. 19970813 code: changed timeoutread(), timeoutwrite() interface. 19970813 code: eliminated shutdown() in timeoutread(), timeoutwrite(). 19970813 code: revamped I/O in qmail-smtpd.c. 19970813 code: used timeoutread(), timeoutwrite() in qmail-smtpd.c. 19970813 code: simplified getcontrol() logic in qmail-remote.c; some out-of-memory messages are now cannot-read-control messages. 19970813 code: eliminated scan_nbblong(). 19970813 code: reformatted qmail-remote.c. 19970813 code: renamed flaganyrecipok as flagbother in qmail-remote.c. 19970813 code: integrated status report into quit() in qmail-remote.c. 19970813 code: revamped smtpcode() in qmail-remote.c. 19970813 code: added flagcritical in qmail-remote.c. eliminates possible-duplicate warning if dot has not yet been sent. 19970813 code: revamped I/O in qmail-remote.c. 19970813 code: quit immediately after sending QUIT in qmail-remote.c. 19970813 code: made many more globals in qmail-remote.c. 19970813 code: switched qmail-remote.c from subfdin to home-grown. 19970813 code: switched qmail-remote.c from subfdout to subfdoutsmall. 19970813 code: added LAST support to qmail-pop3d. 19970812 code: changed qmail_close() success return from 0 to "". 19970812 code: revamped I/O in qmail-qmtpd.c. 19970812 code: added qmail-tcpok. 19970812 code: used strerr in maildirmake.c. 19970812 code: reformatted maildirmake.c. 19970812 code: printed qp in condredirect.c. 19970812 code: printed qqx in condredirect.c. 19970812 code: revamped I/O in condredirect.c. 19970812 code: reformatted condredirect.c. 19970812 code: used strerr in preline.c. 19970812 code: revamped I/O in preline.c. 19970812 code: reformatted preline.c. 19970812 code: printed qp in forward.c. 19970812 code: printed qqx in forward.c. 19970812 code: revamped I/O in forward.c. 19970812 code: used strerr in forward.c. 19970812 code: reformatted forward.c. 19970812 code: used strerr in predate.c. 19970812 code: forced failure in qmail-qmtpd if no recipients; saves time for qmail-send. 19970812 code: added smtpd() to sendmail.c. 19970812 code: added mailq() to sendmail.c. 19970812 code: added die_usage() to sendmail.c. 19970812 code: reformatted sendmail.c. 19970812 code: used byte_zero() in qmail-popup.c. 19970812 code: reformatted qmail-popup.c. 19970812 code: eliminated unused header files in qmail-popup.c. 19970812 code: changed I/O system in qmail-popup.c to match qmail-pop3d. 19970812 doc: pointed people to the mailing list in INSTALL and UPGRADE. 19970810 code: added TXTBSY check to qmail-getpw.c. this gives vendors the opportunity to make getpwnam() reliable. 19970810 code: moved non-deleted messages from new/ to cur/ in qmail-pop3d. tnx to various people. 19970810 code: introduced list() in qmail-pop3d.c. 19970810 code: reformatted qmail-pop3d.c. 19970810 code: merged dataline and newname into line in qmail-pop3d.c. 19970810 code: chopped filenames in qmail-pop3d at colons for UIDL. tnx to various people. 19970810 code: eliminated printint(), printlong() in qmail-pop3d.c. 19970810 code: revamped I/O in qmail-pop3d.c. 19970810 code: used timeoutread(), timeoutwrite() in qmail-pop3d.c. 19970810 code: eliminated die_prot() in qmail-pop3d.c. 19970810 code: eliminated unused header files in qmail-pop3d.c. 19970810 code: switched qmail-pop3d to use maildir.c. tnx MD. 19970809 code: added uid/gid printing to qmail-showctl. tnx PGF. 19970808 code: switched control.c from scan_nbblong to scan_ulong. 19970808 code: cleaned up wait_pid to use waitpid() when possible, and to support at least one extra child otherwise. 19970807 code: in qmail-smtpd, treat long envelope addresses as a syntax error, instead of waiting for qmail-queue to reject them. 19970803 code: changed condredirect, forward, qlist, qmail-inject, qmail-local, qmail-qmtpd, qmail-send, qmail-smtpd, qreceipt for new qmail_close() interface. 19970803 code: revised qmail_close() to handle qmail-queue exit codes. 19970802 doc: documented SMTP-related exit codes in qmail-queue.8. 19970802 doc: documented qmail-queue exit codes in qmail-queue.8. 19970802 code: revamped qmail-queue exit codes. 19970802 doc: noted linking restrictions in qmail-queue.8. 19970802 doc: rewrote INSTALL.mbox. 19970802 doc: split INSTALL.maildir off of INSTALL.mbox. 19970802 code: added /var/qmail/doc/ creation to qmail-hier. 19970802 doc: added ezmlm note to FAQ. 19970802 doc: replaced qlist blurbs with ezmlm blurbs in BLURB*. 19970802 doc: added various notes to qmail-start.9. 19970728 doc: eliminated RFC*. 19970714 doc: added daemontools notes to FAQ. 19970714 code: eliminated ESMTP parameter syntax checking. 19970701 doc: changed ``forwarded'' to ``resent'' in qmail-header.5. 19970629 code: reformatted constmap.c. 19970628 code: changed straynewline() message in qmail-smtpd.c to point to http://pobox.com/~djb/smtplf.html. tnx RDM. 19970609 doc: added preline to vacation example in dot-qmail.9. tnx C2S. 19970421 code: cleaned up slurpclose to handle interrupts. 19970421 code: set qmail-popup to mode 711. tnx MD. 19970421 doc: fixed qmail-local -n example in dot-qmail.9. 19970415 version: qmail 1.01. 19970414 doc: tightened up qmail-upgrade.7. 19970414 code: rewrote rewrite(). 19970414 code: implemented recipientmap. suggested by RDM. 19970414 doc: auto-configured qmail home directory in qmail-control.5, qmail-newu.8, qmail-pw2u.8, qmail-start.8, qmail-users.5. 19970414 port: Solaris needs socket libs for gethostname. impact: can't compile under Solaris. fix: use socket.lib for qmail-local. 19970412 code: introduced stralloc_starts. 19970412 code: introduced str_equal. 19970412 code: introduced str_start. 19970412 code: introduced byte_equal. 19970412 code: made an optional aliasempty arg for qmail-start. 19970412 code: made an aliasempty arg for qmail-lspawn. 19970412 code: changed ALIAS_EMPTY to an arg for qmail-local. 19970412 port: UnixWare returns >0 for SIOCGIFCONF. impact: ipme fails under UnixWare. fix: check for >=0, not =0. tnx JD. 19970412 port: DGUX does not have ranlib. impact: can't compile under DGUX. fix: added dgux line to make-makelib. tnx HWM. 19970412 code: changed maildir library to skip any filename beginning with dot. tnx SP. 19970412 doc: added FAQ entry about aliases with dots. 19970412 doc: clarified in qmail-inject.8 that default envelope sender is the same as _default_ From address. 19970411 code: renamed qmail-makectl as qmail-config. 19970411 code: renamed qmail-alias as qmail-local. 19970411 code: switched from signal library to sig library. 19970411 code: switched from qqtalk library to qmail library. 19970411 code: switched from getline library to getln library. 19970411 code: massive library cleanups. 19970411 code: revamped autoconfiguration system. 19970411 code: revamped configuration interface. 19970411 code: eliminated qmail-home. 19970411 code: eliminated tokenize. 19970220 qmail 1.00. 19970219 change: various documentation tweaks. 19970218 change: updated THOUGHTS. 19970218 change: talked about SPAWN_NUMD in FAQ. tnx EC. 19970210 change: noted in maildir.5 that readers should skip any name starting with a dot. tnx SP. 19970209 change: added note to splogger.8 about reliability. tnx BT. 19970209 change: added section to FAQ on slow sendmail switch. tnx BT. 19970206 change: added section to FAQ about dtcm. tnx PJG. 19970206 change: tweaked maildir.5. 19970201 change: added MH spost note to FAQ. tnx TU. 19970131 change: reorganized FAQ. 19970131 change: added web references to FAQ. 19970124 change: tweaked qmail-upgrade man page. 19970120 qmail 0.96, gamma. 19970120 change: removed various try* in auto-configuration. 19970120 bug: qmail-inject fails to quote argument addresses. impact: addresses containing special characters could be misinterpreted or rejected. tnx C2F. fix: use quote2(). 19970120 portability problem: ESIX puts syslog() and openlog() into -lgen. impact: can't compile under ESIX. fix: put -lgen into LIBS for unix_sv. tnx RN. 19961221 qmail 0.95, gamma. 19961218 change: added various try* to TARGETS. tnx SA. 19961216 change: clarified in qmail-send.8 that virtualdomains does not apply to domains listed in locals. 19961216 change: slurpclose() now closes fd on out-of-memory. makes it more widely applicable. 19961215 change: replaced elm instructions in INSTALL.mbox with an explanation of what source change to make. tnx AB. 19961212 portability problem: under NEWS-OS, time_t needs sys/types.h. impact: couldn't compile under NEWS-OS. fix: include sys/types.h in predate.c. tnx TU. 19961211 change: used timeoutread, timeoutwrite in remoteinfo(). tnx REB. 19961210 portability problem: apparently some SGIs produce a systype of irix64. impact: couldn't compile on those systems. fix: handle irix64 in make-cmds. tnx M3S. 19961208 change: added note to maildir2mbox.1 about mbox locking. 19961208 qmail 0.94, gamma. 19961207 change: added QMAILDEFAULTDOMAIN, QMAILDEFAULTHOST, QMAILIDHOST, QMAILPLUSDOMAIN. tnx BTW. 19961206 cleanup: readsubdir() protects itself against name overflow, rather than depending on caller. 19961204 change: changed FAQ 7.3 to prohibit fixup relaying. 19961203 change: added note to FAQ about possibly having to put a space before "$SENDER" for uux. tnx FW. 19961202 change: added FAQ entry on QUEUE_EXTRA. 19961202 change: added FAQ entry on backups. tnx DP. 19961202 change: added note to INSTALL.mbox about qpopper. tnx VV. 19961201 change: replaced logger with splogger in FAQ 5.1. tnx FPL. 19961201 change: used netmask example for tcpcontrol in FAQ. tnx FPL. 19961201 change: added note to README about the mailing list. tnx FPL. 19961201 change: documented rcpthosts wildcards. tnx RN. 19961201 change: added note to FAQ about making mailx use datemail. 19961201 change: added datemail. function requested by several people; approach suggested by TG. 19961201 change: added predate. 19961129 change: added QUEUE_EXTRA, QUEUE_EXTRALEN. 19961129 change: qmail-remote bounces messages with partial final lines. 19961129 change: added atomcheck() to quote crappy atoms. 19961129 change: revised atomok() to let atoms deal with more crap. 19961127 change: qmail-send adds note to deferral if flagdying. tnx TG. 19961127 change: split off maildirbounce, maildir2qmtp, and maildir2smtp into a separate serialmail package. 19961126 change: eliminated beta success reports from README. 19961124 change: forced res_query() return value to fit inside incoming buffer size. allegedly there are buggy versions of res_query() that don't guarantee this. 19961122 qmail 0.93, gamma. 19961122 change: allowed empty arg list in forward. 19961121 change: qmail-smtpd now uses unknown (like qmail-qmtpd) rather than dying if environment variables are not set. 19961121 cleanup: reorganized helo handling in qmail-smtpd.c. 19961121 cleanup: eliminated newfield_rec. 19961121 cleanup: introduced DATE822FMT. used it in received.c. 19961121 cleanup: introduced received.c. used it in qmail-qmtpd.c, qmail-smtpd.c. 19961121 change: qmail-smtpd now generates a new timestamp for each message. tnx PJG. 19961121 cleanup: used stralloc in newfield. 19961121 cleanup: eliminated newfield_cc. 19961121 change: eliminated hfield_mort(). 19961119 change: added 2-minute damper on tcpto. 19961118 change: wrote defaults for readfile controls in showctl. 19961117 change: control_readfile() now allows comments and blank lines. tnx LW. 19961117 change: qmail-start sets logger gid to GID_NOFILES. 19961117 bug: ipme_init() uses a fixed-length buffer for SIOCGIFCONF. impact: qmail-smtpd and qmail-remote will die if there are too many local IP addresses. tnx MD. fix: ipme_init() now dynamically allocates space, up to 200000 bytes, as long as SIOCGIFCONF keeps failing. note that this is a very widespread bug; it's in amd, exim, mrouted, named, nntpd, rarpd, sendmail, tcpdump, timed, xntpd, and probably dozens more programs. 19961117 portability problem: on BSD 4.4 and various other systems, SIOCGIFCONF will truncate long lists and return success. impact: on those systems, qmail-smtpd and qmail-remote will miss some local IP addresses if there are too many. fix: ipme_init() now checks whether there is enough space left in the buffer for another ifreq, plus 64 bytes JIC. yuck. 19961117 change: ipmeprint now flushes only at end. 19961117 cleanup: introduced subfdinsmall. used it in qmail-clean.c, qmail-qmtpd.c. 19961117 cleanup: introduced subfdoutsmall. used it in hostname.c, printbreak.c, printnumd.c, printsplit.c, qmail-alias.c, qmail-clean.c, qmail-getpw.c, qmail-qmtpd.c, maildir2smtp.c, maildir2qmtp.c. 19961117 change: moved subfderr buf up to 256 characters. 19961117 change: added maildirbounce. tnx MD, TG. 19961116 change: maildir2smtp and maildir2qmtp now print filenames for permanent bounces. tnx MD. 19961116 change: in SECURITY, ``eleven most recent sendmail security holes, five'' -> ``twelve most recent sendmail security holes, six.'' 19961116 change: rewrote qmail-showctl more professionally. 19961115 change: added several tests to find-systype.sh. this will affect many systypes. 19961115 change: qmail-alias now treats most exit codes as soft errors. 19961115 change: revamped exit codes everywhere for 0, 100, 111. 19961114 change: added splogger. 19961114 portability problem: Sun's cc recognizes sqrt() as a builtin, even if math.h is not included and sqrt is defined statically. yuck. impact: when qmail is compiled with Sun's cc, next-retry times are all screwed up. tnx PJG. fix: my sqrt() is now called squareroot(). 19961114 change: dns_ip() now recognizes [1.2.3.4]. tnx DS. 19961112 change: enabled x option in sendmail. tnx DS. 19961111 change: added SIGHUP handling to qmail-send. suggested by many people. 19961111 bug: control routines returned incorrect codes for some out-of-memory conditions. impact: none; conditions cannot happen with sane control files. fix: return -1. 19961111 change: added SIGALRM handling to qmail-send. suggested by many people. 19961111 change: eliminated flagnobreak (-b/-B) from qmail-pw2u. 19961111 change: qmail-getpw now allows hyphens inside usernames. 19961111 change: added users/append to qmail-pw2u. tnx G2A. 19961111 change: added badmailfrom to qmail-smtpd. requested by several people. 19961110 change: replaced elm instructions in INSTALL.mbox with a simple note to set incomingfolders in elm.rc. tnx AB. 19961110 change: replaced ``owner hack'' with ``variable envelope return paths'' throughout the documentation. tnx DS. 19961110 change: qmail-setup installs man pages as well as cat pages. 19961110 change: renamed qmail-newuser as qmail-newu. tnx G2A. 19961110 change: renamed qmail-pw2user as qmail-pw2u. tnx G2A. 19961105 change: set path in INSTALL.boot. tnx TJH. 19961105 change: noted in qmail-smtpd.8 that addresses without @ are always allowed through. 19961105 change: indicated at various spots in FAQ that rcpthosts has to be updated. suggested by various people. 19961105 change: indicated at various spots in FAQ that qmail has to be restarted. suggested by various people. 19961029 change: fixed typo in maildir2qmtp.1. tnx BG. 19961026 qmail 0.92, gamma. 19961026 bug: qmail-getpw did not 0-terminate usernames. tnx CF. impact: qmail-getpw would crash on some systems, deferring local deliveries. fix: 0-terminate. 19961025 cleanup: renamed auto-hassgprm.h to hassgprm.h. 19961025 cleanup: renamed auto-hassgact.h to hassgact.h. 19961024 change: replaced qmail-alias.0 with dot-qmail.0 in INSTALL.alias. tnx MW. 19961022 change: switched uids as early as possible in qmail-start.c. 19961022 change: in SECURITY, ``ten most recent sendmail security holes, five'' -> ``eleven most recent sendmail security holes, five.'' 19961022 change: quote_need() now treats non-ASCII characters the same way as control characters. 19961022 change: added version and home page to qmail.7. 19961022 cleanup: introduced slurpclose.c. used it in qmail-alias.c, qmail-lspawn.c. 19961021 portability problem: AT&T NCR boxes need stdio.h before arpa/nameser.h. impact: dns.c would not compile. fix: include stdio.h. tnx HS. 19961021 change: added AIX section to INSTALL.ids. tnx SSB. 19961021 change: added qmail-pw2user. 19961020 change: added qmail-pw2user.8. 19961020 change: qmail-alias now dies soft on EACCES/EPERM for .qmail. 19961020 change: eliminated root comments from INSTALL.qsmhook. 19961020 change: various improvements in FAQ. 19961017 change: added QLX_ROOT. 19961017 change: renamed hosts in FAQ. tnx SLB. 19961017 change: in dot-qmail.5, documented envnoathost effects. tnx RN. 19961017 change: revamped addresses.5. 19961017 change: added stripvdomprepend() for better bounces. tnx PT. 19961012 portability problem: under HP-UX 9, can't setgroups() to 65537. impact: couldn't compile under HP-UX 9. fix: use 0 instead of 65537 in chkshsgr.c. tnx HHO. 19961008 change: added several qlx codes. 19961008 cleanup: eliminated qlx from qmail-alias. 19961008 change: qmail-lspawn runs qmail-getpw as UID_PW. 19961008 change: added qmail-newuser. 19961008 change: added cdb support to qmail-lspawn. 19961008 change: integrated cdb. 19961007 change: added qmail-users.5. 19961007 change: eliminated usermap. 19961007 cleanup: switched execvp to execv in sendmail, qmail-lspawn. 19961007 change: used qmail-getpw in qmail-lspawn. 19961007 change: renamed LSPAWN_USERLEN as GETPW_USERLEN. 19961007 change: added qmail-getpw. 19961007 change: created users subdirectory of CONF_HOME. 19961007 change: fixed typo in FAQ. tnx J1B. 19961006 change: replaced subfdout with a small ss in qmail-alias. 19961006 change: reduced qmail-alias buffer sizes to 1024. 19961003 change: added note to maildir2smtp.0 about maildirmake. tnx SM. 19961003 bug: if ipme_init() returned -1, qmail-remote would continue, blindly assuming that all addresses are local. impact: on systems with too many aliases, all remote deliveries fail. tnx MD. fix: qmail-remote now dies with temp_oserr() on any result other than 1. 19961003 portability problem: all pre-4.9.4 versions of bind barf, badly, on CNAME queries to lame servers. what a crappy system. even if the resolver doesn't barf, the next name server down the line may barf. impact: qmail can't get mail through to domains that are (1) lame and (2) running old versions of bind. fix: never, ever, do a CNAME query. dns_cname() now does an ANY query instead. this, like sendmail's analogous procedure, is unreliable when a CNAME is mixed with other records. 19961001 cleanup: switched to libfd in qmail-start.c. 19960929 cleanup: renamed auto-hasmkffo.h to hasmkffo.h. 19960928 cleanup: reorganized qmail-start.c. 19960928 cleanup: used libfd in preline.c, qmail-lspawn.c, qmail-popup.c, qmail-rspawn.c, qmail-start.c, qqtalk.c, qsmhook.c. 19960928 cleanup: added libfd. 19960927 change: in SECURITY, ``nine most recent sendmail security holes, four'' -> ``ten most recent sendmail security holes, five.'' 19960926 change: added tcpcontrol notes to FAQ. 19960926 change: qmail-smtpd now immediately closes connection, with a warning message dedicated to Solaris, if stray newlines show up in the incoming data. 19960926 change: added INSTALL.boot. 19960926 portability problem: on systems that can handle IP interface aliases (i.e., on sa_len systems), SIOCGIFADDR returns the primary address for an alias. impact: ipme_init() did not include alias addresses. fix: ipme_init() avoids SIOCGIFADDR on sa_len systems; on these systems, the address we want is already in ifr. tnx DM. 19960926 change: qmail-alias kills itself if locking takes longer than 30 seconds. 19960926 change: qmail-pop3d no longer moves messages. tnx RS. 19960924 change: added note to FAQ about descriptors limit. tnx RD. 19960922 change: open_trunc() now uses 644. 19960922 change: qmail-setup now does umask(077). 19960922 change: maildir2mbox now does umask(077). 19960922 change: moved subfderr buf up to 64 characters. 19960920 change: in SECURITY, ``eight most recent sendmail security holes, three'' -> ``nine most recent sendmail security holes, four.'' 19960920 portability problem: init run commands are subject to job control signals under more systems than HP-UX. impact: on some systems (e.g., Solaris), qmail daemons would be killed. fix: INSTALL now tells everybody to use csh -cf. 19960920 change: added queue-run section to FAQ. 19960920 change: in pine-crashing question in FAQ, added -oem and -oi, so that change will work with the real sendmail too. 19960919 change: added CNAME section to FAQ. tnx to various people. 19960919 change: eliminated QQX_EXECHARD and QQT_EXECHARD. this means that all qmail-queue invocation failures are now soft, even things like EPERM. 19960919 change: replaced ``No such address'' with ``Sorry, no mailbox here by that name.'' tnx G2A. 19960919 change: qmail-remote now includes host name in no-such-host messages. tnx G2A. 19960919 change: replaced ``Temporarily unable to canonicalize address'' with ``CNAME lookup failed temporarily.'' 19960918 change: improved an error message in qmail-alias.c. tnx TG. 19960918 change: added SHELL=/bin/sh to Makefile. tnx JL. 19960916 change: reorganized INSTALL.ids a bit. 19960916 change: ``from smtpd'' is now ``from network''. 19960916 change: SMTPD is now DAEMON. 19960916 change: qmail-start sets logger uid to UID_LOG. tnx JLH. 19960916 change: added CONF_USERL. 19960916 change: iaafmt() now puts a dot on in-addr.arpa. 19960915 change: added UPGRADE. suggested by several people. 19960915 change: added qsutil error messages to qmail-log.5. 19960915 change: qsutil error messages are now alerts. 19960915 portability problem: on some systems, logger appears to use syslog(pri,buf) instead of syslog(pri,"%s",buf). tnx JC. impact: logger could barf or crash if fed messages containing %. an attacker could easily cause a crash, eliminating qmail's logs. fix: % is no longer considered safe for logs. 19960912 cleanup: split seek.c into seek_*.c. 19960912 cleanup: replaced seek_to() with seek_set(). 19960912 cleanup: introduced libseek.a. 19960907 cleanup: split case.c into case_*.c. 19960907 cleanup: introduced libcase.a. 19960907 cleanup: split wait.c into wait_*.c. 19960907 cleanup: introduced libwait.a. 19960907 cleanup: renamed auto-haswaitp.h to haswaitp.h. 19960907 cleanup: split open.c into open_*.c. 19960907 cleanup: introduced libopen.a. 19960904 change: added generic pointer to qmail-control.5. tnx HW. 19960904 change: rewrote rcpthosts section in FAQ. tnx HW. 19960904 change: added organization section to FAQ. tnx HW. 19960902 qmail 0.91, gamma. 19960902 change: control_readfile() can now handle partial lines. tnx JDHB. 19960902 change: eliminated non-fqdn note from FAQ. next version of tcpserver will use DNS directly. 19960902 change: qlist now uses NEWSENDER, not SENDER. 19960902 change: qmail-pop3d no longer obtains a lock. tnx RS. 19960902 change: put }g on all seds in Makefile. 19960831 change: noted in qmail-control.5 that comments are not allowed in control files. tnx J2B. 19960829 change: used double union in alloc.c. tnx ME. 19960829 change: replaced semicolon with colon for smtproutes port. 19960829 change: in INSTALL, put make man just before make setup. 19960829 change: changed a few qmail messages into alerts. 19960829 cleanup: renamed datetime_gmt as datetime_tai. 19960829 change: added note to UUCP question that some UUCP software doesn't want preline -f. tnx SB. 19960829 change: added question 2.4 to FAQ on SLIP/PPP. 19960828 change: replaced owner- with owner-@host-@[] in qmail-inject. 19690828 change: replaced owner- with owner-@host-@[] in qmail-alias. 19960828 change: replaced owner- with owner-@host-@[] in injectbounce(). 19960828 change: replaced owner- with owner-@host-@[] in senderadd() for owner hack. 19960828 change: qmail-inject -n now prints Return-Path. 19960825 cleanup: revised ending code in token_addrlist(). 19960825 change: tokenize now uses linelen 0 for unparse. 19960825 change: if linelen is 0 in token822_unparse, no length limit. 19960825 change: added LINELEN macro to qmail-inject for unparse. 19960825 change: token822_unparse now takes linelen argument. (leaving two spaces on the right before linelen.) 19960824 cleanup: renamed token as token822. 19960822 portability problem: under NEWS-OS, /bin/mail and /usr/ucb/mail invoke sendmail with -E and -J options. tnx TU. impact: couldn't send mail with those programs. fix: accept opts, including _optional_ args. ugh. 19960821 change: sendmail now quits if invoked as newaliases. tnx TU. 19960821 portability problem: under NEWS-OS, dirent.h needs sys/types.h. tnx TU. this POSIX violation also appears in some versions of FreeBSD. impact: couldn't compile under NEWS-OS. fix: include sys/types.h in direntry.h* and trydrent.c. [sigh] 19960821 change: added concurrencyremote question to FAQ. 19960821 change: added chkspawn. 19960821 change: moved default SPAWN_NUMD up to 120. 19960818 change: allowed ;port in smtproutes. tnx AL. 19960818 change: introduced port in qmail-remote.c. 19960818 change: qmail-queue records qp in Received lines. 2 lines of code. tnx ME. 19960818 change: in SECURITY, ``seven most recent sendmail security holes'' -> ``eight most recent sendmail security holes.'' 19960818 change: qmail-pop3d now appends an extra blank line to every message, for compatibility with popper. some clients can't deal with the right thing, unfortunately. tnx FPL. 19960818 change: added qmail-tcpto. 19960818 change: eliminated cc -posix for NeXTs. tnx SA. 19960818 change: eliminated loadfifo. tnx SA. 19960818 change: integrated auto-configured fifo.c code from SA. 19960817 change: put SYSDEPS into a more reasonable order. 19960813 change: indicated possibility of duplication when qmail-remote gets a dead connection after DATA. tnx ME. 19960813 change: documented qmail-inject environment variables. 19960813 change: supported per-recipient owner hack in qmail-inject. 19960813 change: supported per-message owner hack in qmail-inject. 19960813 change: introduced hackedruser into qmail-inject. 19960813 change: introduced QMAILRUSER, QMAILRHOST. 19960812 change: added QMAILINJECT option to allow address-comment form. 19960812 change: made name-address form the default in qmail-inject. 19960812 change: added QMAILINJECT options f and m to delete From and Message-ID on input. tnx LL. 19960812 change: added QMAILINJECT environment variable. 19960812 change: added QMAILHOST, QMAILUSER, QMAILNAME to override MAILHOST, MAILUSER, MAILNAME. tnx MG. 19960812 change: added qmail-showctl. 19960812 portability problem: under Solaris 2.4 and possibly other systems, the linker does not give generic alignment to an array of 4096 chars. tnx JP. impact: some subset of the programs would (reliably) die with a bus error; in the Solaris case, maildir2mbox. fix: redefine space in alloc.c to be aligned. 19960812 change: qmail-remote no longer does CNAME lookups if there's an artificial SMTP route. tnx ME. 19960812 change: added flagcname arg to addrmangle() in qmail-remote. 19960812 cleanup: moved host/relayhost processing earlier in qmail-remote. 19960812 change: qmail-remote stops before DATA if no RCPTs were successful. tnx JLH. 19960812 change: rewrote rcpthosts explanation in FAQ. 19960811 change: added qmail-log.5. 19960811 change: introduced ALIAS_PATERNALISM. configurability requested by several people. 19960811 change: eliminated go-writability test for qmeox(). the alleged value of paternalism is nonexistent if nobody even notices you're doing it. 19960811 change: in qbiff, changed no-/-allowed to no-/-at-beginning, no-dots-allowed, must-be-nonempty. tnx MD. 19960811 change: in mbox.5, discouraged mail readers from looking for From_ lines only after blank lines. too much crap in the world. 19960811 change: added subject line to qreceipt success notices. 19960811 change: added subject line to qmail-send bounce messages. 19960811 change: qmail-alias now expects dash arg. this finally gives lspawn complete control over the local -> ~user/.qmail-ext map. 19960811 change: qmail-lspawn passes dash arg to qmail-alias. 19960811 change: reorganized qlist acknowledgment format. again. 19960811 change: documented EXT, EXT2, EXT3, EXT4. tnx BB. 19960810 change: qmail-makectl now copies locals to rcpthosts. should be a better default. suggested by TK. 19960805 portability problem: new makefile generator put in tabs again. sigh. impact: couldn't compile under some systems. fix: same as before. tnx TG. 19960804 change: added tcpserver instructions to FAQ. 19960804 change: reorganized FAQ server instructions into a new section. 19960801 qmail 0.90, gamma. 19960801 change: qmail-qmtpd now supports rcpthosts, RELAYCLIENT. 19960731 change: default NUMD is now 29. this prepares for weird systems where getpwnam() needs more than one descriptor (but the descriptor limit is still 64! ... you never know), and for possible future getpwnam() replacements. 19960731 change: popped subfderr buffer up to 32 characters. made sure that everybody flushed subfderr as necessary. 19960731 change: maildir2qmtp now prints filenames and responses. 19960731 change: maildir2smtp now prints filenames it's trying and relevant portion of SMTP responses. 19960731 change: used succwrite() in maildir2smtp, maildir2qmtp. simplifies code quite a bit. 19960731 change: qmail-remote's blast() checks sooner for write errors. 19960731 change: added better -e option to sendmail. tnx TG. 19960731 change: added maildir2qmtp. 19960730 cleanup: eliminated die_nomem() in maildir2smtp.c. 19960730 change: dns_cname now pretends that "foo." is a CNAME for "foo" to give the desired behavior for people who misuse DNS and violate RFC 822. tnx RN. 19960730 change: dns_cname now tests for empty names and ] on every loop. 19960730 change: used LSPAWN_BREAK in qmail-send.c for usermap. 19960730 change: updated header example in qmail-header.5. 19960730 change: added printbreak. auto-configured BREAK in dot-qmail.5, qmail-lspawn.7, qmail-send.8, qmail-upgrade.7, qlist2. 19960730 change: added printnumd. auto-configured NUMD in qmail-send.8, qmail-limits.8. 19960730 change: added printsplit. auto-configured split in qmail-upq. 19960730 change: added dot-qmail.5. 19960730 change: qmail-smtpd now treats HELO as including RSET. 19960730 change: added moreinfo to qlist usage message. 19960729 change: improved an error message in qmail-alias. 19960729 cleanup: merged qmeox(), qmeodx(). 19960729 bug: failure to stat .qmail-owner was not an error. impact: if stat failed temporarily (e.g., because of NFS), .qmail-owner would be incorrectly ignored, so outgoing message would have wrong envelope sender. fix: qmail-alias does temp_nfsqmail() if stat() returns a temporary error. 19960729 change: added RFCOWNER. 19960729 change: added qmtpd setup question to FAQ. 19960729 change: added qmail-qmtpd. 19960728 change: revamped maildir2smtp error messages. 19960728 change: revamped maildirwatch error messages. 19960728 change: revamped maildir2mbox error messages. 19960728 change: used strerr in maildir_scan(). 19960728 change: used strerr in maildir_chdir(). 19960728 change: introduced strerr. 19960728 bug: the new tcp-env tried to read from an ndelay socket. impact: TCPREMOTEINFO would always be empty. fix: unset ndelay in remoteinfo.c. 19960728 bug: if maildir2smtp saw a permanent failure after MAIL, it failed to do RSET. impact: all further messages would be rejected at the MAIL stage. fix: maildir2smtp now always does RSET. tnx JW. 19960728 cleanup: qmail-alias now applies lowercase and dot-to-colon conversion directly to dashext, leaving everything else alone. this works since all .qmail access is factored through dashext. 19960727 portability problem: under NeXTStep, -posix is almost entirely broken. impact: qmail daemons would dump core under NeXTStep. fix: turn off -posix, except for loading qmail-setup, which needs mkfifo(); NeXT, bless them, didn't put mkfifo() into the C library where it belongs. this requires a new make command, namely loadfifo. 19960727 change: all characters 33-126 are now considered safe for logs. tnx MD. 19960727 cleanup: eliminated qp variable from mailforward(). 19960727 cleanup: maildirwatch.c includes headerbody.h. 19960727 cleanup: eliminated match from maildirwatch.c. 19960727 cleanup: eliminated code variable from maildir2smtp.c:doit(). 19960727 cleanup: maildir2smtp.c includes scan.h. 19960727 cleanup: maildir.c includes str.h. 19960727 cleanup: qmail-popup.c now includes exit.h. 19960727 cleanup: qmail-pop3d.c now includes exit.h. 19960727 cleanup: eliminated path from qmail-start.c. 19960727 cleanup: eliminated birthplusnn from nextretry(). 19960727 cleanup: eliminated r from timeoutconn(). 19960727 cleanup: tcpto.c now includes byte.h. 19960727 cleanup: spawn.c now declares initialize(). 19960727 cleanup: qmail-lspawn.c now includes str.h, byte.h. 19960727 cleanup: qmail-inject.c now includes quote.h. 19960727 change: qmail-check now checks separately for group readability and other readability. 19960727 bug: maildir2smtp didn't check flagehlo in PIPELINING parsing. impact: a server that said PIPELINING at any point, not just EHLO, would receive pipelined data. fix: check flagehlo. 19960727 bug: readsubdir was calling pause(). impact: if a subdirectory was removed, qmail-send would hang. fix: use rs->pause(). 19960727 change: used error_str in qmail-qread. 19960727 change: qmail-qread now looks for local/remote open errors. 19960727 cleanup: added warn() in qmail-qread.c. 19960727 change: qmail-qread now exits 111 for temporary errors. 19960727 change: used error_str in qmail-setup. 19960727 change: introduced error_str. 19960727 change: replaced qmail-check with make check in INSTALL. 19960727 change: added check target to Makefile. 19960727 change: replaced qmail-setup with make setup in INSTALL. 19960727 change: indirected fake targets through do- targets. 19960727 change: added setup target to Makefile. 19960727 change: qmail-makectl now makes sure that defaultdomain has at least one dot. e.g., enteract.com -> enteract.com, not com. 19960726 bug: quote() failed to quote commas. impact: addresses containing commas would not have been quoted correctly for Return-Path or for SMTP MAIL FROM. fix: quote commas. 19960726 change: sendmail now mentions qmail-qread, not qmail-mailq. 19960726 change: qmail-alias now expects ext arg. this eliminates LSPAWN_BREAK from qmail-alias and gives lspawn almost complete control over the local -> ~user/.qmail-ext transformation. the exception is that qmail-alias always uses ~user/.qmail, ignoring ext, if local is the same as user. 19960726 change: qmail-lspawn passes ext to qmail-alias. 19960726 change: alloc() now uses up a 4K space before calling malloc(). 19960726 change: ipalloc allocation base is now 10. 100 was silly. 19960726 change: stralloc allocation base is now 30. 19960726 change: injectbounce() now supports the owner hack. 19960726 change: qmail-smtpd no longer requires HELO. tnx K1J. 19960726 cleanup: replaced makereceived() with dohelo(). 19960726 change: qmail-smtpd is back to 555 for syntax errors. 19960725 change: qmail-alias now supports the owner hack. tnx to RN for prodding me to look at this problem. 19960725 change: senderadd() now supports the owner hack. 19960725 cleanup: split off senderadd(). 19960725 change: added pine-crashing note to FAQ. 19960725 change: added procmail config.h note to INSTALL.mbox. 19960725 change: added elm TMPDIR note to INSTALL.mbox. 19960725 change: added pine.conf note to INSTALL.mbox. 19960724 change: added fixup note to FAQ. 19960724 change: qmail-inject now exits 111 for temporary errors. 19960724 change: qmail-smtpd now appends RELAYCLIENT to incoming recipient domain names. 19960724 cleanup: moved relayclient out of qmail-smtpd's addrallowed() into caller. 19960724 change: added rcpthosts wildcards. 19960724 change: added clean target to Makefile. 19960723 change: added virtualdomains exceptions. 19960722 change: added BLURB4. 19960722 change: added BLURB3. 19960722 change: eliminated smarthost and localnet. 19960722 change: incorporated relaymap, contributed by LW. renamed it as smtproutes. 19960722 change: qmail-popup now supports APOP. suggested by BG, who distributed similar changes. 19960722 change: qmail-popup now sends APOP timestamp to checkpassword. 19960722 cleanup: in qmail-popup, split off doanddie(). 19960722 change: qmail-popup now prints APOP timestamp in banner. 19960722 change: added hostname argument to qmail-popup. 19960722 cleanup: in qmail-popup, split out() into out(), outflush(). 19960722 cleanup: in qmail-popup, introduced pop3_greet(). 19960721 portability problem: under Unisys SVR4, hostname is not in the usual path. impact: qmail-makectl fails. fix: added hostname command here, used it in qmail-makectl. 19960721 portability problem: on some sysctl-based systems, apparently gethostname() doesn't write anything if the output buffer is too small. it should write a truncated name. impact: if anyone has a hostname longer than 64 characters, maildirs could get up to 64 characters of garbage, rather than a truncated hostname. fix: qmail-alias now does *host = 0 before calling gethostname. 19960721 change: updated FAQ examples from qsmhook to preline. 19960721 change: added preline. 19960721 change: qsmhook now uses signal_init, signal_uninit. 19960721 change: qsmhook now checks specifically for empty args. 19960721 change: documented mbox. 19960721 change: added EXT, EXT2, EXT3, EXT4. 19960721 change: added LAST response to qmail-pop3d, always returning OK 0. tnx RN. 19960721 change: added qmail home page to README. 19960721 change: added HELP response to qmail-smtpd. tnx RN. 19960720 change: expanded, vertically, the qmail-inject error message for unparseable header fields. 19960720 change: logo is now dolphin. tnx CEJ. 19960719 qmail 0.76, beta. 19960719 change: used LSPAWN_BREAK in qmail-alias for deciding how to handle extensions. this should produce better behavior in the (unsupported) case that LSPAWN_BREAK is not a hyphen. 19960719 bug: qmail-smtpd didn't check for null arg on MAIL, RCPT. impact: qmail-smtpd would deref 0 and crash. fix: qmail-smtpd now gives syntax error on null arg. 19960719 change: documented UFLINE in qmail-command.8. tnx TG. 19960718 change: added maildir2smtp. 19960718 cleanup: introduced maildir.c. used it in maildir2mbox.c, maildirwatch.c. 19960718 change: added maildirwatch. 19960718 cleanup: maildir2mbox now sets up pq2 as it is deleting from pq, rather than simultaneously with pq. 19960718 change: added H_DELIVEREDTO. 19960718 portability problem: Unisys requires -lsocket -lnsl. impact: couldn't compile under Unisys. fix: added unix_sv section to make-cmds.sh. tnx TVP. 19960718 change: added unix_sv section in find-systype. tnx TVP. 19960717 change: qmail-alias now appends newline if .qmail does not end with a newline. tnx MC. 19960717 change: qmail-alias now defers delivery for a blank line only if it is the first line of the file. handles user behavior described by MC of putting many newlines at end of file. 19960717 bug: qmail-inject looked for dots in user part, not just host part, when deciding whether to use defaultdomain. impact: the address joe.bloggs@here didn't have defaultdomain added. fix: qmail-inject now stops at the @. 19960717 change: updated INSTALL.alias to mention qmsmac. 19960717 change: syntax error code for SMTP is now 501. 19960717 change: added -e option to sendmail. tnx TG. 19960716 change: changed ~alias files to .qmail-local, not .qmaillocal. suggested by many people. 19960716 change: redid qmail-alias/qmail-lspawn interface. 19960716 change: replaced EXTENSION, USEREXT with LOCAL. 19960716 change: qmail-queue now removes intd, mess upon error, as long as it doesn't time out. suggested by BB et al. 19960716 change: added flagmademess, flagmadeintd to qmail-queue.c. 19960716 cleanup: changed todofd to intdfd in qmail-queue.c. 19960716 cleanup: added cleanup() to qmail-queue.c. 19960716 change: added timeout to tcp-env.c, default 30 seconds. 19960716 change: remoteinfo_get() now uses timeoutconn(). 19960715 change: added procmail config.h note to FAQ. 19960704 change: qmail-upgrade.7 now warns administrators that ~alias generally doesn't apply to addresses starting with a user name. 19960703 change: added echo \c note to FAQ. tnx PJG. 19960702 change: qmail-smtpd now accepts HELO without an argument. tnx K1J, J1B. 19960627 change: qmail-lspawn.8 now mentions that qmail-lspawn doesn't set up supplementary groups. tnx TG. 19960625 portability problem: under Linux, read(,,0) doesn't do proper error slippage. impact: timeoutconn() would always report success; if a connection failed, qmail-remote would report a greeting failure and skip all further MX records. tnx ME. fix: timeoutconn() now uses getpeername() to check for success. 19960625 change: qmail-smtpd now mentions disk full for QQT_WRITE. 19960625 change: qmail-inject now mentions disk full for QQT_WRITE. 19960622 change: if RELAYCLIENT is set, qmail-smtpd skips rcpthosts. 19960609 change: updated INSTALL for current SMTP responses. 19960607 change: clarified INSTALL.qsmhook examples. tnx S1R. 19960607 change: added subject parsing to qlist.c. tnx RN. 19960607 cleanup: used case_diffb in qlist.c. 19960607 change: added extra log information to INSTALL examples. 19960606 change: added -Pn to uucp line in FAQ. tnx DWS. 19960605 portability problem: under Solaris, /usr/bin/groups incorrectly reports your groups in /etc/group, rather than the results of getgroups(). tnx MD, PJG. impact: test #19 in INSTALL fails. fix: added special note to test #19 (sigh) about Solaris. 19960605 change: improved maildir setup commands in INSTALL.mbox. 19960605 change: on success, qmail-alias logs forwarding qp. 9 lines extra code. 19960605 change: qmail-send logs qp for bounce. 6 lines extra code. 19960605 change: qmail-smtpd includes qp in its response when it accepts a message. 7 lines extra code. requested by MD and others. 19960605 change: added qqtalk_qp. 19960605 change: qmail-send now logs uid and qp from todo file. 14 lines extra code. 19960605 change: qmail-queue now records uid and qp in u and p lines in todo file. 7 lines extra code. 19960605 change: improved qmail-alias x-bit error messages. 19960605 change: newline in log is now converted to /, not underscore. 19960604 change: when it accepts a message, qmail-smtpd includes the local time in its 250 response. 19960604 change: on success, qmail-alias prints delivery counts, file+forward+program. 19960603 change: qmail-remote now reports IP address on success. tnx MD. 19960603 change: qmail-send now logs success and failure reports, not just deferral reports. 19960603 change: added netbsd section in find-systype, same as bsd.os section. this will affect netbsd-* systypes. tnx MBS. 19960530 qmail 0.75, beta. 19960528 change: added qmail.7. tnx MD. 19960525 change: added qmail-pop3d. tnx RN. 19960525 change: added qmail-popup. tnx RN. 19960525 change: added elm filter section to FAQ. tnx GB. 19960502 portability problem: on many systems, select() on an almost-full pipe incorrectly says writable. tnx ME for running into this and helping track it down. impact: if qmail-send writes a pipeful to qmail-lspawn or qmail-rspawn before they can react (because of high concurrency, high load, or long addresses), it will receive an incorrect -1/EAGAIN, and will conclude that spawn died. sysadmin will have to restart qmail, and messages will be duplicated. fix: in qmail-send.c, busy-loop if write() to spawn returns any error other than EPIPE. 19960501 bug: qmail-alias treated NAMETOOLONG and NOTDIR as temporary errors. impact: qmail-alias never looked for -default; even if mail was destined to bounce, it would have to time out first. fix: qmail-alias now uses error_temp(). 19960430 bug: qmail-smtpd treated qq crash as permanent error. impact: if somebody actively kills qq, mail will be incorrectly bounced. tnx SS. fix: qmail-smtpd now treats only TOOLONG and EXECHARD as permanent errors. 19960430 cleanup: eliminated QQT_TTY from qqtalk.h. 19960428 change: added ``warning: '' before trouble-marking message. 19960428 change: added percenthack. requested by GB. 19960428 cleanup: switched to auto-generated Makefile. 19960428 cleanup: switched to auto-generated .o dependencies. 19960428 cleanup: eliminated fmt.o, scan.o from Makefile. 19960428 portability problem: under HP-UX 10, the rc pgrp is sent HUP when rc finishes. tnx BG. impact: the qmail daemons are killed when rc finishes. fix: added special note in INSTALL (sigh) to use csh -cf. 19960427 cleanup: added PORT_SMTP in qmail-remote.c. 19960427 cleanup: introduced timeoutwrite.c. used it in qmail-remote.c. 19960427 cleanup: introduced timeoutread.c. used it in qmail-remote.c. 19960427 cleanup: introduced timeoutconn.c. used it in qmail-remote.c. 19960427 change: added timeoutconnect. default: 60 seconds. 19960427 change: added pop3d instructions to FAQ. tnx RN. 19960427 change: eliminated env manipulation from qmail-start. tnx BG. 19960427 change: headerbody now ends header, inserting blank line, if first line of a header field doesn't pass hfield_valid. tnx TG. 19960427 change: headerbody now prepends MBOX-Line: to any header line starting From_. this lets qmail-inject work with elm's bounce. tnx OR, K1J, et al. 19960426 change: added moreinfo arg to qlist and qlist2. 19960426 change: added signal_uncatchchild() to qmail-send.c. tnx BG. now, if sysadmin sets SIGCHLD to SIG_IGN before invoking qmail-send [sigh], qmail-send won't screw up bounce messages. 19960426 change: dns_cname now checks whether last character is ], rather than whether first character is [, for quick return. 19960426 cleanup: glue is now global in dns.c. 19960426 cleanup: qmail-remote no longer does stralloc_0 for host and canonhost. 19960426 change: dns_mxip no longer rejects [foo].bar. 19960426 change: dns_mxip no longer requires for bracket that input be 0-terminated. 19960426 change: qmail-start can now take logger as an argument. 19960426 change: qmail-start now invokes qmail-send in foreground (as parent of other processes). 19960426 change: added mailsubj. tnx GAW. 19960426 portability problem: under some systems, can't lock read-only file. impact: maildir2mbox would always fail on those systems. fix: maildir2mbox now opens a separate lock fd. tnx BG. 19960426 cleanup: removed unnecessary #!/bin/sh and # AUTO from mctl.sh. 19960426 change: added qmail-qstat. 19960426 change: added qmail-qread.8. 19960426 change: renamed qmail-mailq as qmail-qread. 19960419 change: qmail-alias now defers delivery rather than skipping blank lines in .qmail. 19960419 change: in qmail-lspawn.c, lowercased name before getpwnam(). really getpwnam() should do this, but oh well. 19960419 change: added username to qmail-lspawn.c, with LSPAWN_USERLEN in conf-unusual.h. names longer than LSPAWN_USERLEN will skip getpwnam(). 19960419 change: if qlist doesn't see any cmds, it presumes that you meant to subscribe. 19960419 change: reorganized qlist acknowledgment format. 19960415 change: reorganized and rewrote FAQ. 19960415 change: renamed HOWTO as FAQ. 19960414 change: in qmail-alias, converted extension to lowercase just before qmeopen(), qmeox() calls. thus EXTENSION and USEREXT and RECIPIENT will preserve case passed by qmail-lspawn, while .qmailext lookups will not. 19960414 change: removed case_lowers(r) from qmail-lspawn.c. tnx JLH. 19960414 change: moved extension . -> : conversion to just before qmeopen(), qmeox() calls in qmail-alias.c. thus EXTENSION and USEREXT and RECIPIENT will preserve dots. 19960414 change: qsmhook -x now does case-independent comparison. 19960413 change: added procmail instructions to HOWTO. 19960409 bug: qmail-alias does not check for newlines when it generates Return-Path. impact: resulting Return-Path header field will be illegal, if sender address contains newline followed by something other than whitespace. fix: qmail-alias now replaces newline with underscore in rpline. 19960409 change: added leaf UUCP description to HOWTO. tnx J2K. 19960409 change: added -B option to sendmail. tnx OR. 19960409 change: qlist now makes lists unwritable (after renaming from .qtemp to .qmail). tnx MLH. 19960409 change: added flagdtline to qsmhook.c, based on -l option. 19960409 change: added PIPELINING declaration to qmail-smtpd. tnx JGM. 19960409 change: qmail-smtpd now flushes output instantly after DATA, QUIT, HELO, EHLO, NOOP, VRFY, or any 502. 19960409 change: qmail-smtpd now flushes output upon read() and death. 19960409 change: qmail-smtpd no longer flushes output in out(). 19960409 change: increased qmail-smtpd outbuf size from 128 to 512. 19960409 cleanup: in qmail-smtpd, eliminated ssinit() in favor of FDBUF. 19960409 bug: qmail-alias produced aliasfoo-owner rather than foo-owner as envelope sender for ~alias/.qmailfoo. tnx DS. impact: wrong envelope sender whenever ~alias/.qmailfoo-owner existed. fix: qmail-alias now checks for hyphen at beginning of extension. 19960409 change: added _ESMTP to end of 220. tnx JLH. 19960409 change: moved out("\r\n") out of smtp_greet() into callers. this improves the flushing behavior on 221. 19960328 qmail 0.74, beta. 19960326 change: changed subdirectory split from 32 to 23. 19960326 portability problem: some versions of make don't understand that a line with just a tab is blank. impact: couldn't compile under those systems. fix: eliminated extra tab from Makefile. tnx TG. 19960325 change: added qmail-mailq. 19960325 change: introduced readsubdir. 19960325 change: qmail-setup makes split; qmail-check checks split. 19960325 change: used split in qmail-send, qmail-clean, qmail-queue for mess, info, local, remote. 19960325 change: fmtqfn now supports split queue subdirectories. 19960325 cleanup: eliminated cat2s(). 19960325 cleanup: introduced fmtqfn.c. used it in qmail-queue.c, qmail-send.c, qmail-clean.c. 19960325 change: in protocol between qmail-clean and qmail-send, now using intd/ instead of mess/. 19960325 change: qmail-queue.c and triggerpull.c now work inside queue subdirectory. 19960325 change: spawn.c now checks whether message is a regular file. 19960325 change: spawn.c now allows slashes in messid except at beginning. 19960325 cleanup: introduced fnmake_split in qmail-send.c. 19960325 cleanup: eliminated strnum in qmail-send.c in favor of fnmake_{info,todo,mess,chanaddr} and fnmake2_bounce. 19960325 cleanup: introduced strnum3 in qmail-send.c for the logging uses of strnum. 19960325 cleanup: in qmail-send.c, getinfo() now takes id argument. 19960325 cleanup: qmail-send.c now preallocates space for fn, fn2. 19960325 change: time zone is now -0000 instead of +0000. encouraging DRUMS to use this as an i-don't-know-the-local-time indicator. 19960324 change: qmail-rspawn.c now calls tcpto_clean(). 19960324 cleanup: spawn.c now calls initialize(). 19960324 change: qmail-setup makes lock/tcpto; qmail-check checks it. 19960324 change: qmail-remote now quickly skips connect() to a host that seems to be down. tnx BP for pressuring me to get this done. 19960323 change: in qmail-alias.8, renamed mboxg as mboxrd. tnx RD. idea was popularized by RD in June 1995. 19960322 cleanup: eliminated subfd_init(). 19960322 change: qbiff now removes the word Subject. 19960322 change: now /bin/true instead of /dev/null in the generic INSTALL.ids instructions. tnx JPR. 19960322 change: added hfield_skipname(). tnx RN. 19960322 bug: qmail-inject did not check whether USER needed quoting. impact: if USER had weird characters, the From address would generally be wrong, unless the user manually set up MAILUSER with proper quoting. fix: qmail-inject sets up a quoted-string if necessary. 19960322 cleanup: separated out quote_need() in quote.c. 19960322 cleanup: added stralloc_catb.c. used it in qmail-alias.c, qmail-send.c. 19960322 change: qmail-send now uses a quadratic retry schedule from birth of each message. this also eliminates clustering. 19960322 cleanup: separated out nextretry() in qmail-send.c. 19960322 change: qmail-remote now passes all non-@ addresses through without comment, not just <> and <#>. 19960322 change: replaced # test with anything@[] test in qmail-inject. 19960322 change: replaced # with #@[] in qlist.c, qmail-alias.c, qmail-send.c, qreceipt.c. 19960322 change: qmail-lspawn no longer discards messages to <#>. 19960322 cleanup: in qlist, used str_diff for <> and <#> tests. 19960322 change: qmail-alias is now back to testing envelope sender for <> and <#>, rather than things without an @. 19960321 change: added 8BITMIME support to qmail-smtpd. 19960321 change: added ESMTP support to qmail-smtpd. 19960318 change: used NEWSENDER in place of SENDER for |forward. 19960318 change: added NEWSENDER. 19960318 change: added HCMSSC support to qmail-alias.c. 19960318 change: added HCMSSC support to spawn.c. 19960318 change: added HCMSSC support to qmail-remote.c. 19960318 change: added HCMSSC support to qmail-smtpd.c. 19960317 portability problem: SCO requires -lsocket -lnsl. impact: couldn't compile under SCO. fix: added SCO section in make-cmds.sh. tnx JPR. note that this is for OSR 5; 3.2v4.2 will need more fixes, and old 3.2 is basically hopeless. 19960317 bug: newfield_datemake would leave newfield_date alone if it was already initialized, even though qmail-send calls newfield_datemake anew for each bounce. impact: bounce messages would usually have an incorrect Date field. fix: redid newfield_datemake to update newfield_date each time. 19960317 change: allowed . and @ in 822 phrases; 822 doesn't allow them, but they do show up. tnx to the DRUMS group. 19960317 change: replaced GMT with +0000 in date822fmt.c. this confuses a few versions of getdate(), but the DRUMS group is going to outlaw GMT, not just recommend against it as in 1123. 19960317 change: redefined ALIAS_EMPTY to take advantage of . for file deliveries. tnx RN. 19960317 change: qmail-alias now allows . as well as / to start file deliveries. tnx RN. 19960317 change: qmail-alias now dies (soft) if .qmail is writable to others, rather than silently ignoring it. 19960317 change: qmail-alias now dies (soft) if flagforwardonly is violated, rather than silently ignoring the bad instructions. 19960317 change: qmail-alias now ignores x bit on empty .qmail files. 19960317 bug: if RCPT gave 4xx and DATA gave 5xx, qmail-rspawn would incorrectly assign a permanent failure to that recipient. impact: in that case, mail would be incorrectly bounced. fix: remove orr > 0 test from qmail-rspawn.c. 19960310 change: tcp-env now uses signal_uninit(). [sigh] 19960310 change: tcp-env now specifically unsets HOST and INFO if they are not applicable. just trying to make it more widely usable. 19960310 cleanup: used byte_* in remoteinfo.c, ipme.c, tcp-env.c. 19960310 cleanup: added readwrite.h, eliminated sys.h. 19960310 cleanup: included byte.h in qmail-send.c. 19960310 cleanup: eliminated i and j from forward.c's main(). 19960310 cleanup: eliminated wstat from qlist.c. 19960310 cleanup: eliminated die_nomem() parameter in qmail-setup.c. 19960310 cleanup: eliminated i from qmail-remote's addrmangle(). 19960310 cleanup: added exit.h. 19960310 cleanup: split ipalloc.c off of ip.c. 19960310 cleanup: added fmt_strn.c, eliminated fmt_strncpy.c. 19960310 change: reorganized INSTALL to do some pre-upgrade tests. tnx RN. 19960310 change: reordered steps in upgrade procedure in INSTALL. 19960308 change: eliminated ownership test in qmail-alias.c. tnx DS. 19960304 change: in SECURITY, ``six most recent sendmail security holes'' -> ``seven most recent sendmail security holes.'' 19960303 qmail 0.73, beta. 19960303 change: added SYSDEPS. 19960303 cleanup: revamped select.h autoconfiguration. 19960303 cleanup: revamped fork.h autoconfiguration. 19960303 cleanup: revamped direntry.h autoconfiguration. target is now direntry.h; auto-hasdrent.h is gone. 19960303 change: tryflock.c now includes , for consistency with lock.c. may affect portability. 19960302 portability problem: under BSDI, can't set sticky on normal files. dorks. impact: the new qlist doesn't work under BSDI; be glad I test things before release. fix: qmail-alias and qlist now use executable instead of sticky. 19960302 change: gfrom now quotes >From and >>From etc. as well as From; in other words, I'm switching from mbox format to mboxg format. 19960302 cleanup: added gfrom.c. used it in qmail-alias.c, maildir2mbox.c. 19960302 change: addbounce() now substitutes \n\n -> \n/ in reports, and \n -> _ in recips. thus bounces can now be reliably parsed. 19960302 change: if qmail-send had trouble reading the original message or the list of addresses for a bounce, it used to give up and send a bounce with "Oh no! I had trouble reading the rest of your message" or some such. now it aborts the bounce attempt and tries again later. 19960302 cleanup: added qqtalk_fail(). used it in qmail-alias.c, qmail-smtpd.c. 19960302 bug: if mailforward() had trouble reading message (e.g., because of an I/O error), it marked an error but kept reading. impact: could loop forever. fix: upon error, break. 19960302 change: maildir2mbox now scans (restrictively) for return-path. 19960302 change: qbiff now prints subject and body, up to 74 chars. 19960302 change: added H_SUBJECT to hfield. 19960302 change: qbiff now puts TO before FROM. 19960301 cleanup: added fmt_str.c. used it in many places. 19960301 change: qmail-send now says something if you've told it to exit but it's waiting for some deliveries. tnx RN. 19960301 change: qmail-alias -n now continues (with warning) if home directory is sticky. tnx RN. 19960301 change: improved usage messages in qmail-alias.c. tnx RN. 19960301 change: put limit on length of addresses in qlist. 19960301 change: added exit 99 support to qmail-alias. tnx RN. 19960301 change: qmail-alias now exits immediately on temporary or permanent error. rewrote section in qmail-alias.8 accordingly. 19960301 cleanup: eliminated flagsuccesses from qmail-alias.c. 19960301 change: added usermap. 19960301 bug: failure to append to mbox was a permanent error. impact: if mbox was temporarily unopenable (e.g., because fds were low), mail would be incorrectly bounced. fix: failure is now temporary. tnx DS. 19960229 change: qmail-alias now preserves any envelope sender that doesn't contain an @, not just <> and <#>. 19960229 cleanup: revamped byte_* interface. 19960229 cleanup: renamed str_cpy as str_copy. 19960229 cleanup: added str_chr.c. used it in qbiff.c, qmail-smtpd.c. 19960229 cleanup: added str_rchr.c. used it in qmail-send.c, quote.c, qmail-remote.c. 19960229 cleanup: added byte_rchr.c. used it in qmail-smtpd.c, spawn.c. 19960229 cleanup: used USEREXT instead of RECIPIENT in qsmhook.c. 19960229 cleanup: used USEREXT instead of RECIPIENT in qbiff.c. 19960229 cleanup: removed j and k from rewrite() in qmail-send.c. 19960229 portability problem: under HP-UX 10 and Solaris 2.5, can't setgroups()/setgid() to the system's nogroup/nobody gid. dorks. impact: inetd chokes, so all SMTP connections are rejected; and ``alias'' mail, including postmaster, bounces. fix: in INSTALL.ids, set up a separate powerless gid (tentatively ``nofiles'') for qmaild and alias. tnx DS and PJG. 19960229 change: qreceipt now uses qqtalk rather than qmail-inject. 19960229 change: qlist now uses qqtalk rather than qmail-inject. 19960229 change: incorporated qmail-setup patch from RN for better error messages. 19960228 change: added LSPAWN_BREAK in conf-unusual.h; used it in lspawn.c. configurability requested by PJG. 19960228 portability problem: on several systems, including everything from DEC, select() on a pipe reader returns 1 if there aren't any writers yet. pointed out by DS. impact: qmail-send chewed up lots of CPU time. fix: trigger_set() now opens the pipe for writing after opening it for reading. also added trynpbg1; on working systems, no point in wasting the extra fd. 19960228 change: qmail-alias uses .qmail sticky bit for forwardonly. 19960228 change: qlist now sets sticky bit on .qmail file. 19960228 change: un-documented +list. 19960228 portability problem: on HP-UX and possibly other systems, the supplementary group list does not include the gid. pointed out by DS. impact: on those systems, tryshsgr could incorrectly set hasshsgr; this would prevent qmail-send from running. fix: if tryshsgr sees that getgroups() returns 0, now it actively sets up a supplementary group list. added chkshsgr to make sure the setgroups() will work. 19960227 cleanup: eliminated GETSHORT in dns.c in favor of getshort(). 19960227 cleanup: deleted h->len < 3 test from qlist.c:dobody. tnx RN. 19960227 change: replaced ~ with $HOME in INSTALL.mbox. 19960227 change: added note about setgid-mail bits to INSTALL.mbox. 19960227 change: added forward.1. 19960227 change: modified forward to allow multiple addresses. 19960227 change: modified forward to take an entire address, not just a hostname. 19960227 change: renamed qrelay as forward. 19960227 change: added USEREXT support to qmail-alias. 19960227 change: added -F to sendmail. the need for this was pointed out by RN. 19960227 change: added 2 bytes of slop in alloc(). 19960227 bug: received_setup() was not allowing space for the final \0. impact: none; the line length is always between 65 and 75 characters, which gives at least 45 characters of slop with existing malloc() implementations. fix: leave space. tnx NH. note that the bug here is really in fmt_strncpy, which was written before i was truly free of the curse of libc.a. 19960227 change: added ALIAS_EMPTY in conf-unusual.h; used it in qmail-alias.c. tnx PJG. 19960227 change: added SPAWN_NUMD in conf-unusual.h; used it in spawn.c. 19960227 change: added conf-unusual.h. 19960227 cleanup: replaced sizeof(short) with 2 in dns.c. 19960227 portability problem: on an Alpha, long is 64 bits. pointed out by DS. impact: address lookups produced incorrect results on an Alpha; qmail-makectl and qmail-remote failed. fix: replaced sizeof(long) with 4 in dns.c. 19960227 portability problem: on an Alpha, bzero() is declared properly via sys/time.h. impact: couldn't compile on an Alpha. fix: removed bzero() declaration from select.h. tnx DS. 19960227 portability problem: under SCO, sys/file.h is not protected. impact: couldn't compile under SCO. fix: include sys/types.h in lock.c. tnx RN. 19960219 change: added some .qmail-list hints to qlist.1. 19960219 change: added +list support to qmail-alias. 19960215 change: added THANKS. 19960212 bug: foo was not initialized in qrelay.c. impact: depends on the machine; on some machines, no effect; on other machines, guaranteed core dump. fix: initialized foo. tnx DS. 19960209 qmail 0.72, beta. 19960209 change: qmail-alias now replaces dot, not slash, with colon. also, qmeopen() makes sure that .qmail file is S_IFREG; I hope this doesn't cause portability problems. 19960209 change: added success-reporting procedure to INSTALL. 19960208 change: added VERSION. 19960208 change: added qlist2. 19960208 change: revamped qlist interface. tnx RN. 19960208 change: improved an error message in qlist.c. 19960208 change: added qrelay. added relay section to HOWTO. tnx DS. 19960208 cleanup: included substdio.h in qqtalk.h. 19960207 bug: prioq_delmin() wasn't guaranteeing heap structure on the last element. impact: scheduled passes could have been delayed, conceivably as long as half an hour. fix: prioq_delmin() now checks when it can safely move the last element. 19960207 change: added maildirmake.1, maildir2mbox.1. 19960206 change: revised logo paragraph in THOUGHTS. 19960206 change: replaced nowhere.org with nowhere.mil in examples. nowhere.org is a real domain... [sigh] 19960206 change: added qreceipt.1. 19960206 portability problem: IRIX doesn't have vfork. pointed out by DS. impact: couldn't compile under IRIX. fix: added fork.h, tryvfork.c. 19960206 portability problem: IRIX doesn't have ranlib. pointed out by DS. impact: couldn't compile under IRIX. fix: added IRIX section in make-cmds.sh. 19960205 cleanup: removed warning from substdio_copy() documentation; in fact, substdio_copy() can be used safely on a fed substdio. 19960205 change: added qbiff.1. 19960204 change: implemented localnet. removed relevant paragraph from THOUGHTS. tnx IS. 19960204 change: in qmail-remote.8, explained the dangers of smarthost. tnx IS. 19960204 change: implemented virtualdomains wildcards. tnx JLH. 19960203 change: qmail-send now handles virtualdomains _after_ locals. updated INSTALL.qsmhook appropriately. 19960203 change: added note to INSTALL.alias about ~ftp, ~www, ~uucp being owned by root. 19960130 cleanup: in qlist.c, renamed flagremoved as flagwasthere. 19960130 bug: qmail-send did not pay attention to flagexitasap in pass_dochan(). impact: qmail-send would happily start new deliveries even if it wanted to exit. fix: qmail-send now returns immediately in pass_selprep() and pass_dochan() if flagexitasap. 19960130 change: in qlist.c and qlist.1, renamed ext as list. 19960130 change: in qlist.c and qlist.1, renamed manager as owner. 19960129 qmail 0.71, beta. 19960129 change: mentioned djb-qmailbeta in README. tnx MWE. 19960129 change: added a note to INSTALL.mbox making clear that Mailbox is in mbox format. tnx MWE. 19960129 change: qlist now warns you if it didn't see any cmds. tnx RN. 19960129 change: incorporated qlist patch from RN to refuse double subs. 19960129 change: added qlist.1, contributed by RN. mangled it a bit. 19960129 bug: comment was not allowed in ``phrase (comment) ''; pointed out by RN. impact: some correct address lists could be mis-parsed by qmail-inject or qlist. fix: token.c now allows TOKEN_COMMENT in the appropriate scan. 19960128 change: added a logo paragraph to THOUGHTS. 19960127 change: implemented rcpthosts. 19960127 change: split up some uses of putflush in qmail-remote, qmail-smtpd, spawn.c. eliminated NODELAY and corresponding paragraph in THOUGHTS. 19960127 change: added quote2(). used it in qmail-alias, qmail-send, qreceipt. now addresses are properly quoted in the From, To, and internal Return-Path of bounces; the From and To of receipts; and the Return-Path/RPLINE of delivered messages. removed relevant paragraph from THOUGHTS. 19960127 change: in RFCLOOPS, documented fact that Delivered-To address is conventionally not quoted. 19960127 change: knocked default SMTP timeouts down to 20 minutes. 19960127 change: added INSTALL.ids. tnx RN. 19960127 change: in INSTALL, noted that nogroup should already exist. 19960127 bug: pass_selprep checked pqchan[c] even if pass[c].id. impact: qmail-send wasted CPU time whenever more than one message was waiting on a blocked channel. fix: pass_selprep now checks !pass[c].id. 19960127 bug: programs invoked from qmail-alias were immune to SIGPIPE. impact: a delivery pipeline such as |yes|head -1000 would loop forever, since yes does not check for write errors. fix: added signal_uninit(). used it before execvp in qmail-alias. [sigh] 19960127 cleanup: added date822fmt.c. used it in newfield.c, qmail-queue. 19960127 cleanup: added fmt_uint0.c. used it in myctime.c, newfield.c, qmail-queue. 19960127 cleanup: added dnsdoe.c. used it in dnscname, dnsfq, dnsip, dnsmxip, dnsptr. 19960127 cleanup: eliminated temp from dnsfq.c. 19960127 bug: gen_allocdefs was making assumptions incompatible with the alloc_re interface. impact: qmail-send would dump core if you ran out of memory. fix: changed alloc_re interface. 19960126 portability problem: some versions of Linux don't have net/route.h. pointed out by RN. impact: couldn't compile under those versions. fix: ipme.c no longer includes net/route.h; hopefully this won't cause new portability problems. 19960126 change: added chmod instructions to INSTALL and INSTALL.alias. tnx RN. 19960126 change: INSTALL now refers to the traditional sendmail spot (/usr/lib), not the BSD 4.4 spot (/usr/sbin). tnx RN. 19960126 change: make auto-uids.h now creates auto-uids.h.tmp first. thus, if someone disobeys the installation instructions, and his make fails to remove targets upon error, he'll still be okay. tnx RN. 19960126 change: added forgeries.7. 19960125 cleanup: eliminated flagverbose, flagmetoo in sendmail. 19960125 cleanup: added substdio_copy.c. used it at several spots. 19960125 cleanup: added constmap.c. qmail-send now uses constmap for locals and virtualdomains. this will speed things up: no problem now to have thousands of virtual domains. removed relevant paragraph from THOUGHTS. 19960125 change: added linux section in find-systype. this will affect linux-* systypes. tnx RN for relevant info. 19960124 change: added -od, -oe, -p, -f to sendmail. the need for these was pointed out by TN. 19960124 bug: qmail-smtpd was reading from descriptor 1. impact: none; in normal use, both 0 and 1 point to the network. fix: changed 1 to 0. 19960124 bug: qmail-alias treated any .qmail open failure as permanent. impact: if a .qmail file was temporarily unopenable (e.g., because of NFS), it was incorrectly ignored. fix: qmail-alias now dies QLX_SOFT on any open failure other than ENOENT. 19960124 change: added freebsd section in find-systype, same as bsd.os section. this will affect freebsd-* systypes. 19960124 cleanup: find-systype now immediately converts sys to lowercase. 19960124 change: qmail-setup now copies man pages into /var/qmail/man; qmail-check checks /var/qmail/man. using .0 style, which might cause trouble on various machines, but better than not trying. 19960124 change: in qmail-remote.c, changed perm_control to temp_control (and D to Z, thanks); thus failure to read control files (e.g., because of permissions) is now a temporary error. 19960124 bug: in qmail-remote.c, temp_chdir() used D, not Z. impact: if chdir() to CONF_HOME failed (e.g., because of NFS), message would be bounced. fix: changed D to Z. 19960124 change: reorganized README. 19960124 portability problem: Linux has the fifo kernel bug that I had hoped I'd never run into. impact: messages under Linux (and any other systems with this bug) were picked up only in sweeps, not instantly. fix: triggerpull.c now writes a byte (non-blocking) to the fifo. updated INTERNALS accordingly. 19960124 bug: in qmail-remote.c, if quit() saw a remote write error, it would call writeerr() even though a message report had already been produced. impact: the mess report would include an extra ``ZConnected but communications failed,'' which was confusing to humans. fix: quit() now simply skips the wait-for-QUIT smtpcode() upon write error. 19960124 portability problem: Linux does not have SIGSYS or SIGEMT. impact: couldn't compile under Linux. fix: added appropriate ifdefs in signal.c. 19960124 qmail 0.70, beta. netqmail-1.06/tcpto.h0000644000076400007640000000016106541176434014152 0ustar nelsonnelson#ifndef TCPTO_H #define TCPTO_H extern int tcpto(); extern void tcpto_err(); extern void tcpto_clean(); #endif netqmail-1.06/THANKS0000644000076400007640000001557210724074204013565 0ustar nelsonnelsonThanks to lots of people for success and failure reports, code, ideas, and documentation. See CHANGES for details of specific contributions. Sorry if I left anyone out. A2B = Are Bryne A2L = Ali Lomonaco A2P = Andrea Paolini AAF = Adam A. Frey AB = Alan Briggs ABC = Alan B. Clegg AC = Arne Coucheron ACB = Andy C. Brandt ADM = Adam D. Morley AF = Andreas Faerber AG = Armin Gruner AGB = Andre Grosse Bley AH = Amos Hayes AI = Akihiro Iijima AJ = Alan Jaffray AJK = Antti-Juhani Kaijanaho AKB = Allen K. Briggs AL = Andreas Lamprecht ALB = Allan L. Bazinet ANR = Adriano Nagelschmidt Rodrigues AP = Andrew Pam AS = Akos Szalkai AV = Alex Vostrikov AWB = Andy W. Barclay AY = Araki Yasuhiro B1F = Bo Fussing B2F = Brad Forschinger B2H = Buck Huppmann B2L = Brent Laminack B2W = Bil Wendling B3W = Boris Wedl BB = Bruce Bodger BC = Bob Collie BCK = Benjamin C. Kite BCM = Bill C. Miller BDB = Boris D. Beletsky BDM = Byron D. Miller BEO = Bruce E. O'Neel BET = Bennett E. Todd BG = Bert Gijsbers BH = Brad Howes BJ = Brian Jackson BJM = Barry J. Miller BL = Brian Litzinger BMF = Brian M. Fisk BN = Bill Nugent BP = Bruce Perens BR = Brian J. Reichert BS = Bjoern Stabell BT = Brad Templeton BTW = Brian T. Wightman BW = Bill Weinman BZ = Blaz Zupan C2F = Chuck Foster C2H = Christoph Heidermanns C2S = Craig Shrimpton CEJ = Colin Eric Johnson CF = C. Ferree CG = Chris Garrigues CH = Chael Hall CHR = Craig H. Rowland CK = Christoph Kaesling CL = Carsten Leonhardt CLS = Christopher L. Seawood CM = Charles Mattair CMP = Chase M. Phillips CR = Christian Riede CS = Cloyce Spradling CSH = Clayton S. Haapala D1H = Dieter Heidner D2H = Dan Hollis D2K = Dax Kelson D2S = Dan Senie D3S = Don Samek DA = Dave Arcuri DAR = Daniel A. Reish DB = David Buscher DBK = Douglas B. Kerry DC = Dan Cross DCC = Daniel C. Cotey DE = Daniel Egnor DEH = Daniel E. Harris DF = Dale Farnsworth DG = David Guntner DK = Dave Kopper DL = Daniel Lawrence DM = David Mazieres DML = David M. Lew DP = Dave Platt DS = Dave Sill DST = Daniel S. Thibadeau DWS = David Wayne Summers EC = Evan Champion ECG = Eric C. Garrison EG = Eivind Gjelseth EK = Eric Krohn EP = Emanuele Pucciarelli ERH = Eric R. Hankins ES = Eric Smith ESM = Edward S. Marshall ET = Eivind Tagseth ETT = Emmanuel T. Tardieu F2T = Frank Thieme FE = Frank Ederveen FN = Faried Nawaz FPL = Frederik P. Lindberg FT = Frank Tegtmeyer FW = Frank Wagner G1A = Graham Adams G2A = Greg Andrews GAW = Greg A. Woods GB = Glenn Barry GH = Gene Hightower GL = Giles Lean GLM = Grant L. Miller H2S = Harley Silver HCJ = Helio Coelho Jr. HDG = Hans de Graaff HG = Howard Goldstein HHO = Harald Hanche-Olsen HJB = Herbert J. Bernstein HM = Hirokazu Morikawa HS = Harlan Stenn HT = Henry Timmerman HW = Hal Wine HWM = Henry W. Miller IH = Ingmar Hupp IK = Ivan Kohler IKW = Ian Keith Wynne IS = Icarus Sparry IW = Ian Westcott J1B = John Banghart J1K = Jost Krieger J2B = Jos Backus J2K = Johannes Kroeger J2M = Joel Maslak J2P = John Parker J2W = Jim Whitby JAB = Jeremy A. Bussard JAK = Johan A. Kullstam JB = Joshua Buysse JBB = Jason B. Brown JBF = John B. Fleming JC = Jim Clausing JCD = Jeffrey C. Dege JD = Joe Doupnik JDHB = Johannes D. H. Beekhuizen JDJ = Joshua D. Juran JF = Janos Farkas JFK = James F. Kane III JGM = John G. Myers JJB = J. J. Bailey JJMK = Jonathan J. M. Katz JJR = Jaron J. Rubenstein JK = Jari Kirma JL = Jim Littlefield JLB = Julie L. Baumler JLH = Jason L. Haar JLW = Jason L. Wright JM = Jim Meehan JMS = Jason M. Stokes JMT = John M. Twilley JP = John Palkovic JPB = Joe Block JPH = Justin P. Hannah JPR = Jean-Pierre Radley JRL = John R. Levine JRM = Jason R. Mastaler JRY = Jamie R. Yukes JS = Jesper Skriver JTB = Jonathan T. Bowie JW = John Whittaker JWB = James W. Birdsall K1J = Kyle Jones K2J = Kevin Johnson KA = Klaus Aigte KB = Keith Burdis KE = Kenny Elliott KJJ = Kevin J. Johnson KJS = Kevin J. Sawyer KMD = Kevin M. Dulzo KO = Keith Owens KR = Kenji Rikitake KT = Karsten Thygesen KUT = Kai Uwe Tempel KY = Kentaro Yoshitomi L2L = Louis Larry L3L = Luis Lopes LB = Laurentiu Badea LL = lilo LW = Lionel Widdifield M2C = Mark Crimmins M2G = Michael R. Gile M2H = Martin Hager M2L = M. Lyons M2R = Mark Riekenberg M2S = Mikael Suokas M3H = Michael Holzt M3L = Michael Lazarou M3S = Morten Skjelland M4S = Michael Shields MB = Martin Budsj? MBS = Michael B. Scher MC = Michael Cooley MD = Mark Delany MDI = Miguel de Icaza ME = Marc Ewing MEE = Mads E. Eilertsen MF = Massimo Fusaro MG = Michael Graff MGM = Mitchell G. Morris MH = Markus Hofmann MJD = Mark-Jason Dominus MJG = Manuel J. Galan ML = Martin Lucina MLH = May Liss Haarstad MM = Martin Mersberger MMM = Momchil M. Momchev MMM2 = Marc M. Martinez MP = Matt Paduano MR = Mosfeq Rashid MRG = Matthew R. Green MS = Mark Spears MSD = Mandell S. Degerness MSS = Matthew S. Soffen MT = Mark Thompson MW = Mate Wierdl MWE = Mark W. Eichin NA = Norm Aleks NAA = Nicholas A. Amato NH = Nick Holloway NND = N. Dudorov NR = Norbert Roeding NW = Nicholas Waples OK = Oezguer Kesim OR = Ollivier Robert OS = Oliver Seiler PB = Peter Bowyer PCO = Peter C. Olsen PGF = Paul Fox PGR = Phil G. Rorex PH = Paul Harrington PJG = Paul Graham PJH = Peter J. Hunter PK = Petri Kaukasoina PMH = Peter M. Haworth PO = Paul Overell PS = Paul Svensson PT = Paul Taylor PTW = P. T. Withington PW = Peter Wilkinson R2N = Rivo Nurges RA = Russ Allbery RAB = Randolph Allen Bentson RAM = Robin A. McCollum RB = Robert Bridgham RC = Ryan Crum RD = Rahul Dhesi RDM = Raul D. Miller REB = Ronald E. Bickers RF = Rainer Fraedrich RFH = Robert F. Harrison RGS = Richard G. Sharman RJC = Robert J. Carter RJH = Randy Harmon RJO = Richard J. Ohnemus RK = Riho Kurg RL = Robert Luce RM = Rich McClellan RN = Russell Nelson RO = Roberto Oppedisano RPS = Russell P. Sutherland RS = Robert Sanders RSK = Robert S. Krzaczek S1R = Satish Ramachandran S2P = Stefan Puscasu S2R = Sean Reifschneider S2S = Scott Schwartz S2T = Steve Taylor S3T = Steffen Thorsen SA = Satoshi Adachi SAE = Stefaan A. Eeckels SAS = Steven A. Schrader SB = Stephane Bortzmeyer SC = Stefan Cars SCW = Steven C. Work SG = Steven Grimm SGC = Stephen G. Comings SJ = Sudish Joseph SJB = SJ Burns SJW = Stephen J. White SLB = Steven L. Baur SM = Shawn McHorse SP = Stephen Parker SPM = Salvatore P. Miccicke SS = Simon Shapiro SSB = Stik Bakken ST = Steve Tylock SV = Sven Velt SVD = Stef Van Dessel T2K = Tomoya Konishi T2M = Toni Mueller T2U = Todd Underwood TA = Tetsuo Aoki TB = Tobias Brox TD = Tom Demmer TEE = Thomas E. Erskine TG = Tim Goodwin TH = Ton Hospel TJH = Timothy J. Hunt TK = Terry Kennedy TL = Timothy Lorenc TLF = Timo L. Felbinger TLM = Timothy L. Mayo TM = Toshinori Maeno TN = Thomas Neumann TRR = Tracy R. Reed TT = Takaki Taniguchi TU = Tetsu Ushijima TV = Tommi Virtanen TVP = Tom van Peer UO = Uwe Ohse VBM = Vladimir B. Machulsky VR = Vincenzo Romano VU = Viriya Upatising VV = Vince Vielhaber W2K = Wolfram Kahl WEB = William E. Baxter WK = Werner Koch WS = Wilbur Sims WW = Wei Wu YC = Yuji Chikahiro YF = Yaroslav Faybishenko ZU = Zin Uda netqmail-1.06/tryshsgr.c0000644000076400007640000000041606541176434014704 0ustar nelsonnelsonvoid main() { short x[4]; x[0] = x[1] = 1; if (getgroups(1,x) == 0) if (setgroups(1,x) == -1) _exit(1); if (getgroups(1,x) == -1) _exit(1); if (x[1] != 1) _exit(1); x[1] = 2; if (getgroups(1,x) == -1) _exit(1); if (x[1] != 2) _exit(1); _exit(0); } netqmail-1.06/sig_child.c0000644000076400007640000000037406541176434014747 0ustar nelsonnelson#include #include "sig.h" void sig_childblock() { sig_block(SIGCHLD); } void sig_childunblock() { sig_unblock(SIGCHLD); } void sig_childcatch(f) void (*f)(); { sig_catch(SIGCHLD,f); } void sig_childdefault() { sig_catch(SIGCHLD,SIG_DFL); } netqmail-1.06/triggerpull.c0000644000076400007640000000034606541176434015361 0ustar nelsonnelson#include "ndelay.h" #include "open.h" #include "triggerpull.h" void triggerpull() { int fd; fd = open_write("lock/trigger"); if (fd >= 0) { ndelay_on(fd); write(fd,"",1); /* if it fails, bummer */ close(fd); } } netqmail-1.06/remoteinfo.h0000644000076400007640000000012206541176434015165 0ustar nelsonnelson#ifndef REMOTEINFO_H #define REMOTEINFO_H extern char *remoteinfo_get(); #endif netqmail-1.06/addresses.50000644000076400007640000001372506541176434014725 0ustar nelsonnelson.TH addresses 5 .SH "NAME" addresses \- formats for Internet mail addresses .SH "INTRODUCTION" A .B mail address is a string of characters containing @. Every mail address has a .B local part and a .B domain part\fR. The domain part is everything after the final @. The local part is everything before. For example, the mail addresses .EX God@heaven.af.mil @heaven.af.mil @at@@heaven.af.mil .EE all have domain part .BR heaven.af.mil . The local parts are .BR God , empty, and .BR @at@ . Some domains have owners. It is up to the owner of .B heaven.af.mil to say how mail messages will be delivered to addresses with domain part .BR heaven.af.mil . The domain part of an address is interpreted without regard to case, so .EX God@heaven.af.mil .br God@HEAVEN.AF.MIL .br God@Heaven.AF.Mil .EE all refer to the same domain. There is one exceptional address that does not contain an @: namely, the empty string. The empty string cannot be used as a recipient address. It can be used as a sender address so that the real sender doesn't receive bounces. .SH "QMAIL EXTENSIONS" The .B qmail system allows several further types of addresses in mail envelopes. First, an envelope recipient address without an @ is interpreted as being at .IR envnoathost . For example, if .I envnoathost is .BR heaven.af.mil , the address .B God will be rewritten as .BR God@heaven.af.mil . Second, the address .B #@[] is used as an envelope sender address for double bounces. Third, envelope sender addresses of the form .I pre\fB@\fIhost\fB-@[] are used to support variable envelope return paths (VERPs). .B qmail-send will rewrite .I pre\fB@\fIhost\fB-@[] as .I prerecip\fB=\fIdomain\fB@\fIhost for deliveries to .IR recip\fB@\fIdomain . Bounces directly from .B qmail-send will come back to .IR pre\fB@\fIhost . .SH "CHOOSING MAIL ADDRESSES" Here are some suggestions on choosing mail addresses for the Internet. Do not use non-ASCII characters. Under RFC 822 and RFC 821, these characters cannot be used in mail headers or in SMTP commands. In practice, they are regularly corrupted. Do not use ASCII control characters. NUL is regularly corrupted. CR and LF cannot be used in some combinations and are corrupted in all. None of these characters are usable on business cards. Avoid spaces and the characters .EX \\"<>()[],;: .EE These all require quoting in mail headers and in SMTP. Many existing mail programs do not handle quoting properly. Do not use @ in a local part. @ requires quoting in mail headers and in SMTP. Many programs incorrectly look for the first @, rather than the last @, to find the domain part of an address. In a local part, do not use two consecutive dots, a dot at the beginning, or a dot at the end. Any of these would require quoting in mail headers. Do not use an empty local part; it cannot appear in SMTP commands. Avoid local parts longer than 64 characters. Be wary of uppercase letters in local parts. Some mail programs (and users!) will incorrectly convert .B God@heaven.af.mil to .BR god@heaven.af.mil . Be wary of the following characters: .EX $&!#~`'^*|{} .EE Some users will not know how to feed these characters safely to their mail programs. In domain names, stick to letters, digits, dash, and dot. One popular DNS resolver has, under the banner of security, recently begun destroying domain names that contain certain other characters, including underscore. Exception: A dotted-decimal IP address in brackets, such as .BR [127.0.0.1] , identifies a domain owned by whoever owns the host at that IP address, and can be used safely. In a domain name, do not use two consecutive dots, a dot at the beginning, or a dot at the end. This means that, when a domain name is broken down into components separated by dots, there are no empty components. Always use at least one dot in a domain name. If you own the .B mil domain, don't bother using the address .BR root@mil ; most users will be unable to send messages to that address. Same for the root domain. Avoid domain names longer than 64 characters. .SH "ENCODED ADDRESSES IN SMTP COMMANDS" RFC 821 defines an encoding of mail addresses in SMTP. For example, the addresses .EX God@heaven.af.mil .br a"quote@heaven.af.mil .br The Almighty.One@heaven.af.mil .EE could be encoded in RCPT commands as .EX RCPT TO: .br RCPT TO: .br RCPT TO: .EE There are several restrictions in RFC 821 on the mail addresses that can be used over SMTP. Non-ASCII characters are prohibited. The local part must not be empty. The domain part must be a sequence of elements separated by dots, where each element is either a component, a sequence of digits preceded by #, or a dotted-decimal IP address surrounded by brackets. The only allowable characters in components are letters, digits, and dashes. Every component must (believe it or not) have at least three characters; the first character must be a letter; the last character must not be a hyphen. .SH "ENCODED ADDRESSES IN MAIL HEADERS" RFC 822 defines an encoding of mail addresses in certain header fields in a mail message. For example, the addresses .EX God@heaven.af.mil .br a"quote@heaven.af.mil .br The Almighty.One@heaven.af.mil .EE could be encoded in a .B To field as .EX To: God@heaven.af.mil, .br <@brl.mil:"a\\"quote"@heaven.af.mil>, .br "The Almighty".One@heaven.af.mil .EE or perhaps .EX To: < "God"@heaven .af.mil>, .br "a\\"quote" (Who?) @ heaven . af. mil .br , God<"The Almighty.One"@heaven.af.mil> .EE There are several restrictions on the mail addresses that can be used in these header fields. Non-ASCII characters are prohibited. The domain part must be a sequence of elements separated by dots, where each element either (1) begins with [ and ends with ] or (2) is a nonempty string of printable ASCII characters not including any of .EX \\".<>()[],;: .EE and not including space. .SH "SEE ALSO" envelopes(5), qmail-header(5), qmail-inject(8), qmail-remote(8), qmail-smtpd(8) netqmail-1.06/binm1+df.sh0000644000076400007640000000065206541176434014604 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using dot-forward to support sendmail-style ~/.forward files. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using BSD 4.4 binmail interface: /usr/libexec/mail.local -r exec env - PATH="QMAIL/bin:$PATH" \ qmail-start '|dot-forward .forward |preline -f /usr/libexec/mail.local -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/scan_ulong.c0000644000076400007640000000053006541176434015144 0ustar nelsonnelson#include "scan.h" unsigned int scan_ulong(s,u) register char *s; register unsigned long *u; { register unsigned int pos; register unsigned long result; register unsigned long c; pos = 0; result = 0; while ((c = (unsigned long) (unsigned char) (s[pos] - '0')) < 10) { result = result * 10 + c; ++pos; } *u = result; return pos; } netqmail-1.06/ndelay.h0000644000076400007640000000013406541176434014275 0ustar nelsonnelson#ifndef NDELAY_H #define NDELAY_H extern int ndelay_on(); extern int ndelay_off(); #endif netqmail-1.06/fmt_strn.c0000644000076400007640000000041606541176434014653 0ustar nelsonnelson#include "fmt.h" unsigned int fmt_strn(s,t,n) register char *s; register char *t; register unsigned int n; { register unsigned int len; char ch; len = 0; if (s) { while (n-- && (ch = t[len])) s[len++] = ch; } else while (n-- && t[len]) len++; return len; } netqmail-1.06/qmail-newu.90000644000076400007640000000137006541176434015024 0ustar nelsonnelson.TH qmail-newu 8 .SH NAME qmail-newu \- prepare address assignments for qmail-lspawn .SH SYNOPSIS .B qmail-newu .SH DESCRIPTION .B qmail-newu reads the assignments in .B QMAILHOME/users/assign and writes them into .B QMAILHOME/users/cdb in a binary format suited for quick access by .BR qmail-lspawn . If there is a problem with .BR users/assign , .B qmail-newu complains and leaves .B users/cdb alone. .B qmail-newu ensures that .B users/cdb is updated atomically, so .B qmail-lspawn never has to wait for .B qmail-newu to finish. However, .B qmail-newu makes no attempt to protect against two simultaneous updates of .BR users/cdb . The binary .B users/cdb format is portable across machines. .SH "SEE ALSO" qmail-users(5), qmail-lspawn(8), qmail-pw2u(8) netqmail-1.06/timeoutwrite.h0000644000076400007640000000012206541176434015557 0ustar nelsonnelson#ifndef TIMEOUTWRITE_H #define TIMEOUTWRITE_H extern int timeoutwrite(); #endif netqmail-1.06/elq.sh0000644000076400007640000000005506541176434013767 0ustar nelsonnelsonQMAIL/bin/maildir2mbox && exec elm ${1+"$@"} netqmail-1.06/error_str.30000644000076400007640000000044706541176434014764 0ustar nelsonnelson.TH error_str 3 .SH NAME error_str \- names for syscall error codes .SH SYNTAX .B #include char *\fBerror_str\fP(\fIe\fR); int \fIe\fR; .SH DESCRIPTION .B error_str returns a printable string describing syscall error code .IR e . Normally .I e is .BR errno . .SH "SEE ALSO" error(3) netqmail-1.06/str_cpy.c0000644000076400007640000000051206541176434014477 0ustar nelsonnelson#include "str.h" unsigned int str_copy(s,t) register char *s; register char *t; { register int len; len = 0; for (;;) { if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; if (!(*s = *t)) return len; ++s; ++t; ++len; } } netqmail-1.06/subgetopt.c0000644000076400007640000000315106541176434015032 0ustar nelsonnelson/* subgetopt.c, subgetopt.h: (yet another) improved getopt clone, inner layer D. J. Bernstein, djb@pobox.com. No dependencies. No system requirements. 19970228: Cleanups. 931129: Adapted from getopt.c. No known patent problems. Documentation in subgetopt.3. */ #define SUBGETOPTNOSHORT #include "subgetopt.h" #define sgopt subgetopt #define optind subgetoptind #define optpos subgetoptpos #define optarg subgetoptarg #define optproblem subgetoptproblem #define optdone subgetoptdone int optind = 1; int optpos = 0; char *optarg = 0; int optproblem = 0; int optdone = SUBGETOPTDONE; int sgopt(argc,argv,opts) int argc; char **argv; char *opts; { int c; char *s; optarg = 0; if (!argv || (optind >= argc) || !argv[optind]) return optdone; if (optpos && !argv[optind][optpos]) { ++optind; optpos = 0; if ((optind >= argc) || !argv[optind]) return optdone; } if (!optpos) { if (argv[optind][0] != '-') return optdone; ++optpos; c = argv[optind][1]; if ((c == '-') || (c == 0)) { if (c) ++optind; optpos = 0; return optdone; } /* otherwise c is reassigned below */ } c = argv[optind][optpos]; ++optpos; s = opts; while (*s) { if (c == *s) { if (s[1] == ':') { optarg = argv[optind] + optpos; ++optind; optpos = 0; if (!*optarg) { optarg = argv[optind]; if ((optind >= argc) || !optarg) { /* argument past end */ optproblem = c; return '?'; } ++optind; } } return c; } ++s; if (*s == ':') ++s; } optproblem = c; return '?'; } netqmail-1.06/trynpbg1.c0000644000076400007640000000073606541176434014572 0ustar nelsonnelson#include "select.h" #include "open.h" #include "fifo.h" #define FN "temp-trynpbg1.fifo" void main() { int flagbug; struct timeval instant; fd_set rfds; flagbug = 0; if (fifo_make(FN,0600) != -1) { close(0); if (open_read(FN) == 0) { FD_ZERO(&rfds); FD_SET(0,&rfds); instant.tv_sec = instant.tv_usec = 0; if (select(1,&rfds,(fd_set *) 0,(fd_set *) 0,&instant) > 0) flagbug = 1; } unlink(FN); } _exit(!flagbug); } netqmail-1.06/qreceipt.c0000644000076400007640000000654306541176434014642 0ustar nelsonnelson#include "sig.h" #include "env.h" #include "substdio.h" #include "stralloc.h" #include "subfd.h" #include "getln.h" #include "alloc.h" #include "str.h" #include "hfield.h" #include "token822.h" #include "error.h" #include "gen_alloc.h" #include "gen_allocdefs.h" #include "headerbody.h" #include "exit.h" #include "open.h" #include "quote.h" #include "qmail.h" void die_noreceipt() { _exit(0); } void die() { _exit(100); } void die_temp() { _exit(111); } void die_nomem() { substdio_putsflush(subfderr,"qreceipt: fatal: out of memory\n"); die_temp(); } void die_fork() { substdio_putsflush(subfderr,"qreceipt: fatal: unable to fork\n"); die_temp(); } void die_qqperm() { substdio_putsflush(subfderr,"qreceipt: fatal: permanent qmail-queue error\n"); die(); } void die_qqtemp() { substdio_putsflush(subfderr,"qreceipt: fatal: temporary qmail-queue error\n"); die_temp(); } void die_usage() { substdio_putsflush(subfderr, "qreceipt: usage: qreceipt deliveryaddress\n"); die(); } void die_read() { if (errno == error_nomem) die_nomem(); substdio_putsflush(subfderr,"qreceipt: fatal: read error\n"); die_temp(); } void doordie(sa,r) stralloc *sa; int r; { if (r == 1) return; if (r == -1) die_nomem(); substdio_putsflush(subfderr,"qreceipt: fatal: unable to parse this: "); substdio_putflush(subfderr,sa->s,sa->len); die(); } char *target; int flagreceipt = 0; char *returnpath; stralloc messageid = {0}; stralloc sanotice = {0}; int rwnotice(addr) token822_alloc *addr; { token822_reverse(addr); if (token822_unquote(&sanotice,addr) != 1) die_nomem(); if (sanotice.len == str_len(target)) if (!str_diffn(sanotice.s,target,sanotice.len)) flagreceipt = 1; token822_reverse(addr); return 1; } struct qmail qqt; stralloc quoted = {0}; void finishheader() { char *qqx; if (!flagreceipt) die_noreceipt(); if (str_equal(returnpath,"")) die_noreceipt(); if (str_equal(returnpath,"#@[]")) die_noreceipt(); if (!quote2("ed,returnpath)) die_nomem(); if (qmail_open(&qqt) == -1) die_fork(); qmail_puts(&qqt,"From: DELIVERY NOTICE SYSTEM <"); qmail_put(&qqt,quoted.s,quoted.len); qmail_puts(&qqt,">\n"); qmail_puts(&qqt,"To: <"); qmail_put(&qqt,quoted.s,quoted.len); qmail_puts(&qqt,">\n"); qmail_puts(&qqt,"Subject: success notice\n\ \n\ Hi! This is the qreceipt program. Your message was delivered to the\n\ following address: "); qmail_puts(&qqt,target); qmail_puts(&qqt,". Thanks for asking.\n"); if (messageid.s) { qmail_puts(&qqt,"Your "); qmail_put(&qqt,messageid.s,messageid.len); } qmail_from(&qqt,""); qmail_to(&qqt,returnpath); qqx = qmail_close(&qqt); if (*qqx) if (*qqx == 'D') die_qqperm(); else die_qqtemp(); } stralloc hfbuf = {0}; token822_alloc hfin = {0}; token822_alloc hfrewrite = {0}; token822_alloc hfaddr = {0}; void doheaderfield(h) stralloc *h; { switch(hfield_known(h->s,h->len)) { case H_MESSAGEID: if (!stralloc_copy(&messageid,h)) die_nomem(); break; case H_NOTICEREQUESTEDUPONDELIVERYTO: doordie(h,token822_parse(&hfin,h,&hfbuf)); doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rwnotice)); break; } } void dobody(h) stralloc *h; { ; } void main(argc,argv) int argc; char **argv; { sig_pipeignore(); if (!(target = argv[1])) die_usage(); if (!(returnpath = env_get("SENDER"))) die_usage(); if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read(); die_noreceipt(); } netqmail-1.06/TEST.deliver0000644000076400007640000000731306541176434015011 0ustar nelsonnelsonYou can do several tests of qmail delivery without setting up qmail to accept messages through SMTP or through /usr/lib/sendmail: 1. After you start qmail, look for a qmail: status: local 0/10 remote 0/20 line in syslog. qmail-send always prints either ``cannot start'' or ``status''. (The big number is a splogger timestamp.) 2. Do a ps and look for the qmail daemons. There should be four of them, all idle: qmail-send, running as qmails; qmail-lspawn, running as root; qmail-rspawn, running as qmailr; and qmail-clean, running as qmailq. You will also see splogger, running as qmaill. 3. Local-local test: Send yourself an empty message. (Replace ``me'' with your username. Make sure to include the ``to:'' colon.) % echo to: me | /var/qmail/bin/qmail-inject The message will show up immediately in your mailbox, and syslog will show something like this: qmail: new msg 53 qmail: info msg 53: bytes 246 from qp 20345 uid 666 qmail: starting delivery 1: msg 53 to local me@domain qmail: status: local 1/10 remote 0/20 qmail: delivery 1: success: did_1+0+0/ qmail: status: local 0/10 remote 0/20 qmail: end msg 53 (53 is an inode number; 20345 is a process ID; your numbers will probably be different.) 4. Local-error test: Send a message to a nonexistent local address. % echo to: nonexistent | /var/qmail/bin/qmail-inject qmail: new msg 53 qmail: info msg 53: bytes 246 from qp 20351 uid 666 qmail: starting delivery 2: msg 53 to local nonexistent@domain qmail: status: local 1/10 remote 0/20 qmail: delivery 2: failure: No_such_address.__#5.1.1_/ qmail: status: local 0/10 remote 0/20 qmail: bounce msg 53 qp 20357 qmail: end msg 53 qmail: new msg 54 qmail: info msg 54: bytes 743 from <> qp 20357 uid 666 qmail: starting delivery 3: msg 54 to local me@domain qmail: status: local 1/10 remote 0/20 qmail: delivery 3: success: did_1+0+0/ qmail: status: local 0/10 remote 0/20 qmail: end msg 54 You will now have a bounce message in your mailbox. 5. Local-remote test: Send an empty message to your account on another machine. % echo to: me@wherever | /var/qmail/bin/qmail-inject qmail: new msg 53 qmail: info msg 53: bytes 246 from qp 20372 uid 666 qmail: starting delivery 4: msg 53 to remote me@wherever qmail: status: local 0/10 remote 1/20 qmail: delivery 4: success: 1.2.3.4_accepted_message./... qmail: status: local 0/10 remote 0/20 qmail: end msg 53 There will be a pause between ``starting delivery'' and ``success''; SMTP is slow. Check that the message is in your mailbox on the other machine. 6. Local-postmaster test: Send mail to postmaster, any capitalization. % echo to: POSTmaster | /var/qmail/bin/qmail-inject Look for the message in the alias mailbox, normally ~alias/Mailbox. 7. Double-bounce test: Send a message with a completely bad envelope. % /var/qmail/bin/qmail-inject -f nonexistent To: unknownuser Subject: testing This is a test. This is only a test. % (Use end-of-file, not dot, to end the message.) Look for the double bounce in the alias mailbox. 8. Group membership test: % cat > ~me/.qmail-groups |groups >> MYGROUPS; exit 0 % /var/qmail/bin/qmail-inject me-groups < /dev/null % cat ~me/MYGROUPS MYGROUPS will show your normal gid and nothing else. (Under Solaris, make sure to use /usr/ucb/groups; /usr/bin/groups is broken.) netqmail-1.06/conf-cc0000644000076400007640000000005706541176434014107 0ustar nelsonnelsoncc -O2 This will be used to compile .c files. netqmail-1.06/qmail-inject.c0000644000076400007640000004507206541176434015403 0ustar nelsonnelson#include "sig.h" #include "substdio.h" #include "stralloc.h" #include "subfd.h" #include "sgetopt.h" #include "getln.h" #include "alloc.h" #include "str.h" #include "fmt.h" #include "hfield.h" #include "token822.h" #include "control.h" #include "env.h" #include "gen_alloc.h" #include "gen_allocdefs.h" #include "error.h" #include "qmail.h" #include "now.h" #include "exit.h" #include "quote.h" #include "headerbody.h" #include "auto_qmail.h" #include "newfield.h" #include "constmap.h" #define LINELEN 80 datetime_sec starttime; char *qmopts; int flagdeletesender = 0; int flagdeletefrom = 0; int flagdeletemessid = 0; int flagnamecomment = 0; int flaghackmess = 0; int flaghackrecip = 0; char *mailhost; char *mailuser; int mailusertokentype; char *mailrhost; char *mailruser; stralloc control_idhost = {0}; stralloc control_defaultdomain = {0}; stralloc control_defaulthost = {0}; stralloc control_plusdomain = {0}; stralloc sender = {0}; stralloc envsbuf = {0}; token822_alloc envs = {0}; int flagrh; int flagqueue; struct qmail qqt; void put(s,len) char *s; int len; { if (flagqueue) qmail_put(&qqt,s,len); else substdio_put(subfdout,s,len); } void puts(s) char *s; { put(s,str_len(s)); } void perm() { _exit(100); } void temp() { _exit(111); } void die_nomem() { substdio_putsflush(subfderr,"qmail-inject: fatal: out of memory\n"); temp(); } void die_invalid(sa) stralloc *sa; { substdio_putsflush(subfderr,"qmail-inject: fatal: invalid header field: "); substdio_putflush(subfderr,sa->s,sa->len); perm(); } void die_qqt() { substdio_putsflush(subfderr,"qmail-inject: fatal: unable to run qmail-queue\n"); temp(); } void die_chdir() { substdio_putsflush(subfderr,"qmail-inject: fatal: internal bug\n"); temp(); } void die_read() { if (errno == error_nomem) die_nomem(); substdio_putsflush(subfderr,"qmail-inject: fatal: read error\n"); temp(); } void doordie(sa,r) stralloc *sa; int r; { if (r == 1) return; if (r == -1) die_nomem(); substdio_putsflush(subfderr,"qmail-inject: fatal: unable to parse this line:\n"); substdio_putflush(subfderr,sa->s,sa->len); perm(); } GEN_ALLOC_typedef(saa,stralloc,sa,len,a) GEN_ALLOC_readyplus(saa,stralloc,sa,len,a,i,n,x,10,saa_readyplus) static stralloc sauninit = {0}; saa savedh = {0}; saa hrlist = {0}; saa tocclist = {0}; saa hrrlist = {0}; saa reciplist = {0}; int flagresent; void exitnicely() { char *qqx; if (!flagqueue) substdio_flush(subfdout); if (flagqueue) { int i; if (!stralloc_0(&sender)) die_nomem(); qmail_from(&qqt,sender.s); for (i = 0;i < reciplist.len;++i) { if (!stralloc_0(&reciplist.sa[i])) die_nomem(); qmail_to(&qqt,reciplist.sa[i].s); } if (flagrh) if (flagresent) for (i = 0;i < hrrlist.len;++i) { if (!stralloc_0(&hrrlist.sa[i])) die_nomem(); qmail_to(&qqt,hrrlist.sa[i].s); } else for (i = 0;i < hrlist.len;++i) { if (!stralloc_0(&hrlist.sa[i])) die_nomem(); qmail_to(&qqt,hrlist.sa[i].s); } qqx = qmail_close(&qqt); if (*qqx) if (*qqx == 'D') { substdio_puts(subfderr,"qmail-inject: fatal: "); substdio_puts(subfderr,qqx + 1); substdio_puts(subfderr,"\n"); substdio_flush(subfderr); perm(); } else { substdio_puts(subfderr,"qmail-inject: fatal: "); substdio_puts(subfderr,qqx + 1); substdio_puts(subfderr,"\n"); substdio_flush(subfderr); temp(); } } _exit(0); } void savedh_append(h) stralloc *h; { if (!saa_readyplus(&savedh,1)) die_nomem(); savedh.sa[savedh.len] = sauninit; if (!stralloc_copy(savedh.sa + savedh.len,h)) die_nomem(); ++savedh.len; } void savedh_print() { int i; for (i = 0;i < savedh.len;++i) put(savedh.sa[i].s,savedh.sa[i].len); } stralloc defaultdomainbuf = {0}; token822_alloc defaultdomain = {0}; stralloc defaulthostbuf = {0}; token822_alloc defaulthost = {0}; stralloc plusdomainbuf = {0}; token822_alloc plusdomain = {0}; void rwroute(addr) token822_alloc *addr; { if (addr->t[addr->len - 1].type == TOKEN822_AT) while (addr->len) if (addr->t[--addr->len].type == TOKEN822_COLON) return; } void rwextraat(addr) token822_alloc *addr; { int i; if (addr->t[0].type == TOKEN822_AT) { --addr->len; for (i = 0;i < addr->len;++i) addr->t[i] = addr->t[i + 1]; } } void rwextradot(addr) token822_alloc *addr; { int i; if (addr->t[0].type == TOKEN822_DOT) { --addr->len; for (i = 0;i < addr->len;++i) addr->t[i] = addr->t[i + 1]; } } void rwnoat(addr) token822_alloc *addr; { int i; int shift; for (i = 0;i < addr->len;++i) if (addr->t[i].type == TOKEN822_AT) return; shift = defaulthost.len; if (!token822_readyplus(addr,shift)) die_nomem(); for (i = addr->len - 1;i >= 0;--i) addr->t[i + shift] = addr->t[i]; addr->len += shift; for (i = 0;i < shift;++i) addr->t[i] = defaulthost.t[shift - 1 - i]; } void rwnodot(addr) token822_alloc *addr; { int i; int shift; for (i = 0;i < addr->len;++i) { if (addr->t[i].type == TOKEN822_DOT) return; if (addr->t[i].type == TOKEN822_AT) break; } for (i = 0;i < addr->len;++i) { if (addr->t[i].type == TOKEN822_LITERAL) return; if (addr->t[i].type == TOKEN822_AT) break; } shift = defaultdomain.len; if (!token822_readyplus(addr,shift)) die_nomem(); for (i = addr->len - 1;i >= 0;--i) addr->t[i + shift] = addr->t[i]; addr->len += shift; for (i = 0;i < shift;++i) addr->t[i] = defaultdomain.t[shift - 1 - i]; } void rwplus(addr) token822_alloc *addr; { int i; int shift; if (addr->t[0].type != TOKEN822_ATOM) return; if (!addr->t[0].slen) return; if (addr->t[0].s[addr->t[0].slen - 1] != '+') return; --addr->t[0].slen; /* remove + */ shift = plusdomain.len; if (!token822_readyplus(addr,shift)) die_nomem(); for (i = addr->len - 1;i >= 0;--i) addr->t[i + shift] = addr->t[i]; addr->len += shift; for (i = 0;i < shift;++i) addr->t[i] = plusdomain.t[shift - 1 - i]; } void rwgeneric(addr) token822_alloc *addr; { if (!addr->len) return; /* don't rewrite <> */ if (addr->len >= 2) if (addr->t[1].type == TOKEN822_AT) if (addr->t[0].type == TOKEN822_LITERAL) if (!addr->t[0].slen) /* don't rewrite */ return; rwroute(addr); if (!addr->len) return; /* <@foo:> -> <> */ rwextradot(addr); if (!addr->len) return; /* <.> -> <> */ rwextraat(addr); if (!addr->len) return; /* <@> -> <> */ rwnoat(addr); rwplus(addr); rwnodot(addr); } int setreturn(addr) token822_alloc *addr; { if (!sender.s) { token822_reverse(addr); if (token822_unquote(&sender,addr) != 1) die_nomem(); if (flaghackrecip) if (!stralloc_cats(&sender,"-@[]")) die_nomem(); token822_reverse(addr); } return 1; } int rwreturn(addr) token822_alloc *addr; { rwgeneric(addr); setreturn(addr); return 1; } int rwsender(addr) token822_alloc *addr; { rwgeneric(addr); return 1; } void rwappend(addr,xl) token822_alloc *addr; saa *xl; { token822_reverse(addr); if (!saa_readyplus(xl,1)) die_nomem(); xl->sa[xl->len] = sauninit; if (token822_unquote(&xl->sa[xl->len],addr) != 1) die_nomem(); ++xl->len; token822_reverse(addr); } int rwhrr(addr) token822_alloc *addr; { rwgeneric(addr); rwappend(addr,&hrrlist); return 1; } int rwhr(addr) token822_alloc *addr; { rwgeneric(addr); rwappend(addr,&hrlist); return 1; } int rwtocc(addr) token822_alloc *addr; { rwgeneric(addr); rwappend(addr,&hrlist); rwappend(addr,&tocclist); return 1; } int htypeseen[H_NUM]; stralloc hfbuf = {0}; token822_alloc hfin = {0}; token822_alloc hfrewrite = {0}; token822_alloc hfaddr = {0}; void doheaderfield(h) stralloc *h; { int htype; int (*rw)() = 0; htype = hfield_known(h->s,h->len); if (flagdeletefrom) if (htype == H_FROM) return; if (flagdeletemessid) if (htype == H_MESSAGEID) return; if (flagdeletesender) if (htype == H_RETURNPATH) return; if (htype) htypeseen[htype] = 1; else if (!hfield_valid(h->s,h->len)) die_invalid(h); switch(htype) { case H_TO: case H_CC: rw = rwtocc; break; case H_BCC: case H_APPARENTLYTO: rw = rwhr; break; case H_R_TO: case H_R_CC: case H_R_BCC: rw = rwhrr; break; case H_RETURNPATH: rw = rwreturn; break; case H_SENDER: case H_FROM: case H_REPLYTO: case H_RETURNRECEIPTTO: case H_ERRORSTO: case H_R_SENDER: case H_R_FROM: case H_R_REPLYTO: rw = rwsender; break; } if (rw) { doordie(h,token822_parse(&hfin,h,&hfbuf)); doordie(h,token822_addrlist(&hfrewrite,&hfaddr,&hfin,rw)); if (token822_unparse(h,&hfrewrite,LINELEN) != 1) die_nomem(); } if (htype == H_BCC) return; if (htype == H_R_BCC) return; if (htype == H_RETURNPATH) return; if (htype == H_CONTENTLENGTH) return; /* some things are just too stupid */ savedh_append(h); } void dobody(h) stralloc *h; { put(h->s,h->len); } stralloc torecip = {0}; token822_alloc tr = {0}; void dorecip(s) char *s; { if (!quote2(&torecip,s)) die_nomem(); switch(token822_parse(&tr,&torecip,&hfbuf)) { case -1: die_nomem(); case 0: substdio_puts(subfderr,"qmail-inject: fatal: unable to parse address: "); substdio_puts(subfderr,s); substdio_putsflush(subfderr,"\n"); perm(); } token822_reverse(&tr); rwgeneric(&tr); rwappend(&tr,&reciplist); } stralloc defaultfrom = {0}; token822_alloc df = {0}; void defaultfrommake() { char *fullname; fullname = env_get("QMAILNAME"); if (!fullname) fullname = env_get("MAILNAME"); if (!fullname) fullname = env_get("NAME"); if (!token822_ready(&df,20)) die_nomem(); df.len = 0; df.t[df.len].type = TOKEN822_ATOM; df.t[df.len].s = "From"; df.t[df.len].slen = 4; ++df.len; df.t[df.len].type = TOKEN822_COLON; ++df.len; if (fullname && !flagnamecomment) { df.t[df.len].type = TOKEN822_QUOTE; df.t[df.len].s = fullname; df.t[df.len].slen = str_len(fullname); ++df.len; df.t[df.len].type = TOKEN822_LEFT; ++df.len; } df.t[df.len].type = mailusertokentype; df.t[df.len].s = mailuser; df.t[df.len].slen = str_len(mailuser); ++df.len; if (mailhost) { df.t[df.len].type = TOKEN822_AT; ++df.len; df.t[df.len].type = TOKEN822_ATOM; df.t[df.len].s = mailhost; df.t[df.len].slen = str_len(mailhost); ++df.len; } if (fullname && !flagnamecomment) { df.t[df.len].type = TOKEN822_RIGHT; ++df.len; } if (fullname && flagnamecomment) { df.t[df.len].type = TOKEN822_COMMENT; df.t[df.len].s = fullname; df.t[df.len].slen = str_len(fullname); ++df.len; } if (token822_unparse(&defaultfrom,&df,LINELEN) != 1) die_nomem(); doordie(&defaultfrom,token822_parse(&df,&defaultfrom,&hfbuf)); doordie(&defaultfrom,token822_addrlist(&hfrewrite,&hfaddr,&df,rwsender)); if (token822_unparse(&defaultfrom,&hfrewrite,LINELEN) != 1) die_nomem(); } stralloc defaultreturnpath = {0}; token822_alloc drp = {0}; stralloc hackedruser = {0}; char strnum[FMT_ULONG]; void dodefaultreturnpath() { if (!stralloc_copys(&hackedruser,mailruser)) die_nomem(); if (flaghackmess) { if (!stralloc_cats(&hackedruser,"-")) die_nomem(); if (!stralloc_catb(&hackedruser,strnum,fmt_ulong(strnum,(unsigned long) starttime))) die_nomem(); if (!stralloc_cats(&hackedruser,".")) die_nomem(); if (!stralloc_catb(&hackedruser,strnum,fmt_ulong(strnum,(unsigned long) getpid()))) die_nomem(); } if (flaghackrecip) if (!stralloc_cats(&hackedruser,"-")) die_nomem(); if (!token822_ready(&drp,10)) die_nomem(); drp.len = 0; drp.t[drp.len].type = TOKEN822_ATOM; drp.t[drp.len].s = "Return-Path"; drp.t[drp.len].slen = 11; ++drp.len; drp.t[drp.len].type = TOKEN822_COLON; ++drp.len; drp.t[drp.len].type = TOKEN822_QUOTE; drp.t[drp.len].s = hackedruser.s; drp.t[drp.len].slen = hackedruser.len; ++drp.len; if (mailrhost) { drp.t[drp.len].type = TOKEN822_AT; ++drp.len; drp.t[drp.len].type = TOKEN822_ATOM; drp.t[drp.len].s = mailrhost; drp.t[drp.len].slen = str_len(mailrhost); ++drp.len; } if (token822_unparse(&defaultreturnpath,&drp,LINELEN) != 1) die_nomem(); doordie(&defaultreturnpath,token822_parse(&drp,&defaultreturnpath,&hfbuf)); doordie(&defaultreturnpath ,token822_addrlist(&hfrewrite,&hfaddr,&drp,rwreturn)); if (token822_unparse(&defaultreturnpath,&hfrewrite,LINELEN) != 1) die_nomem(); } int flagmft = 0; stralloc mft = {0}; struct constmap mapmft; void mft_init() { char *x; int r; x = env_get("QMAILMFTFILE"); if (!x) return; r = control_readfile(&mft,x,0); if (r == -1) die_read(); /*XXX*/ if (!r) return; if (!constmap_init(&mapmft,mft.s,mft.len,0)) die_nomem(); flagmft = 1; } void finishmft() { int i; static stralloc sa = {0}; static stralloc sa2 = {0}; if (!flagmft) return; if (htypeseen[H_MAILFOLLOWUPTO]) return; for (i = 0;i < tocclist.len;++i) if (constmap(&mapmft,tocclist.sa[i].s,tocclist.sa[i].len)) break; if (i == tocclist.len) return; puts("Mail-Followup-To: "); i = tocclist.len; while (i--) { if (!stralloc_copy(&sa,&tocclist.sa[i])) die_nomem(); if (!stralloc_0(&sa)) die_nomem(); if (!quote2(&sa2,sa.s)) die_nomem(); put(sa2.s,sa2.len); if (i) puts(",\n "); } puts("\n"); } void finishheader() { flagresent = htypeseen[H_R_SENDER] || htypeseen[H_R_FROM] || htypeseen[H_R_REPLYTO] || htypeseen[H_R_TO] || htypeseen[H_R_CC] || htypeseen[H_R_BCC] || htypeseen[H_R_DATE] || htypeseen[H_R_MESSAGEID]; if (!sender.s) dodefaultreturnpath(); if (!flagqueue) { static stralloc sa = {0}; static stralloc sa2 = {0}; if (!stralloc_copy(&sa,&sender)) die_nomem(); if (!stralloc_0(&sa)) die_nomem(); if (!quote2(&sa2,sa.s)) die_nomem(); puts("Return-Path: <"); put(sa2.s,sa2.len); puts(">\n"); } /* could check at this point whether there are any recipients */ if (flagqueue) if (qmail_open(&qqt) == -1) die_qqt(); if (flagresent) { if (!htypeseen[H_R_DATE]) { if (!newfield_datemake(starttime)) die_nomem(); puts("Resent-"); put(newfield_date.s,newfield_date.len); } if (!htypeseen[H_R_MESSAGEID]) { if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem(); puts("Resent-"); put(newfield_msgid.s,newfield_msgid.len); } if (!htypeseen[H_R_FROM]) { defaultfrommake(); puts("Resent-"); put(defaultfrom.s,defaultfrom.len); } if (!htypeseen[H_R_TO] && !htypeseen[H_R_CC]) puts("Resent-Cc: recipient list not shown: ;\n"); } else { if (!htypeseen[H_DATE]) { if (!newfield_datemake(starttime)) die_nomem(); put(newfield_date.s,newfield_date.len); } if (!htypeseen[H_MESSAGEID]) { if (!newfield_msgidmake(control_idhost.s,control_idhost.len,starttime)) die_nomem(); put(newfield_msgid.s,newfield_msgid.len); } if (!htypeseen[H_FROM]) { defaultfrommake(); put(defaultfrom.s,defaultfrom.len); } if (!htypeseen[H_TO] && !htypeseen[H_CC]) puts("Cc: recipient list not shown: ;\n"); finishmft(); } savedh_print(); } void getcontrols() { static stralloc sa = {0}; char *x; mft_init(); if (chdir(auto_qmail) == -1) die_chdir(); if (control_init() == -1) die_read(); if (control_rldef(&control_defaultdomain,"control/defaultdomain",1,"defaultdomain") != 1) die_read(); x = env_get("QMAILDEFAULTDOMAIN"); if (x) if (!stralloc_copys(&control_defaultdomain,x)) die_nomem(); if (!stralloc_copys(&sa,".")) die_nomem(); if (!stralloc_cat(&sa,&control_defaultdomain)) die_nomem(); doordie(&sa,token822_parse(&defaultdomain,&sa,&defaultdomainbuf)); if (control_rldef(&control_defaulthost,"control/defaulthost",1,"defaulthost") != 1) die_read(); x = env_get("QMAILDEFAULTHOST"); if (x) if (!stralloc_copys(&control_defaulthost,x)) die_nomem(); if (!stralloc_copys(&sa,"@")) die_nomem(); if (!stralloc_cat(&sa,&control_defaulthost)) die_nomem(); doordie(&sa,token822_parse(&defaulthost,&sa,&defaulthostbuf)); if (control_rldef(&control_plusdomain,"control/plusdomain",1,"plusdomain") != 1) die_read(); x = env_get("QMAILPLUSDOMAIN"); if (x) if (!stralloc_copys(&control_plusdomain,x)) die_nomem(); if (!stralloc_copys(&sa,".")) die_nomem(); if (!stralloc_cat(&sa,&control_plusdomain)) die_nomem(); doordie(&sa,token822_parse(&plusdomain,&sa,&plusdomainbuf)); if (control_rldef(&control_idhost,"control/idhost",1,"idhost") != 1) die_read(); x = env_get("QMAILIDHOST"); if (x) if (!stralloc_copys(&control_idhost,x)) die_nomem(); } #define RECIP_DEFAULT 1 #define RECIP_ARGS 2 #define RECIP_HEADER 3 #define RECIP_AH 4 void main(argc,argv) int argc; char **argv; { int i; int opt; int recipstrategy; sig_pipeignore(); starttime = now(); qmopts = env_get("QMAILINJECT"); if (qmopts) while (*qmopts) switch(*qmopts++) { case 'c': flagnamecomment = 1; break; case 's': flagdeletesender = 1; break; case 'f': flagdeletefrom = 1; break; case 'i': flagdeletemessid = 1; break; case 'r': flaghackrecip = 1; break; case 'm': flaghackmess = 1; break; } mailhost = env_get("QMAILHOST"); if (!mailhost) mailhost = env_get("MAILHOST"); mailrhost = env_get("QMAILSHOST"); if (!mailrhost) mailrhost = mailhost; mailuser = env_get("QMAILUSER"); if (!mailuser) mailuser = env_get("MAILUSER"); if (!mailuser) mailuser = env_get("USER"); if (!mailuser) mailuser = env_get("LOGNAME"); if (!mailuser) mailuser = "anonymous"; mailusertokentype = TOKEN822_ATOM; if (quote_need(mailuser,str_len(mailuser))) mailusertokentype = TOKEN822_QUOTE; mailruser = env_get("QMAILSUSER"); if (!mailruser) mailruser = mailuser; for (i = 0;i < H_NUM;++i) htypeseen[i] = 0; recipstrategy = RECIP_DEFAULT; flagqueue = 1; getcontrols(); if (!saa_readyplus(&hrlist,1)) die_nomem(); if (!saa_readyplus(&tocclist,1)) die_nomem(); if (!saa_readyplus(&hrrlist,1)) die_nomem(); if (!saa_readyplus(&reciplist,1)) die_nomem(); while ((opt = getopt(argc,argv,"aAhHnNf:")) != opteof) switch(opt) { case 'a': recipstrategy = RECIP_ARGS; break; case 'A': recipstrategy = RECIP_DEFAULT; break; case 'h': recipstrategy = RECIP_HEADER; break; case 'H': recipstrategy = RECIP_AH; break; case 'n': flagqueue = 0; break; case 'N': flagqueue = 1; break; case 'f': if (!quote2(&sender,optarg)) die_nomem(); doordie(&sender,token822_parse(&envs,&sender,&envsbuf)); token822_reverse(&envs); rwgeneric(&envs); token822_reverse(&envs); if (token822_unquote(&sender,&envs) != 1) die_nomem(); break; case '?': default: perm(); } argc -= optind; argv += optind; if (recipstrategy == RECIP_DEFAULT) recipstrategy = (*argv ? RECIP_ARGS : RECIP_HEADER); if (recipstrategy != RECIP_HEADER) while (*argv) dorecip(*argv++); flagrh = (recipstrategy != RECIP_ARGS); if (headerbody(subfdin,doheaderfield,finishheader,dobody) == -1) die_read(); exitnicely(); } netqmail-1.06/sig_hup.c0000644000076400007640000000037406541176434014460 0ustar nelsonnelson#include #include "sig.h" void sig_hangupblock() { sig_block(SIGHUP); } void sig_hangupunblock() { sig_unblock(SIGHUP); } void sig_hangupcatch(f) void (*f)(); { sig_catch(SIGHUP,f); } void sig_hangupdefault() { sig_catch(SIGHUP,SIG_DFL); } netqmail-1.06/BLURB0000644000076400007640000000465106541176434013451 0ustar nelsonnelsonqmail is a secure, reliable, efficient, simple message transfer agent. It is meant as a replacement for the entire sendmail-binmail system on typical Internet-connected UNIX hosts. Secure: Security isn't just a goal, but an absolute requirement. Mail delivery is critical for users; it cannot be turned off, so it must be completely secure. (This is why I started writing qmail: I was sick of the security holes in sendmail and other MTAs.) Reliable: qmail's straight-paper-path philosophy guarantees that a message, once accepted into the system, will never be lost. qmail also supports maildir, a new, super-reliable user mailbox format. Maildirs, unlike mbox files and mh folders, won't be corrupted if the system crashes during delivery. Even better, not only can a user safely read his mail over NFS, but any number of NFS clients can deliver mail to him at the same time. Efficient: On a Pentium under BSD/OS, qmail can easily sustain 200000 local messages per day---that's separate messages injected and delivered to mailboxes in a real test! Although remote deliveries are inherently limited by the slowness of DNS and SMTP, qmail overlaps 20 simultaneous deliveries by default, so it zooms quickly through mailing lists. (This is why I finished qmail: I had to get a big mailing list set up.) Simple: qmail is vastly smaller than any other Internet MTA. Some reasons why: (1) Other MTAs have separate forwarding, aliasing, and mailing list mechanisms. qmail has one simple forwarding mechanism that lets users handle their own mailing lists. (2) Other MTAs offer a spectrum of delivery modes, from fast+unsafe to slow+queued. qmail-send is instantly triggered by new items in the queue, so the qmail system has just one delivery mode: fast+queued. (3) Other MTAs include, in effect, a specialized version of inetd that watches the load average. qmail's design inherently limits the machine load, so qmail-smtpd can safely run from your system's inetd. Replacement for sendmail: qmail supports host and user masquerading, full host hiding, virtual domains, null clients, list-owner rewriting, relay control, double-bounce recording, arbitrary RFC 822 address lists, cross-host mailing list loop detection, per-recipient checkpointing, downed host backoffs, independent message retry schedules, etc. In short, it's up to speed on modern MTA features. qmail also includes a drop-in ``sendmail'' wrapper so that it will be used transparently by your current UAs. netqmail-1.06/chkspawn.c0000644000076400007640000000252006541176434014633 0ustar nelsonnelson#include "substdio.h" #include "subfd.h" #include "fmt.h" #include "select.h" #include "exit.h" #include "auto_spawn.h" char num[FMT_ULONG]; fd_set fds; void main() { unsigned long hiddenlimit; unsigned long maxnumd; hiddenlimit = sizeof(fds) * 8; maxnumd = (hiddenlimit - 5) / 2; if (auto_spawn < 1) { substdio_puts(subfderr,"Oops. You have set conf-spawn lower than 1.\n"); substdio_flush(subfderr); _exit(1); } if (auto_spawn > 255) { substdio_puts(subfderr,"Oops. You have set conf-spawn higher than 255.\n"); substdio_flush(subfderr); _exit(1); } if (auto_spawn > maxnumd) { substdio_puts(subfderr,"Oops. Your system's FD_SET() has a hidden limit of "); substdio_put(subfderr,num,fmt_ulong(num,hiddenlimit)); substdio_puts(subfderr," descriptors.\n\ This means that the qmail daemons could crash if you set the run-time\n\ concurrency higher than "); substdio_put(subfderr,num,fmt_ulong(num,maxnumd)); substdio_puts(subfderr,". So I'm going to insist that the concurrency\n\ limit in conf-spawn be at most "); substdio_put(subfderr,num,fmt_ulong(num,maxnumd)); substdio_puts(subfderr,". Right now it's "); substdio_put(subfderr,num,fmt_ulong(num,(unsigned long) auto_spawn)); substdio_puts(subfderr,".\n"); substdio_flush(subfderr); _exit(1); } _exit(0); } netqmail-1.06/received.h0000644000076400007640000000010706541176434014607 0ustar nelsonnelson#ifndef RECEIVED_H #define RECEIVED_H extern void received(); #endif netqmail-1.06/subgetopt.h0000644000076400007640000000101006541176434015027 0ustar nelsonnelson#ifndef SUBGETOPT_H #define SUBGETOPT_H #ifndef SUBGETOPTNOSHORT #define sgopt subgetopt #define sgoptarg subgetoptarg #define sgoptind subgetoptind #define sgoptpos subgetoptpos #define sgoptproblem subgetoptproblem #define sgoptprogname subgetoptprogname #define sgoptdone subgetoptdone #endif #define SUBGETOPTDONE -1 extern int subgetopt(); extern char *subgetoptarg; extern int subgetoptind; extern int subgetoptpos; extern int subgetoptproblem; extern char *subgetoptprogname; extern int subgetoptdone; #endif netqmail-1.06/trysgact.c0000644000076400007640000000025306541176434014656 0ustar nelsonnelson#include void main() { struct sigaction sa; sa.sa_handler = 0; sa.sa_flags = 0; sigemptyset(&sa.sa_mask); sigaction(0,&sa,(struct sigaction *) 0); } netqmail-1.06/maildirwatch.10000644000076400007640000000070706541176434015410 0ustar nelsonnelson.TH maildirwatch 1 .SH NAME maildirwatch \- look for new mail in a maildir .SH SYNOPSIS .B maildirwatch .SH DESCRIPTION .B maildirwatch watches your .I maildir for new mail. You must supply a .B MAILDIR environment variable with the name of your .I maildir directory. .B maildirwatch prints a new mail summary twice per minute. It is designed to run inside a (VT100-compatible) window; it clears the window before each summary. .SH "SEE ALSO" maildir(5) netqmail-1.06/qmail-lspawn.c0000644000076400007640000001257206541176434015432 0ustar nelsonnelson#include "fd.h" #include "wait.h" #include "prot.h" #include "substdio.h" #include "stralloc.h" #include "scan.h" #include "exit.h" #include "fork.h" #include "error.h" #include "cdb.h" #include "case.h" #include "slurpclose.h" #include "auto_qmail.h" #include "auto_uids.h" #include "qlx.h" char *aliasempty; void initialize(argc,argv) int argc; char **argv; { aliasempty = argv[1]; if (!aliasempty) _exit(100); } int truncreport = 3000; void report(ss,wstat,s,len) substdio *ss; int wstat; char *s; int len; { int i; if (wait_crashed(wstat)) { substdio_puts(ss,"Zqmail-local crashed.\n"); return; } switch(wait_exitcode(wstat)) { case QLX_CDB: substdio_puts(ss,"ZTrouble reading users/cdb in qmail-lspawn.\n"); return; case QLX_NOMEM: substdio_puts(ss,"ZOut of memory in qmail-lspawn.\n"); return; case QLX_SYS: substdio_puts(ss,"ZTemporary failure in qmail-lspawn.\n"); return; case QLX_NOALIAS: substdio_puts(ss,"ZUnable to find alias user!\n"); return; case QLX_ROOT: substdio_puts(ss,"ZNot allowed to perform deliveries as root.\n"); return; case QLX_USAGE: substdio_puts(ss,"ZInternal qmail-lspawn bug.\n"); return; case QLX_NFS: substdio_puts(ss,"ZNFS failure in qmail-local.\n"); return; case QLX_EXECHARD: substdio_puts(ss,"DUnable to run qmail-local.\n"); return; case QLX_EXECSOFT: substdio_puts(ss,"ZUnable to run qmail-local.\n"); return; case QLX_EXECPW: substdio_puts(ss,"ZUnable to run qmail-getpw.\n"); return; case 111: case 71: case 74: case 75: substdio_put(ss,"Z",1); break; case 0: substdio_put(ss,"K",1); break; case 100: default: substdio_put(ss,"D",1); break; } for (i = 0;i < len;++i) if (!s[i]) break; substdio_put(ss,s,i); } stralloc lower = {0}; stralloc nughde = {0}; stralloc wildchars = {0}; void nughde_get(local) char *local; { char *(args[3]); int pi[2]; int gpwpid; int gpwstat; int r; int fd; int flagwild; if (!stralloc_copys(&lower,"!")) _exit(QLX_NOMEM); if (!stralloc_cats(&lower,local)) _exit(QLX_NOMEM); if (!stralloc_0(&lower)) _exit(QLX_NOMEM); case_lowerb(lower.s,lower.len); if (!stralloc_copys(&nughde,"")) _exit(QLX_NOMEM); fd = open_read("users/cdb"); if (fd == -1) if (errno != error_noent) _exit(QLX_CDB); if (fd != -1) { uint32 dlen; unsigned int i; r = cdb_seek(fd,"",0,&dlen); if (r != 1) _exit(QLX_CDB); if (!stralloc_ready(&wildchars,(unsigned int) dlen)) _exit(QLX_NOMEM); wildchars.len = dlen; if (cdb_bread(fd,wildchars.s,wildchars.len) == -1) _exit(QLX_CDB); i = lower.len; flagwild = 0; do { /* i > 0 */ if (!flagwild || (i == 1) || (byte_chr(wildchars.s,wildchars.len,lower.s[i - 1]) < wildchars.len)) { r = cdb_seek(fd,lower.s,i,&dlen); if (r == -1) _exit(QLX_CDB); if (r == 1) { if (!stralloc_ready(&nughde,(unsigned int) dlen)) _exit(QLX_NOMEM); nughde.len = dlen; if (cdb_bread(fd,nughde.s,nughde.len) == -1) _exit(QLX_CDB); if (flagwild) if (!stralloc_cats(&nughde,local + i - 1)) _exit(QLX_NOMEM); if (!stralloc_0(&nughde)) _exit(QLX_NOMEM); close(fd); return; } } --i; flagwild = 1; } while (i); close(fd); } if (pipe(pi) == -1) _exit(QLX_SYS); args[0] = "bin/qmail-getpw"; args[1] = local; args[2] = 0; switch(gpwpid = vfork()) { case -1: _exit(QLX_SYS); case 0: if (prot_gid(auto_gidn) == -1) _exit(QLX_USAGE); if (prot_uid(auto_uidp) == -1) _exit(QLX_USAGE); close(pi[0]); if (fd_move(1,pi[1]) == -1) _exit(QLX_SYS); execv(*args,args); _exit(QLX_EXECPW); } close(pi[1]); if (slurpclose(pi[0],&nughde,128) == -1) _exit(QLX_SYS); if (wait_pid(&gpwstat,gpwpid) != -1) { if (wait_crashed(gpwstat)) _exit(QLX_SYS); if (wait_exitcode(gpwstat) != 0) _exit(wait_exitcode(gpwstat)); } } int spawn(fdmess,fdout,s,r,at) int fdmess; int fdout; char *s; char *r; int at; { int f; if (!(f = fork())) { char *(args[11]); unsigned long u; int n; int uid; int gid; char *x; unsigned int xlen; r[at] = 0; if (!r[0]) _exit(0); /* <> */ if (chdir(auto_qmail) == -1) _exit(QLX_USAGE); nughde_get(r); x = nughde.s; xlen = nughde.len; args[0] = "bin/qmail-local"; args[1] = "--"; args[2] = x; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; scan_ulong(x,&u); uid = u; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; scan_ulong(x,&u); gid = u; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; args[3] = x; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; args[4] = r; args[5] = x; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; args[6] = x; n = byte_chr(x,xlen,0); if (n++ == xlen) _exit(QLX_USAGE); x += n; xlen -= n; args[7] = r + at + 1; args[8] = s; args[9] = aliasempty; args[10] = 0; if (fd_move(0,fdmess) == -1) _exit(QLX_SYS); if (fd_move(1,fdout) == -1) _exit(QLX_SYS); if (fd_copy(2,1) == -1) _exit(QLX_SYS); if (prot_gid(gid) == -1) _exit(QLX_USAGE); if (prot_uid(uid) == -1) _exit(QLX_USAGE); if (!getuid()) _exit(QLX_ROOT); execv(*args,args); if (error_temp(errno)) _exit(QLX_EXECSOFT); _exit(QLX_EXECHARD); } return f; } netqmail-1.06/PIC.nullclient0000644000076400007640000000242106541176434015357 0ustar nelsonnelson Original message: To: bill@irs.gov Hi. qmail-inject Fill in the complete envelope and header: | (envelope) from joe@heaven.af.mil to bill@irs.gov | From: joe@heaven.af.mil | To: bill@irs.gov | | Hi. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, bill@irs.gov. | Is irs.gov in locals? No. | Is bill@irs.gov in virtualdomains? No. | Is irs.gov in virtualdomains? No. | Is .gov in virtualdomains? No. | Deliver remotely to bill@irs.gov. V qmail-rspawn Run qmail-remote. | V qmail-remote Look at host name, irs.gov. Is irs.gov listed in smtproutes? Yes: ":bigbang.af.mil". Look up DNS A for bigbang.af.mil and connect by SMTP: MAIL FROM: RCPT TO: netqmail-1.06/qmail-control.90000644000076400007640000000361606541176434015533 0ustar nelsonnelson.TH qmail-control 5 .SH "NAME" qmail-control \- qmail configuration files .SH "INTRODUCTION" You can change the behavior of the .B qmail system by modifying .BR qmail 's .I control files in .BR QMAILHOME/control . .B qmail can survive with just one control file, .IR me , containing the fully-qualified name of the current host. This file is used as the default for other hostname-related control files. Comments are allowed in .IR badmailfrom , .IR locals , .IR percenthack , .IR qmqpservers , .IR rcpthosts , .IR smtproutes , and .IR virtualdomains . Trailing spaces and tabs are allowed in any control file. The following table lists all control files other than .IR me . See the corresponding man pages for further details. .RS .nf .ta 5c 10c control default used by .I badmailfrom \fR(none) \fRqmail-smtpd .I bouncefrom \fRMAILER-DAEMON \fRqmail-send .I bouncehost \fIme \fRqmail-send .I concurrencylocal \fR10 \fRqmail-send .I concurrencyremote \fR20 \fRqmail-send .I defaultdomain \fIme \fRqmail-inject .I defaulthost \fIme \fRqmail-inject .I databytes \fR0 \fRqmail-smtpd .I doublebouncehost \fIme \fRqmail-send .I doublebounceto \fRpostmaster \fRqmail-send .I envnoathost \fIme \fRqmail-send .I helohost \fIme \fRqmail-remote .I idhost \fIme \fRqmail-inject .I localiphost \fIme \fRqmail-smtpd .I locals \fIme \fRqmail-send .I morercpthosts \fR(none) \fRqmail-smtpd .I percenthack \fR(none) \fRqmail-send .I plusdomain \fIme \fRqmail-inject .I qmqpservers \fR(none) \fRqmail-qmqpc .I queuelifetime \fR604800 \fRqmail-send .I rcpthosts \fR(none) \fRqmail-smtpd .I smtpgreeting \fIme \fRqmail-smtpd .I smtproutes \fR(none) \fRqmail-remote .I timeoutconnect \fR60 \fRqmail-remote .I timeoutremote \fR1200 \fRqmail-remote .I timeoutsmtpd \fR1200 \fRqmail-smtpd .I virtualdomains \fR(none) \fRqmail-send .fi .RE .SH "SEE ALSO" qmail-inject(8), qmail-qmqpc(8), qmail-remote(8), qmail-send(8), qmail-showctl(8), qmail-smtpd(8) netqmail-1.06/extra.h0000644000076400007640000000013106541176434014141 0ustar nelsonnelson#ifndef EXTRA_H #define EXTRA_H #define QUEUE_EXTRA "" #define QUEUE_EXTRALEN 0 #endif netqmail-1.06/env.c0000644000076400007640000000436106541176434013612 0ustar nelsonnelson/* env.c, envread.c, env.h: environ library Daniel J. Bernstein, djb@silverton.berkeley.edu. Depends on str.h, alloc.h. Requires environ. 19960113: rewrite. warning: interface is different. No known patent problems. */ #include "str.h" #include "alloc.h" #include "env.h" int env_isinit = 0; /* if env_isinit: */ static int ea; /* environ is a pointer to ea+1 char*'s. */ static int en; /* the first en of those are ALLOCATED. environ[en] is 0. */ static void env_goodbye(i) int i; { alloc_free(environ[i]); environ[i] = environ[--en]; environ[en] = 0; } static char *null = 0; void env_clear() { if (env_isinit) while (en) env_goodbye(0); else environ = &null; } static void env_unsetlen(s,len) char *s; int len; { int i; for (i = en - 1;i >= 0;--i) if (!str_diffn(s,environ[i],len)) if (environ[i][len] == '=') env_goodbye(i); } int env_unset(s) char *s; { if (!env_isinit) if (!env_init()) return 0; env_unsetlen(s,str_len(s)); return 1; } static int env_add(s) char *s; { char *t; t = env_findeq(s); if (t) env_unsetlen(s,t - s); if (en == ea) { ea += 30; if (!alloc_re(&environ,(en + 1) * sizeof(char *),(ea + 1) * sizeof(char *))) { ea = en; return 0; } } environ[en++] = s; environ[en] = 0; return 1; } int env_put(s) char *s; { char *u; if (!env_isinit) if (!env_init()) return 0; u = alloc(str_len(s) + 1); if (!u) return 0; str_copy(u,s); if (!env_add(u)) { alloc_free(u); return 0; } return 1; } int env_put2(s,t) char *s; char *t; { char *u; int slen; if (!env_isinit) if (!env_init()) return 0; slen = str_len(s); u = alloc(slen + str_len(t) + 2); if (!u) return 0; str_copy(u,s); u[slen] = '='; str_copy(u + slen + 1,t); if (!env_add(u)) { alloc_free(u); return 0; } return 1; } int env_init() { char **newenviron; int i; for (en = 0;environ[en];++en) ; ea = en + 10; newenviron = (char **) alloc((ea + 1) * sizeof(char *)); if (!newenviron) return 0; for (en = 0;environ[en];++en) { newenviron[en] = alloc(str_len(environ[en]) + 1); if (!newenviron[en]) { for (i = 0;i < en;++i) alloc_free(newenviron[i]); alloc_free(newenviron); return 0; } str_copy(newenviron[en],environ[en]); } newenviron[en] = 0; environ = newenviron; env_isinit = 1; return 1; } netqmail-1.06/dns.c0000644000076400007640000002027410724070436013600 0ustar nelsonnelson#include #include #include #include #include #include #include extern int res_query(); extern int res_search(); #include "ip.h" #include "ipalloc.h" #include "fmt.h" #include "alloc.h" #include "str.h" #include "stralloc.h" #include "dns.h" #include "case.h" static unsigned short getshort(c) unsigned char *c; { unsigned short u; u = c[0]; return (u << 8) + c[1]; } static union { HEADER hdr; unsigned char buf[PACKETSZ]; } response; static int responselen; static unsigned char *responseend; static unsigned char *responsepos; static int numanswers; static char name[MAXDNAME]; static struct ip_address ip; unsigned short pref; static stralloc glue = {0}; static int (*lookup)() = res_query; static int resolve(domain,type) stralloc *domain; int type; { int n; int i; errno = 0; if (!stralloc_copy(&glue,domain)) return DNS_MEM; if (!stralloc_0(&glue)) return DNS_MEM; responselen = lookup(glue.s,C_IN,type,response.buf,sizeof(response)); if (responselen <= 0) { if (errno == ECONNREFUSED) return DNS_SOFT; if (h_errno == TRY_AGAIN) return DNS_SOFT; return DNS_HARD; } if (responselen >= sizeof(response)) responselen = sizeof(response); responseend = response.buf + responselen; responsepos = response.buf + sizeof(HEADER); n = ntohs(response.hdr.qdcount); while (n-- > 0) { i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); if (i < 0) return DNS_SOFT; responsepos += i; i = responseend - responsepos; if (i < QFIXEDSZ) return DNS_SOFT; responsepos += QFIXEDSZ; } numanswers = ntohs(response.hdr.ancount); return 0; } static int findname(wanttype) int wanttype; { unsigned short rrtype; unsigned short rrdlen; int i; if (numanswers <= 0) return 2; --numanswers; if (responsepos == responseend) return DNS_SOFT; i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); if (i < 0) return DNS_SOFT; responsepos += i; i = responseend - responsepos; if (i < 4 + 3 * 2) return DNS_SOFT; rrtype = getshort(responsepos); rrdlen = getshort(responsepos + 8); responsepos += 10; if (rrtype == wanttype) { if (dn_expand(response.buf,responseend,responsepos,name,MAXDNAME) < 0) return DNS_SOFT; responsepos += rrdlen; return 1; } responsepos += rrdlen; return 0; } static int findip(wanttype) int wanttype; { unsigned short rrtype; unsigned short rrdlen; int i; if (numanswers <= 0) return 2; --numanswers; if (responsepos == responseend) return DNS_SOFT; i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); if (i < 0) return DNS_SOFT; responsepos += i; i = responseend - responsepos; if (i < 4 + 3 * 2) return DNS_SOFT; rrtype = getshort(responsepos); rrdlen = getshort(responsepos + 8); responsepos += 10; if (rrtype == wanttype) { if (rrdlen < 4) return DNS_SOFT; ip.d[0] = responsepos[0]; ip.d[1] = responsepos[1]; ip.d[2] = responsepos[2]; ip.d[3] = responsepos[3]; responsepos += rrdlen; return 1; } responsepos += rrdlen; return 0; } static int findmx(wanttype) int wanttype; { unsigned short rrtype; unsigned short rrdlen; int i; if (numanswers <= 0) return 2; --numanswers; if (responsepos == responseend) return DNS_SOFT; i = dn_expand(response.buf,responseend,responsepos,name,MAXDNAME); if (i < 0) return DNS_SOFT; responsepos += i; i = responseend - responsepos; if (i < 4 + 3 * 2) return DNS_SOFT; rrtype = getshort(responsepos); rrdlen = getshort(responsepos + 8); responsepos += 10; if (rrtype == wanttype) { if (rrdlen < 3) return DNS_SOFT; pref = (responsepos[0] << 8) + responsepos[1]; if (dn_expand(response.buf,responseend,responsepos + 2,name,MAXDNAME) < 0) return DNS_SOFT; responsepos += rrdlen; return 1; } responsepos += rrdlen; return 0; } void dns_init(flagsearch) int flagsearch; { res_init(); if (flagsearch) lookup = res_search; } int dns_cname(sa) stralloc *sa; { int r; int loop; for (loop = 0;loop < 10;++loop) { if (!sa->len) return loop; if (sa->s[sa->len - 1] == ']') return loop; if (sa->s[sa->len - 1] == '.') { --sa->len; continue; } switch(resolve(sa,T_ANY)) { case DNS_MEM: return DNS_MEM; case DNS_SOFT: return DNS_SOFT; case DNS_HARD: return loop; default: while ((r = findname(T_CNAME)) != 2) { if (r == DNS_SOFT) return DNS_SOFT; if (r == 1) { if (!stralloc_copys(sa,name)) return DNS_MEM; break; } } if (r == 2) return loop; } } return DNS_HARD; /* alias loop */ } #define FMT_IAA 40 static int iaafmt(s,ip) char *s; struct ip_address *ip; { unsigned int i; unsigned int len; len = 0; i = fmt_ulong(s,(unsigned long) ip->d[3]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[2]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[1]); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_ulong(s,(unsigned long) ip->d[0]); len += i; if (s) s += i; i = fmt_str(s,".in-addr.arpa."); len += i; if (s) s += i; return len; } int dns_ptr(sa,ip) stralloc *sa; struct ip_address *ip; { int r; if (!stralloc_ready(sa,iaafmt((char *) 0,ip))) return DNS_MEM; sa->len = iaafmt(sa->s,ip); switch(resolve(sa,T_PTR)) { case DNS_MEM: return DNS_MEM; case DNS_SOFT: return DNS_SOFT; case DNS_HARD: return DNS_HARD; } while ((r = findname(T_PTR)) != 2) { if (r == DNS_SOFT) return DNS_SOFT; if (r == 1) { if (!stralloc_copys(sa,name)) return DNS_MEM; return 0; } } return DNS_HARD; } static int dns_ipplus(ia,sa,pref) ipalloc *ia; stralloc *sa; int pref; { int r; struct ip_mx ix; if (!stralloc_copy(&glue,sa)) return DNS_MEM; if (!stralloc_0(&glue)) return DNS_MEM; if (glue.s[0]) { ix.pref = 0; if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) { if (!ipalloc_append(ia,&ix)) return DNS_MEM; return 0; } } switch(resolve(sa,T_A)) { case DNS_MEM: return DNS_MEM; case DNS_SOFT: return DNS_SOFT; case DNS_HARD: return DNS_HARD; } while ((r = findip(T_A)) != 2) { ix.ip = ip; ix.pref = pref; if (r == DNS_SOFT) return DNS_SOFT; if (r == 1) if (!ipalloc_append(ia,&ix)) return DNS_MEM; } return 0; } int dns_ip(ia,sa) ipalloc *ia; stralloc *sa; { if (!ipalloc_readyplus(ia,0)) return DNS_MEM; ia->len = 0; return dns_ipplus(ia,sa,0); } int dns_mxip(ia,sa,random) ipalloc *ia; stralloc *sa; unsigned long random; { int r; struct mx { stralloc sa; unsigned short p; } *mx; struct ip_mx ix; int nummx; int i; int j; int flagsoft; if (!ipalloc_readyplus(ia,0)) return DNS_MEM; ia->len = 0; if (!stralloc_copy(&glue,sa)) return DNS_MEM; if (!stralloc_0(&glue)) return DNS_MEM; if (glue.s[0]) { ix.pref = 0; if (!glue.s[ip_scan(glue.s,&ix.ip)] || !glue.s[ip_scanbracket(glue.s,&ix.ip)]) { if (!ipalloc_append(ia,&ix)) return DNS_MEM; return 0; } } switch(resolve(sa,T_MX)) { case DNS_MEM: return DNS_MEM; case DNS_SOFT: return DNS_SOFT; case DNS_HARD: return dns_ip(ia,sa); } mx = (struct mx *) alloc(numanswers * sizeof(struct mx)); if (!mx) return DNS_MEM; nummx = 0; while ((r = findmx(T_MX)) != 2) { if (r == DNS_SOFT) { alloc_free(mx); return DNS_SOFT; } if (r == 1) { mx[nummx].p = pref; mx[nummx].sa.s = 0; if (!stralloc_copys(&mx[nummx].sa,name)) { while (nummx > 0) alloc_free(mx[--nummx].sa.s); alloc_free(mx); return DNS_MEM; } ++nummx; } } if (!nummx) return dns_ip(ia,sa); /* e.g., CNAME -> A */ flagsoft = 0; while (nummx > 0) { unsigned long numsame; i = 0; numsame = 1; for (j = 1;j < nummx;++j) if (mx[j].p < mx[i].p) { i = j; numsame = 1; } else if (mx[j].p == mx[i].p) { ++numsame; random = random * 69069 + 1; if ((random / 2) < (2147483647 / numsame)) i = j; } switch(dns_ipplus(ia,&mx[i].sa,mx[i].p)) { case DNS_MEM: case DNS_SOFT: flagsoft = 1; break; } alloc_free(mx[i].sa.s); mx[i] = mx[--nummx]; } alloc_free(mx); return flagsoft; } netqmail-1.06/cdb_unpack.c0000644000076400007640000000030106541176434015101 0ustar nelsonnelson#include "cdb.h" uint32 cdb_unpack(buf) unsigned char *buf; { uint32 num; num = buf[3]; num <<= 8; num += buf[2]; num <<= 8; num += buf[1]; num <<= 8; num += buf[0]; return num; } netqmail-1.06/binm2.sh0000644000076400007640000000046706541176434014224 0ustar nelsonnelson#!/bin/sh # Using splogger to send the log through syslog. # Using binmail to deliver messages to /var/spool/mail/$USER by default. # Using SVR4 binmail interface: /bin/mail -r exec env - PATH="QMAIL/bin:$PATH" \ qmail-start \ '|preline -f /bin/mail -r "${SENDER:-MAILER-DAEMON}" -d "$USER"' \ splogger qmail netqmail-1.06/qmail-pop3d.80000644000076400007640000000146406541176434015076 0ustar nelsonnelson.TH qmail-pop3d 8 .SH NAME qmail-pop3d \- distribute mail via POP .SH SYNOPSIS .B qmail-pop3d .I maildirname .SH DESCRIPTION .B qmail-pop3d lets a user read and delete his mail through the network. Mail is stored in a .B maildir called .IR maildirname , normally .BR Maildir , in the user's home directory. .B qmail-pop3d is normally invoked under .BR qmail-popup , which reads a username and password, and .BR /bin/checkpassword , which checks the password and sets up environment variables. .B qmail-pop3d has a 20-minute idle timeout. .B qmail-pop3d supports UIDL, TOP, and LAST. .B qmail-pop3d appends an extra blank line to every message to work around serious bugs in certain clients. .B qmail-pop3d is based on a program contributed by Russ Nelson. .SH "SEE ALSO" maildir(5), qmail-local(8), qmail-popup(8) netqmail-1.06/str_diff.c0000644000076400007640000000066706541176434014627 0ustar nelsonnelson#include "str.h" int str_diff(s,t) register char *s; register char *t; { register char x; for (;;) { x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; x = *s; if (x != *t) break; if (!x) break; ++s; ++t; } return ((int)(unsigned int)(unsigned char) x) - ((int)(unsigned int)(unsigned char) *t); } netqmail-1.06/conf-break0000644000076400007640000000043006541176434014601 0ustar nelsonnelson- This character is the user-ext delimiter. The default delimiter is -, meaning that user joe controls joe-anything. Some system administrators prefer + or =. You can override this choice at run time with the qmail-users mechanism. Multicharacter delimiters are not permitted. netqmail-1.06/envread.c0000644000076400007640000000066706541176434014453 0ustar nelsonnelson#include "env.h" #include "str.h" extern /*@null@*/char *env_get(s) char *s; { int i; unsigned int slen; char *envi; slen = str_len(s); for (i = 0;envi = environ[i];++i) if ((!str_diffn(s,envi,slen)) && (envi[slen] == '=')) return envi + slen + 1; return 0; } extern char *env_pick() { return environ[0]; } extern char *env_findeq(s) char *s; { for (;*s;++s) if (*s == '=') return s; return 0; } netqmail-1.06/error.30000644000076400007640000000140310724070436014056 0ustar nelsonnelson.TH error 3 .SH NAME error \- syscall error codes .SH SYNTAX .B #include .br .B #include extern int \fBerror_intr\fP; .br extern int \fBerror_nomem\fP; .br extern int \fBerror_noent\fP; .br extern int \fBerror_txtbsy\fP; .br extern int \fBerror_io\fP; .br extern int \fBerror_exist\fP; .br extern int \fBerror_timeout\fP; .br extern int \fBerror_inprogress\fP; .br extern int \fBerror_wouldblock\fP; .br extern int \fBerror_again\fP; .br extern int \fBerror_pipe\fP; .br extern int \fBerror_perm\fP; .br extern int \fBerror_acces\fP; .SH DESCRIPTION UNIX syscalls provide detailed error codes in the .B errno variable. The .B error library provides portable names for a variety of possible .B errno values. .SH "SEE ALSO" error_str(3), error_temp(3) netqmail-1.06/warn-shsgr0000644000076400007640000000031306541176434014665 0ustar nelsonnelsonOops. Your getgroups() returned 0, and setgroups() failed; this means that I can't reliably do my shsgr test. Please either ``make'' as root or ``make'' while you're in one or more supplementary groups. netqmail-1.06/byte_cr.c0000644000076400007640000000050406541176434014444 0ustar nelsonnelson#include "byte.h" void byte_copyr(to,n,from) register char *to; register unsigned int n; register char *from; { to += n; from += n; for (;;) { if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; if (!n) return; *--to = *--from; --n; } } netqmail-1.06/PIC.rem2local0000644000076400007640000000246506541176434015076 0ustar nelsonnelsonqmail-smtpd Receive message by SMTP from another host: | MAIL FROM: | RCPT TO: | | Is $RELAYCLIENT set? No. | Is heaven.af.mil in rcpthosts? Yes. | Accept RCPT. V qmail-queue Store message safely on disk. Trigger qmail-send. | V qmail-send Look at envelope recipient, joe@heaven.af.mil. | Is heaven.af.mil in locals? Yes. | Deliver locally to joe@heaven.af.mil. V qmail-lspawn ./Mailbox | Look at mailbox name, joe. | Is joe listed in qmail-users? No. | Is there a joe account? Yes. | Is joe's uid nonzero? Yes. | Is ~joe visible to the qmailp user? Yes. | Is ~joe owned by joe? Yes. | Give control of the message to joe. | Run qmail-local. V qmail-local joe ~joe joe '' '' heaven.af.mil bill@irs.gov ./Mailbox Does ~joe/.qmail exist? No. Write message to ./Mailbox in mbox format. netqmail-1.06/conf-qmail0000644000076400007640000000101106541176434014614 0ustar nelsonnelson/var/qmail This is the qmail home directory. It must be a local directory, not shared among machines. This is where qmail queues all mail messages. The queue (except for bounce message contents) is crashproof, if the filesystem guarantees that single-byte writes are atomic and that directory operations are synchronous. These guarantees are provided by fixed-block filesystems such as UFS and by journaling filesystems. Under Linux, make sure that all mail-handling filesystems are mounted with synchronous metadata. netqmail-1.06/maildirmake.10000644000076400007640000000034006541176434015210 0ustar nelsonnelson.TH maildirmake 1 .SH NAME maildirmake \- create a maildir for incoming mail .SH SYNOPSIS .B maildirmake .I dir .SH DESCRIPTION .B maildirmake makes a new directory, .IR dir , in .B maildir format. .SH "SEE ALSO" maildir(5) netqmail-1.06/strerr.h0000644000076400007640000000644306541176434014353 0ustar nelsonnelson#ifndef STRERR_H #define STRERR_H struct strerr { struct strerr *who; char *x; char *y; char *z; } ; extern struct strerr strerr_sys; extern void strerr_sysinit(); extern char *strerr(); extern void strerr_warn(); extern void strerr_die(); #define STRERR(r,se,a) \ { se.who = 0; se.x = a; se.y = 0; se.z = 0; return r; } #define STRERR_SYS(r,se,a) \ { se.who = &strerr_sys; se.x = a; se.y = 0; se.z = 0; return r; } #define STRERR_SYS3(r,se,a,b,c) \ { se.who = &strerr_sys; se.x = a; se.y = b; se.z = c; return r; } #define strerr_warn6(x1,x2,x3,x4,x5,x6,se) \ strerr_warn((x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) #define strerr_warn5(x1,x2,x3,x4,x5,se) \ strerr_warn((x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) #define strerr_warn4(x1,x2,x3,x4,se) \ strerr_warn((x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_warn3(x1,x2,x3,se) \ strerr_warn((x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_warn2(x1,x2,se) \ strerr_warn((x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_warn1(x1,se) \ strerr_warn((x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_die6(e,x1,x2,x3,x4,x5,x6,se) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) (se)) #define strerr_die5(e,x1,x2,x3,x4,x5,se) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) (se)) #define strerr_die4(e,x1,x2,x3,x4,se) \ strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_die3(e,x1,x2,x3,se) \ strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_die2(e,x1,x2,se) \ strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_die1(e,x1,se) \ strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) (se)) #define strerr_die6sys(e,x1,x2,x3,x4,x5,x6) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),&strerr_sys) #define strerr_die5sys(e,x1,x2,x3,x4,x5) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,&strerr_sys) #define strerr_die4sys(e,x1,x2,x3,x4) \ strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,&strerr_sys) #define strerr_die3sys(e,x1,x2,x3) \ strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,&strerr_sys) #define strerr_die2sys(e,x1,x2) \ strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) #define strerr_die1sys(e,x1) \ strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,&strerr_sys) #define strerr_die6x(e,x1,x2,x3,x4,x5,x6) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(x6),(struct strerr *) 0) #define strerr_die5x(e,x1,x2,x3,x4,x5) \ strerr_die((e),(x1),(x2),(x3),(x4),(x5),(char *) 0,(struct strerr *) 0) #define strerr_die4x(e,x1,x2,x3,x4) \ strerr_die((e),(x1),(x2),(x3),(x4),(char *) 0,(char *) 0,(struct strerr *) 0) #define strerr_die3x(e,x1,x2,x3) \ strerr_die((e),(x1),(x2),(x3),(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) #define strerr_die2x(e,x1,x2) \ strerr_die((e),(x1),(x2),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) #define strerr_die1x(e,x1) \ strerr_die((e),(x1),(char *) 0,(char *) 0,(char *) 0,(char *) 0,(char *) 0,(struct strerr *) 0) #endif netqmail-1.06/wait.30000644000076400007640000000322506541176434013704 0ustar nelsonnelson.TH wait 3 .SH NAME wait \- check child process status .SH SYNTAX .B #include int \fBwait_nohang\fP(&\fIwstat\fR); .br int \fBwait_stop\fP(&\fIwstat\fR); .br int \fBwait_stopnohang\fP(&\fIwstat\fR); .br int \fBwait_pid\fP(&\fIwstat\fR,\fIpid\fR); int \fBwait_exitcode\fP(\fIwstat\fR); .br int \fBwait_crashed\fP(\fIwstat\fR); .br int \fBwait_stopped\fP(\fIwstat\fR); .br int \fBwait_stopsig\fP(\fIwstat\fR); int \fIpid\fR; .br int \fIwstat\fR; .SH DESCRIPTION .B wait_nohang looks for zombies (child processes that have exited). If it sees a zombie, it eliminates the zombie, puts the zombie's exit status into .IR wstat , and returns the zombie's process ID. If there are several zombies, .B wait_nohang picks one. If there are children but no zombies, .B wait_nohang returns 0. If there are no children, .B wait_nohang returns -1, setting .B errno appropriately. .B wait_stopnohang is similar to .BR wait_nohang , but it also looks for children that have stopped. .B wait_stop is similar to .BR wait_stopnohang , but if there are children it will pause waiting for one of them to stop or exit. .B wait_pid waits for child process .I pid to exit. It eliminates any zombie that shows up in the meantime, discarding the exit status. .B wait_stop and .B wait_pid retry upon .BR error_intr . .SH "STATUS PARSING" If the child stopped, .B wait_stopped is nonzero; .B wait_stopsig is the signal that caused the child to stop. If the child exited by crashing, .B wait_stopped is zero; .B wait_crashed is nonzero. If the child exited normally, .B wait_stopped is zero; .B wait_crashed is zero; and .B wait_exitcode is the child's exit code. .SH "SEE ALSO" wait(2), error(3) netqmail-1.06/qmail-qmtpd.80000644000076400007640000000112706541176434015172 0ustar nelsonnelson.TH qmail-qmtpd 8 .SH NAME qmail-qmtpd \- receive mail via QMTP .SH SYNOPSIS .B qmail-qmtpd .SH DESCRIPTION .B qmail-qmtpd receives mail messages via the Quick Mail Transfer Protocol (QMTP) and invokes .B qmail-queue to deposit them into the outgoing queue. .B qmail-qmtpd must be supplied several environment variables; see .BR tcp-environ(5) . .B qmail-qmtpd supports the .IR rcpthosts , .IR morercpthosts , .BR RELAYCLIENT , .IR databytes , and .B DATABYTES mechanisms described in .BR qmail-smtpd(8) . .SH "SEE ALSO" tcp-env(1), tcp-environ(5), qmail-control(5), qmail-queue(8), qmail-smtpd(8) netqmail-1.06/qmail.c0000644000076400007640000000701710724070436014117 0ustar nelsonnelson#include "substdio.h" #include "readwrite.h" #include "wait.h" #include "exit.h" #include "fork.h" #include "fd.h" #include "qmail.h" #include "auto_qmail.h" #include "env.h" static char *binqqargs[2] = { 0, 0 } ; static void setup_qqargs() { if(!binqqargs[0]) binqqargs[0] = env_get("QMAILQUEUE"); if(!binqqargs[0]) binqqargs[0] = "bin/qmail-queue"; } int qmail_open(qq) struct qmail *qq; { int pim[2]; int pie[2]; setup_qqargs(); if (pipe(pim) == -1) return -1; if (pipe(pie) == -1) { close(pim[0]); close(pim[1]); return -1; } switch(qq->pid = vfork()) { case -1: close(pim[0]); close(pim[1]); close(pie[0]); close(pie[1]); return -1; case 0: close(pim[1]); close(pie[1]); if (fd_move(0,pim[0]) == -1) _exit(120); if (fd_move(1,pie[0]) == -1) _exit(120); if (chdir(auto_qmail) == -1) _exit(61); execv(*binqqargs,binqqargs); _exit(120); } qq->fdm = pim[1]; close(pim[0]); qq->fde = pie[1]; close(pie[0]); substdio_fdbuf(&qq->ss,write,qq->fdm,qq->buf,sizeof(qq->buf)); qq->flagerr = 0; return 0; } unsigned long qmail_qp(qq) struct qmail *qq; { return qq->pid; } void qmail_fail(qq) struct qmail *qq; { qq->flagerr = 1; } void qmail_put(qq,s,len) struct qmail *qq; char *s; int len; { if (!qq->flagerr) if (substdio_put(&qq->ss,s,len) == -1) qq->flagerr = 1; } void qmail_puts(qq,s) struct qmail *qq; char *s; { if (!qq->flagerr) if (substdio_puts(&qq->ss,s) == -1) qq->flagerr = 1; } void qmail_from(qq,s) struct qmail *qq; char *s; { if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; close(qq->fdm); substdio_fdbuf(&qq->ss,write,qq->fde,qq->buf,sizeof(qq->buf)); qmail_put(qq,"F",1); qmail_puts(qq,s); qmail_put(qq,"",1); } void qmail_to(qq,s) struct qmail *qq; char *s; { qmail_put(qq,"T",1); qmail_puts(qq,s); qmail_put(qq,"",1); } char *qmail_close(qq) struct qmail *qq; { int wstat; int exitcode; qmail_put(qq,"",1); if (!qq->flagerr) if (substdio_flush(&qq->ss) == -1) qq->flagerr = 1; close(qq->fde); if (wait_pid(&wstat,qq->pid) != qq->pid) return "Zqq waitpid surprise (#4.3.0)"; if (wait_crashed(wstat)) return "Zqq crashed (#4.3.0)"; exitcode = wait_exitcode(wstat); switch(exitcode) { case 115: /* compatibility */ case 11: return "Denvelope address too long for qq (#5.1.3)"; case 31: return "Dmail server permanently rejected message (#5.3.0)"; case 51: return "Zqq out of memory (#4.3.0)"; case 52: return "Zqq timeout (#4.3.0)"; case 53: return "Zqq write error or disk full (#4.3.0)"; case 0: if (!qq->flagerr) return ""; /* fall through */ case 54: return "Zqq read error (#4.3.0)"; case 55: return "Zqq unable to read configuration (#4.3.0)"; case 56: return "Zqq trouble making network connection (#4.3.0)"; case 61: return "Zqq trouble in home directory (#4.3.0)"; case 63: case 64: case 65: case 66: case 62: return "Zqq trouble creating files in queue (#4.3.0)"; case 71: return "Zmail server temporarily rejected message (#4.3.0)"; case 72: return "Zconnection to mail server timed out (#4.4.1)"; case 73: return "Zconnection to mail server rejected (#4.4.1)"; case 74: return "Zcommunication with mail server failed (#4.4.2)"; case 91: /* fall through */ case 81: return "Zqq internal bug (#4.3.0)"; case 120: return "Zunable to exec qq (#4.3.0)"; default: if ((exitcode >= 11) && (exitcode <= 40)) return "Dqq permanent problem (#5.3.0)"; return "Zqq temporary problem (#4.3.0)"; } } netqmail-1.06/qsmhook.c0000644000076400007640000000661206541176434014504 0ustar nelsonnelson#include "fd.h" #include "stralloc.h" #include "readwrite.h" #include "sgetopt.h" #include "wait.h" #include "env.h" #include "byte.h" #include "str.h" #include "alloc.h" #include "exit.h" #include "fork.h" #include "case.h" #include "subfd.h" #include "error.h" #include "substdio.h" #include "sig.h" void die(e,s) int e; char *s; { substdio_putsflush(subfderr,s); _exit(e); } void die_usage() { die(100,"qsmhook: fatal: incorrect usage\n"); } void die_temp() { die(111,"qsmhook: fatal: temporary problem\n"); } void die_read() { die(111,"qsmhook: fatal: unable to read message\n"); } void die_badcmd() { die(100,"qsmhook: fatal: command not found\n"); } int flagrpline = 0; char *rpline; int flagufline = 1; char *ufline; int flagdtline = 0; char *dtline; char *host; char *sender; char *recip; stralloc newarg = {0}; substdio ssout; char outbuf[SUBSTDIO_OUTSIZE]; substdio ssin; char inbuf[SUBSTDIO_INSIZE]; void main(argc,argv) int argc; char **argv; { int pid; int wstat; int pi[2]; int opt; char **arg; char *x; int i; int flagesc; sig_pipeignore(); if (!(dtline = env_get("DTLINE"))) die_usage(); if (!(rpline = env_get("RPLINE"))) die_usage(); if (!(ufline = env_get("UFLINE"))) die_usage(); if (!(recip = env_get("LOCAL"))) die_usage(); if (!(host = env_get("HOST"))) die_usage(); if (!(sender = env_get("SENDER"))) die_usage(); while ((opt = getopt(argc,argv,"DFlMmnPsx:")) != opteof) switch(opt) { case 'D': case 'F': case 'M': break; /* be serious */ case 'l': flagdtline = 1; break; /* also return-receipt-to? blech */ case 'm': break; /* we only handle one recipient anyway */ case 'n': flagufline = 0; break; case 's': break; /* could call quote() otherwise, i suppose... */ case 'P': flagrpline = 1; break; case 'x': if (case_starts(recip,optarg)) recip += str_len(optarg); break; default: _exit(100); } argc -= optind; argv += optind; if (!*argv) die_usage(); for (arg = argv;x = *arg;++arg) { if (!stralloc_copys(&newarg,"")) die_temp(); flagesc = 0; for (i = 0;x[i];++i) if (flagesc) { switch(x[i]) { case '%': if (!stralloc_cats(&newarg,"%")) die_temp(); break; case 'g': if (!stralloc_cats(&newarg,sender)) die_temp(); break; case 'h': if (!stralloc_cats(&newarg,host)) die_temp(); break; case 'u': if (!stralloc_cats(&newarg,recip)) die_temp(); break; } flagesc = 0; } else if (x[i] == '%') flagesc = 1; else if (!stralloc_append(&newarg,&x[i])) die_temp(); if (!stralloc_0(&newarg)) die_temp(); i = str_len(newarg.s) + 1; if (!(x = alloc(i))) die_temp(); byte_copy(x,i,newarg.s); *arg = x; } if (pipe(pi) == -1) die_temp(); switch(pid = fork()) { case -1: die_temp(); case 0: close(pi[1]); if (fd_move(0,pi[0]) == -1) die_temp(); sig_pipedefault(); execvp(*argv,argv); if (error_temp(errno)) die_temp(); die_badcmd(); } close(pi[0]); substdio_fdbuf(&ssout,write,pi[1],outbuf,sizeof(outbuf)); substdio_fdbuf(&ssin,read,0,inbuf,sizeof(inbuf)); if (flagufline) substdio_bputs(&ssout,ufline); if (flagrpline) substdio_bputs(&ssout,rpline); if (flagdtline) substdio_bputs(&ssout,dtline); if (substdio_copy(&ssout,&ssin) == -2) die_read(); substdio_flush(&ssout); close(pi[1]); if (wait_pid(&wstat,pid) == -1) die_temp(); if (wait_crashed(wstat)) die_temp(); _exit(wait_exitcode(wstat)); } netqmail-1.06/conf-ld0000644000076400007640000000007606541176434014122 0ustar nelsonnelsoncc -s This will be used to link .o files into an executable. netqmail-1.06/prioq.c0000644000076400007640000000157106541176434014154 0ustar nelsonnelson#include "alloc.h" #include "gen_allocdefs.h" #include "prioq.h" GEN_ALLOC_readyplus(prioq,struct prioq_elt,p,len,a,i,n,x,100,prioq_readyplus) int prioq_insert(pq,pe) prioq *pq; struct prioq_elt *pe; { int i; int j; if (!prioq_readyplus(pq,1)) return 0; j = pq->len++; while (j) { i = (j - 1)/2; if (pq->p[i].dt <= pe->dt) break; pq->p[j] = pq->p[i]; j = i; } pq->p[j] = *pe; return 1; } int prioq_min(pq,pe) prioq *pq; struct prioq_elt *pe; { if (!pq->p) return 0; if (!pq->len) return 0; *pe = pq->p[0]; return 1; } void prioq_delmin(pq) prioq *pq; { int i; int j; int n; if (!pq->p) return; n = pq->len; if (!n) return; i = 0; --n; for (;;) { j = i + i + 2; if (j > n) break; if (pq->p[j - 1].dt <= pq->p[j].dt) --j; if (pq->p[n].dt <= pq->p[j].dt) break; pq->p[i] = pq->p[j]; i = j; } pq->p[i] = pq->p[n]; pq->len = n; } netqmail-1.06/newfield.c0000644000076400007640000000353206541176434014616 0ustar nelsonnelson#include "fmt.h" #include "datetime.h" #include "stralloc.h" #include "date822fmt.h" #include "newfield.h" /* "Date: 26 Sep 1995 04:46:53 -0000\n" */ stralloc newfield_date = {0}; /* "Message-ID: <19950926044653.12345.qmail@silverton.berkeley.edu>\n" */ stralloc newfield_msgid = {0}; static unsigned int datefmt(s,when) char *s; datetime_sec when; { unsigned int i; unsigned int len; struct datetime dt; datetime_tai(&dt,when); len = 0; i = fmt_str(s,"Date: "); len += i; if (s) s += i; i = date822fmt(s,&dt); len += i; if (s) s += i; return len; } static unsigned int msgidfmt(s,idhost,idhostlen,when) char *s; char *idhost; int idhostlen; datetime_sec when; { unsigned int i; unsigned int len; struct datetime dt; datetime_tai(&dt,when); len = 0; i = fmt_str(s,"Message-ID: <"); len += i; if (s) s += i; i = fmt_uint(s,dt.year + 1900); len += i; if (s) s += i; i = fmt_uint0(s,dt.mon + 1,2); len += i; if (s) s += i; i = fmt_uint0(s,dt.mday,2); len += i; if (s) s += i; i = fmt_uint0(s,dt.hour,2); len += i; if (s) s += i; i = fmt_uint0(s,dt.min,2); len += i; if (s) s += i; i = fmt_uint0(s,dt.sec,2); len += i; if (s) s += i; i = fmt_str(s,"."); len += i; if (s) s += i; i = fmt_uint(s,getpid()); len += i; if (s) s += i; i = fmt_str(s,".qmail@"); len += i; if (s) s += i; i = fmt_strn(s,idhost,idhostlen); len += i; if (s) s += i; i = fmt_str(s,">\n"); len += i; if (s) s += i; return len; } int newfield_datemake(when) datetime_sec when; { if (!stralloc_ready(&newfield_date,datefmt(FMT_LEN,when))) return 0; newfield_date.len = datefmt(newfield_date.s,when); return 1; } int newfield_msgidmake(idhost,idhostlen,when) char *idhost; int idhostlen; datetime_sec when; { if (!stralloc_ready(&newfield_msgid,msgidfmt(FMT_LEN,idhost,idhostlen,when))) return 0; newfield_msgid.len = msgidfmt(newfield_msgid.s,idhost,idhostlen,when); return 1; } netqmail-1.06/qmail-send.90000644000076400007640000001143706541176434015004 0ustar nelsonnelson.TH qmail-send 8 .SH NAME qmail-send \- deliver mail messages from the queue .SH SYNOPSIS .B qmail-send .SH DESCRIPTION .B qmail-send handles messages placed into the outgoing queue by .BR qmail-queue . It uses .B qmail-lspawn to deliver messages to local recipients and .B qmail-rspawn to deliver messages to remote recipients. If a message is temporarily undeliverable to one or more addresses, .B qmail-send leaves it in the queue and tries the addresses again later. .B qmail-send prints a readable record of its activities to descriptor 0. It writes commands to .BR qmail-lspawn , .BR qmail-rspawn , and .B qmail-clean on descriptors 1, 3, and 5, and reads responses from descriptors 2, 4, and 6. .B qmail-send is responsible for avoiding deadlock. If .B qmail-send receives a TERM signal, it will exit cleanly, after waiting (possibly more than a minute) for current delivery attempts to finish. If .B qmail-send receives an ALRM signal, it will reschedule every message in the queue for immediate delivery. .SH "CONTROL FILES" .B WARNING: .B qmail-send reads its control files only when it starts. If you change the control files, you must stop and restart .BR qmail-send . Exception: If .B qmail-send receives a HUP signal, it will reread .I locals and .IR virtualdomains . .TP 5 .I bouncefrom Bounce username. Default: .BR MAILER-DAEMON . .TP 5 .I bouncehost Bounce host. Default: .IR me , if that is supplied; otherwise the literal name .BR bouncehost , which is probably not what you want. If a message is permanently undeliverable, .B qmail-send sends a .B single-bounce notice back to the message's envelope sender. The notice is .B From: \fIbouncefrom\fB@\fIbouncehost\fR, although its envelope sender is empty. .TP 5 .I concurrencylocal Maximum number of simultaneous local delivery attempts. Default: 10. If 0, local deliveries will be put on hold. .I concurrencylocal is limited at compile time to SPAWN. .TP 5 .I concurrencyremote Maximum number of simultaneous remote delivery attempts. Default: 20. If 0, remote deliveries will be put on hold. .I concurrencyremote is limited at compile time to SPAWN. .TP 5 .I doublebouncehost Double-bounce host. Default: .IR me , if that is supplied; otherwise the literal name .BR doublebouncehost , which is probably not what you want. .TP 5 .I doublebounceto User to receive double-bounces. Default: .BR postmaster . If a single-bounce notice is permanently undeliverable, .B qmail-send sends a .B double-bounce notice to .IR doublebounceto\fB@\fIdoublebouncehost . (If that bounces, .B qmail-send gives up.) .TP 5 .I envnoathost Presumed domain name for addresses without @ signs. Default: .IR me , if that is supplied; otherwise the literal name .BR envnoathost , which is probably not what you want. If .B qmail-send sees an envelope recipient address without an @ sign, it appends .B @\fIenvnoathost\fR. .TP 5 .I locals List of domain names that the current host receives mail for, one per line. Default: .IR me , if that is supplied; otherwise .B qmail-send refuses to run. An address .I user@domain is considered local if .I domain is listed in .IR locals . .TP 5 .I percenthack List of domain names where the percent hack is applied. If .I domain is listed in .IR percenthack , any address of the form .I user%fqdn@domain is rewritten as .IR user@fqdn . .I user may contain %, so the percent hack may be applied repeatedly. .B qmail-send handles .I percenthack before .IR locals . .TP 5 .I queuelifetime Number of seconds a message can stay in the queue. Default: 604800 (one week). After this time expires, .B qmail-send will try the message once more, but it will treat any temporary delivery failures as permanent failures. .TP 5 .I virtualdomains List of virtual users or domains, one per line. A virtual user has the form .IR user\fB@\fIdomain\fB:\fIprepend , without any extra spaces. When .B qmail-send sees the recipient address .IR user\fB@\fIdomain , it converts it to .I prepend\fB-\fIuser\fB@\fIdomain and treats it as local. A virtual domain has the form .IR domain\fB:\fIprepend . It applies to any recipient address at .IR domain . For example, if .EX nowhere.mil:joeBREAKfoo .EE is in .IR virtualdomains , and a message arrives for .BR info@nowhere.mil , .B qmail-send will rewrite the recipient address as .B joeBREAKfoo-info@nowhere.mil and deliver the message locally. .I virtualdomains may contain wildcards: .EX .fax:uucpBREAKfax :aliasBREAKcatchall .nowhere.mil:joeBREAKfoo-host .EE .I virtualdomains may also contain exceptions: an empty .I prepend means that .I domain is not a virtual domain. .B qmail-send handles .I virtualdomains after .IR locals : if a domain is listed in .IR locals , .I virtualdomains does not apply. .SH "SEE ALSO" nice(1), addresses(5), envelopes(5), qmail-control(5), qmail-log(5), qmail-queue(8), qmail-clean(8), qmail-lspawn(8), qmail-rspawn(8) netqmail-1.06/error_temp.30000644000076400007640000000105106541176434015111 0ustar nelsonnelson.TH error_temp 3 .SH NAME error_temp \- identify soft syscall error codes .SH SYNTAX .B #include int \fBerror_temp\fP(\fIe\fR); int \fIe\fR; .SH DESCRIPTION .B error_temp returns 1 if syscall error code .I e is a soft error, 0 if it is a hard error. Normally .I e is .BR errno . A hard error is persistent: file not found, read-only file system, symbolic link loop, etc. A soft error is usually transient: out of memory, out of disk space, I/O error, disk quota exceeded, connection refused, host unreachable, etc. .SH "SEE ALSO" error(3) netqmail-1.06/sgetopt.c0000644000076400007640000000237506541176434014512 0ustar nelsonnelson/* sgetopt.c, sgetopt.h: (yet another) improved getopt clone, outer layer D. J. Bernstein, djb@pobox.com. Depends on subgetopt.h, substdio.h, subfd.h. No system requirements. 19970208: Cleanups. 931201: Baseline. No known patent problems. Documentation in sgetopt.3. */ #include "substdio.h" #include "subfd.h" #define SGETOPTNOSHORT #include "sgetopt.h" #define SUBGETOPTNOSHORT #include "subgetopt.h" #define getopt sgetoptmine #define optind subgetoptind #define opterr sgetopterr #define optproblem subgetoptproblem #define optprogname sgetoptprogname int opterr = 1; char *optprogname = 0; int getopt(argc,argv,opts) int argc; char **argv; char *opts; { int c; char *s; if (!optprogname) { optprogname = *argv; if (!optprogname) optprogname = ""; for (s = optprogname;*s;++s) if (*s == '/') optprogname = s + 1; } c = subgetopt(argc,argv,opts); if (opterr) if (c == '?') { char chp[2]; chp[0] = optproblem; chp[1] = '\n'; substdio_puts(subfderr,optprogname); if (argv[optind] && (optind < argc)) substdio_puts(subfderr,": illegal option -- "); else substdio_puts(subfderr,": option requires an argument -- "); substdio_put(subfderr,chp,2); substdio_flush(subfderr); } return c; } netqmail-1.06/sig_alarm.c0000644000076400007640000000037406541176434014760 0ustar nelsonnelson#include #include "sig.h" void sig_alarmblock() { sig_block(SIGALRM); } void sig_alarmunblock() { sig_unblock(SIGALRM); } void sig_alarmcatch(f) void (*f)(); { sig_catch(SIGALRM,f); } void sig_alarmdefault() { sig_catch(SIGALRM,SIG_DFL); }