: '---------- cut here ----------' PATH=:/bin:/usr/bin:/usr/ucb: : : SHAR archive format. : Archive created Mon Dec 11 21:33:41 PST 1989 by allyn@odin.ucsd.edu : to unbundle, "sh" this file -- do not use csh. : echo x - README sed 's/^X//' > README <<'!File!Separator!' Xdeliver -- Mail Delivery Program X XThis program is a delivery agent designed for use with sendmail. XIt is the local mailer program that actually delivers mail to the user Xmailboxes. The AT&T version of /bin/mail, which normally handles mail Xdelivery on System V, does not interact properly with sendmail, and the XWollongong Group does not distribute one. X XThe recommended use is to link this program to /bin/mail and /bin/rmail. In Xthis way, all mail will go through sendmail. The only drawback to this Xapproach is that some users actually use /bin/mail to read mail, and this Xprogram does not include that functionality. X XTo compile the program, simply type "make". to install it, type X"make install" as root. The program goes in /usr/local/lib/deliver Xand is automatically linked to /bin/rmail. The link to /bin/mail must Xbe performed manually, if desired. Type the commands X"mv /bin/mail /bin/omail; ln /bin/rmail /bin/mail". The original AT&T Xversion of /bin/mail is saved in /bin/omail. (If /usr/local/lib and /bin Xare not on the same filesystem, the links will fail and you'll have to copy Xthe file and set the permissions yourself). X Xthis mailer line should be placed in your sendmail.cf file: XMlocal, P=/usr/local/lib/deliver, F=lsDFMm, S=10, R=20, A=mail -d $u X XIncidentally, I have found two problems with the Wollongong Group's Xversion of sendmail. Do not freeze the configuration file with the Xcommand "/usr/lib/sendmail -bz" or things stop working (make sure the Xfile /usr/lib/sendmail.fc does not exist). Also, the alias database Xis never saved properly. It is rebuilt each time sendmail is run. XSo keep the /usr/lib/aliases file short. X XNeither of these problems are present in my port of sendmail 5.58 Xavailable on ucsd.edu in u3b2/sendmail.cpio.Z. X XGood Luck! X XAllyn Fratkin Xallyn@cs.ucsd.edu !File!Separator! newsize="`wc -c < README`" if test $newsize -ne 1825 ; then echo Error: file is not the correct length. Should be 1825, is $newsize fi ls -l README echo x - Makefile sed 's/^X//' > Makefile <<'!File!Separator!' XSHELL=/bin/sh XLOCK=lock.o XTARGET=/usr/local/lib/deliver X Xmail: mail.o $(LOCK) local.o getmsg.o X $(CC) $(CFLAGS) mail.o getmsg.o $(LOCK) local.o -o mail X Xclean: X rm -f *.o mail X Xinstall: X cp mail $(TARGET) X chown root $(TARGET) X chgrp mail $(TARGET) X chmod 2751 $(TARGET) X rm -f /bin/rmail X ln $(TARGET) /bin/rmail !File!Separator! newsize="`wc -c < Makefile`" if test $newsize -ne 314 ; then echo Error: file is not the correct length. Should be 314, is $newsize fi ls -l Makefile echo x - getmsg.c sed 's/^X//' > getmsg.c <<'!File!Separator!' X/* X * $Header: getmsg.c,v 1.3 86/04/14 17:22:45 allyn Exp $ X * X * This file was known as getfrom.c in pre-sendmail versions (up to 1.3) X * X * $Log: getfrom.c,v $ X * Revision 1.3 86/04/14 17:22:45 allyn X * Last pre-sendmail version. X * X * Revision 1.2 85/04/23 11:07:17 allyn X * Minor modifications to production system. X * X * Revision 1.1 85/03/07 16:26:57 allyn X * Initial revision X * X */ X X#include "mail.h" X#define rindex strrchr X X/* X * return 1 if p begins with target X */ Xprefix(p,target) Xregister char *target, *p; X{ X while(*target) if(*p++ != *target++) return(0); X return(1); X} X X/* X * search for an occurence of str in buf X */ Xsearch(buf, str) Xchar *buf, *str; X{ X register int i, j, l; X X l = strlen(buf); X j = strlen(str); X if(l == 0 || j == 0 || j > l) return(0); X l = l - j + 1; X for(i=0; iFrom " lines X * into a single line, and inserting a ">" in front of any line X * in the body that begins "From ". Return the sender. X */ Xchar * Xgetmsg(fpin, fpout) Xregister FILE *fpin, *fpout; X{ X int i, j, first; X char line[LINE]; X static char frombuf[LINE]; X long l; X X /* dump any beginning junk in the message. there shouldn't be any */ X do { X fgets(line, sizeof(line), fpin); X } while (!feof(fpin) && !ferror(fpin) && !prefix(line,"From ")); X X if (feof(fpin) || ferror(fpin)) X return(NULL); X X if (i = search(line, "remote from ")) { X copy2(&line[i-1+12], frombuf); X strcat(frombuf, "!"); X } X X copy2(line+5, frombuf+strlen(frombuf)); X fgets(line, sizeof(line), fpin); X first = 1; X while (prefix(line, ">From ") != NULL) { X if (first) X j = first = 0; X else X while((j = rindex(frombuf,'!')) == 0) X strcat(frombuf, "!"); X if (i = search(line, "remote from ")) { X copy2(&line[i-1+12], &frombuf[j]); X strcat(frombuf, "!"); X } X copy2(line+6, &frombuf[strlen(frombuf)]); X fgets(line, sizeof(line), fpin); X } X time(&l); X fprintf(fpout, "From %s %s", frombuf, ctime(&l)); X fputs(line, fpout); X while (fgets(line, sizeof(line), fpin) != NULL) { X if (prefix(line, "From ") != NULL) X putc('>', fpout); X fputs(line, fpout); X } X fflush(fpout); X return(frombuf); X} !File!Separator! newsize="`wc -c < getmsg.c`" if test $newsize -ne 2679 ; then echo Error: file is not the correct length. Should be 2679, is $newsize fi ls -l getmsg.c echo x - local.c sed 's/^X//' > local.c <<'!File!Separator!' X/* X * $Header: local.c,v 1.4 86/04/14 17:23:00 allyn Exp $ X * X * $Log: local.c,v $ X * Revision 1.4 86/04/14 17:23:00 allyn X * Last pre-sendmail version. X * X * Revision 1.3 85/05/29 17:05:59 allyn X * A little tuning of local delivery. X * X * Revision 1.2 85/04/23 11:07:25 allyn X * Minor modifications to production system. X * X * Revision 1.1 85/03/07 16:27:45 allyn X * Initial revision X * X */ X X#include "mail.h" X#include X#include X Xlocal_deliver(fp, user) Xchar *user; XFILE *fp; X{ X register FILE *mailfile; X register int c; X char mailbox[64]; X struct passwd *pw, *getpwnam(); X X if ((pw = getpwnam(user)) == NULL) { X fprintf(stderr, "mail: no local user \"%s\"\n", user); X errors++; X return(-1); X } X sprintf(mailbox,"%s/%s", SPOOLDIR, user); X lock(mailbox); X rewind(fp); X if ((mailfile = fopen(mailbox, "a")) == NULL) { X fprintf(stderr, "mail: can't open mailbox \"%s\"\n", mailbox); X errors++; X return(-1); X } X lock(mailbox); /* we have to make sure */ X (void) fseek(mailfile, 0L, 2); X (void) chmod(mailbox, BOX_MODE); X (void) chown(mailbox, pw->pw_uid, getegid()); X while ((c = getc(fp)) != EOF) X putc(c, mailfile); X putc('\n', mailfile); X fclose(mailfile); X unlock(); X return(0); X} !File!Separator! newsize="`wc -c < local.c`" if test $newsize -ne 1222 ; then echo Error: file is not the correct length. Should be 1222, is $newsize fi ls -l local.c echo x - lock.c sed 's/^X//' > lock.c <<'!File!Separator!' X#ifndef lint Xstatic char sccsid[] = "@(#)lock.c 2.4 (Berkeley) 8/11/83"; X#endif X X/* X * A mailing program. X * X * Stuff to do version 7 style locking. X */ X X#include X#include X X#define NOSTR ((char *) 0) /* Null string pointer */ X Xchar *maillock = ".lock"; /* Lock suffix for mailname */ Xchar *lockname = "/usr/mail/tmXXXXXX"; Xchar locktmp[30]; /* Usable lock temporary */ Xstatic char curlock[50]; /* Last used name of lock */ Xstatic int locked; /* To note that we locked it */ X X/* X * Lock the specified mail file by setting the file mailfile.lock. X * We must, of course, be careful to unlink the lock file by a call X * to unlock before we stop. The algorithm used here is to see if X * the lock exists, and if it does, to check its modify time. If it X * is older than 5 minutes, we assume error and set our own file. X * Otherwise, we wait for 5 seconds and try again. X */ X Xlock(file) Xchar *file; X{ X register int f; X struct stat sbuf; X long curtime; X X if (file == NOSTR) { X printf("Locked = %d\n", locked); X return(0); X } X if (locked) X return(0); X strcpy(curlock, file); X strcat(curlock, maillock); X strcpy(locktmp, lockname); X mktemp(locktmp); X unlink(locktmp); X for (;;) { X f = lock1(locktmp, curlock); X if (f == 0) { X locked = 1; X return(0); X } X if (stat(curlock, &sbuf) < 0) X return(0); X time(&curtime); X if (curtime < sbuf.st_ctime + 300) { X sleep(5); X continue; X } X unlink(curlock); X } X} X X/* X * Remove the mail lock, and note that we no longer X * have it locked. X */ X Xunlock() X{ X X if (locked) { X unlink(curlock); X locked = 0; X } X} X X/* X * Attempt to set the lock by creating the temporary file, X * then doing a link/unlink. If it fails, return -1 else 0 X */ X Xlock1(tempfile, name) X char tempfile[], name[]; X{ X register int fd; X X fd = creat(tempfile, 0); X if (fd < 0) X return(-1); X close(fd); X if (link(tempfile, name) < 0) { X unlink(tempfile); X return(-1); X } X unlink(tempfile); X return(0); X} !File!Separator! newsize="`wc -c < lock.c`" if test $newsize -ne 1959 ; then echo Error: file is not the correct length. Should be 1959, is $newsize fi ls -l lock.c echo x - mail.c sed 's/^X//' > mail.c <<'!File!Separator!' X/* X * mail: X * a simple and quick mail sending program for PC/IX. X * Allyn Fratkin 28-Feb-85 X * X * This simple and quick mail program has outlived its usefulness. X * It is now becoming a front-end for sendmail. X * Allyn Fratkin 14-Apr-86 X */ X X#ifndef lint Xstatic char rcsid[] = X "$Header: mail.c,v 1.5 86/04/14 17:23:22 allyn Exp $"; X#endif X X/* X * $Log: mail.c,v $ X * Revision 1.5 86/04/14 17:23:22 allyn X * Last pre-sendmail version. X * X * Revision 1.4 85/06/14 13:07:33 allyn X * Changed remote_deliver parameters to include the number of users to X * send to. X * X * Revision 1.3 85/05/29 17:06:35 allyn X * Small modifications to main procedure. X * X * X * Revision 1.2 85/04/23 11:07:53 allyn X * Minor modifications to production system. X * X * Revision 1.1 85/03/07 16:28:37 allyn X * Initial revision X * X */ X X#include X#include X#include X#include "sysexits.h" X#include "mail.h" X Xextern char *strchr(), *strrchr(); Xextern void *malloc(); Xchar *getuser(); X X#define local(user) (strchr(user, '!') == NULL) X Xchar *templates[] = { X "/usr/spool/mqueue", X "/spool/mqueue", X "/tmp", X 0, X}; X Xmain(argc,argv) Xint argc; Xchar **argv; X{ X char *sender, *tempname, *temp(); X char **avect, **ap; X extern char *getmsg(); X X if (argc == 1) { X fprintf(stderr, "usage: mail \n"); X fprintf(stderr, "use the command \"mailx\" to read mail.\n"); X exit(EX_USAGE); X } X X if (strrchr(argv[0], '/')) { X char *t; X X t = strrchr(argv[0], '/') + 1; X rmail = (*t == 'r'); X } X else X rmail = (**argv == 'r'); X X /* if -d flag is given we should deliver locally */ X if (!rmail) X if (strcmp(argv[1], "-d") != 0) { X argv[0] = "-sendmail"; X execv(SENDMAIL, argv); X perror(SENDMAIL); X exit(EX_UNAVAILABLE); X } X else X argv++; X X tempname = temp("data"); X if ((tmp = fopen(tempname, "w+")) == NULL) X exit(EX_TEMPFAIL); X (void) unlink(tempname); X X if ((sender = getmsg(stdin, tmp)) == NULL) X exit(EX_DATAERR); X X rewind(tmp); X X if (rmail) { X (void) close(0); X (void) dup(fileno(tmp)); X (void) close(fileno(tmp)); X X avect = (char **) malloc((unsigned int)(argc + 4) * sizeof(char *)); X avect[0] = "-sendmail"; X avect[1] = "-f"; X avect[2] = sender; X X ap = &avect[3]; X while (*(++argv)) X *ap++ = *argv; X *ap = NULL; X X (void) execv(SENDMAIL, avect); X perror(SENDMAIL); X exit(EX_UNAVAILABLE); X } X X /* deliver messages */ X X while (*(++argv)) X local_deliver(tmp, *argv); X X fclose(tmp); X exit(errors ? errors : EX_OK); X} X X/* X * return a temp file name with the specified "type" X */ Xchar * Xtemp(s) Xchar *s; X{ X char *x, *m, **tplate, name[40], *mktemp(); X X for (tplate = templates; **tplate; tplate++) { X if (access(*tplate, A_EXIST) >= 0) X break; X } X if (!*tplate) X exit(EX_UNAVAILABLE); X sprintf(name, "%s/%sXXXXXX", *tplate, s); X x = mktemp(name); X m = (char *) malloc(strlen(x) + 1); X if (!m) X exit(EX_TEMPFAIL); X strcpy(m, x); X X return(m); X} !File!Separator! newsize="`wc -c < mail.c`" if test $newsize -ne 2917 ; then echo Error: file is not the correct length. Should be 2917, is $newsize fi ls -l mail.c echo x - mail.h sed 's/^X//' > mail.h <<'!File!Separator!' X#include X X#define LINE 512 X#define BOX_MODE 0620 X#define SPOOLDIR "/usr/mail" X#define SENDMAIL "/usr/lib/sendmail" X X#define A_EXIST 0 X Xint errors, rmail; XFILE *tmp; X Xextern int errno; !File!Separator! newsize="`wc -c < mail.h`" if test $newsize -ne 196 ; then echo Error: file is not the correct length. Should be 196, is $newsize fi ls -l mail.h echo x - sysexits.h sed 's/^X//' > sysexits.h <<'!File!Separator!' X/* X * Copyright (c) 1987 Regents of the University of California. X * All rights reserved. X * X * Redistribution and use in source and binary forms are permitted X * provided that this notice is preserved and that due credit is given X * to the University of California at Berkeley. The name of the University X * may not be used to endorse or promote products derived from this X * software without specific prior written permission. This software X * is provided ``as is'' without express or implied warranty. X * X * @(#)sysexits.h 4.4 (Berkeley) 3/24/88 X */ X X/* X** SYSEXITS.H -- Exit status codes for system programs. X** X** This include file attempts to categorize possible error X** exit statuses for system programs, notably delivermail X** and the Berkeley network. X** X** Error numbers begin at EX__BASE to reduce the possibility of X** clashing with other exit statuses that random programs may X** already return. The meaning of the codes is approximately X** as follows: X** X** EX_USAGE -- The command was used incorrectly, e.g., with X** the wrong number of arguments, a bad flag, a bad X** syntax in a parameter, or whatever. X** EX_DATAERR -- The input data was incorrect in some way. X** This should only be used for user's data & not X** system files. X** EX_NOINPUT -- An input file (not a system file) did not X** exist or was not readable. This could also include X** errors like "No message" to a mailer (if it cared X** to catch it). X** EX_NOUSER -- The user specified did not exist. This might X** be used for mail addresses or remote logins. X** EX_NOHOST -- The host specified did not exist. This is used X** in mail addresses or network requests. X** EX_UNAVAILABLE -- A service is unavailable. This can occur X** if a support program or file does not exist. This X** can also be used as a catchall message when something X** you wanted to do doesn't work, but you don't know X** why. X** EX_SOFTWARE -- An internal software error has been detected. X** This should be limited to non-operating system related X** errors as possible. X** EX_OSERR -- An operating system error has been detected. X** This is intended to be used for such things as "cannot X** fork", "cannot create pipe", or the like. It includes X** things like getuid returning a user that does not X** exist in the passwd file. X** EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp, X** etc.) does not exist, cannot be opened, or has some X** sort of error (e.g., syntax error). X** EX_CANTCREAT -- A (user specified) output file cannot be X** created. X** EX_IOERR -- An error occurred while doing I/O on some file. X** EX_TEMPFAIL -- temporary failure, indicating something that X** is not really an error. In sendmail, this means X** that a mailer (e.g.) could not create a connection, X** and the request should be reattempted later. X** EX_PROTOCOL -- the remote system returned something that X** was "not possible" during a protocol exchange. X** EX_NOPERM -- You did not have sufficient permission to X** perform the operation. This is not intended for X** file system problems, which should use NOINPUT or X** CANTCREAT, but rather for higher level permissions. X** For example, kre uses this to restrict who students X** can send mail to. X** X** Maintained by Eric Allman (eric@berkeley, ucbvax!eric) -- X** please mail changes to me. X** X** @(#)sysexits.h 4.4 3/24/88 X*/ X X# define EX_OK 0 /* successful termination */ X X# define EX__BASE 64 /* base value for error messages */ X X# define EX_USAGE 64 /* command line usage error */ X# define EX_DATAERR 65 /* data format error */ X# define EX_NOINPUT 66 /* cannot open input */ X# define EX_NOUSER 67 /* addressee unknown */ X# define EX_NOHOST 68 /* host name unknown */ X# define EX_UNAVAILABLE 69 /* service unavailable */ X# define EX_SOFTWARE 70 /* internal software error */ X# define EX_OSERR 71 /* system error (e.g., can't fork) */ X# define EX_OSFILE 72 /* critical OS file missing */ X# define EX_CANTCREAT 73 /* can't create (user) output file */ X# define EX_IOERR 74 /* input/output error */ X# define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */ X# define EX_PROTOCOL 76 /* remote error in protocol */ X# define EX_NOPERM 77 /* permission denied */ X# define EX_CONFIG 78 /* configuration error */ !File!Separator! newsize="`wc -c < sysexits.h`" if test $newsize -ne 4258 ; then echo Error: file is not the correct length. Should be 4258, is $newsize fi ls -l sysexits.h exit 0