From: Bill Joy Date: Fri, 31 Oct 1980 14:39:59 +0000 (-0800) Subject: BSD 4 development X-Git-Tag: BSD-4~103 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/e43191cd168026c607c3506a5fec0dd77f0de1a0 BSD 4 development Work on file usr/src/cmd/delivermail/TO_BE_DONE Work on file usr/src/cmd/delivermail/alias.c.save Work on file usr/src/cmd/delivermail/aliases.5 Work on file usr/src/cmd/delivermail/arpa-mailer.8 Work on file usr/src/cmd/delivermail/delivermail.8 Work on file usr/src/cmd/delivermail/mail-dm.c Work on file usr/src/cmd/delivermail/userinfo.5 Work on file usr/src/cmd/delivermail/v6-mail.c Synthesized-from: CSRG//cd1/4.0 --- diff --git a/usr/src/cmd/delivermail/TO_BE_DONE b/usr/src/cmd/delivermail/TO_BE_DONE new file mode 100644 index 0000000000..aa04f22f63 --- /dev/null +++ b/usr/src/cmd/delivermail/TO_BE_DONE @@ -0,0 +1,22 @@ + ** (Someday) collect all names that are local in advance, and send + them all off to /bin/mail at once -- fork before sending so + that we can return status quickly. + + *** Handle :Include: specifications. + + * (Somehow) have "From" person modified so that if an alias exists + for the person, it will appear post-aliased rather than pre-aliased, + especially (perhaps only?) in ARPANET mail. For example, if there + exists an alias "fabry->cory:fabry", then if mail comes in from + "cory:fabry", make it appear as though it were from "fabry". + + * Do aliasing on mail being returned also (?). + + **** Allow "" "at" "" as three separate parameters. + + *** Put host aliasing into the users file, e.g., + vax135!:research!vax135! + + ***** Change sendto & aliasdbm to know about quoted commas. + Currently, quoted commas delimit aliases when they should be + ignored. diff --git a/usr/src/cmd/delivermail/alias.c.save b/usr/src/cmd/delivermail/alias.c.save new file mode 100644 index 0000000000..b9d6cda496 --- /dev/null +++ b/usr/src/cmd/delivermail/alias.c.save @@ -0,0 +1,279 @@ +# include +# include +# include +# include "delivermail.h" + +/* +** ALIAS -- Compute aliases. +** +** Scans the file /usr/lib/mailaliases for a set of aliases. +** If found, it arranges to deliver to them by inserting the +** new names onto the SendQ queue. +** +** Parameters: +** none +** +** Returns: +** none +** +** Side Effects: +** Aliases found on SendQ are removed and put onto +** AliasQ; replacements are added to SendQ. This is +** done until no such replacement occurs. +** +** Defined Constants: +** MAXRCRSN -- the maximum recursion depth. +** ALIASFILE -- the pathname of the alias file. +** +** Requires: +** fopen (stdio) +** fgets (stdio) +** rewind (stdio) +** isspace (sys) +** printf (sys) +** deliver +** +** Called By: +** deliver +** +** Files: +** /usr/lib/mailaliases -- the mail aliases. +** +** Notes: +** If NoAlias (the "-n" flag) is set, no aliasing is +** done. +** +** Deficiencies: +** It should complain about names that are aliased to +** nothing. +** It is unsophisticated about line overflows. +** It should probably take either the ARPANET sndmsg +** format for aliases, or read Mail files and +** pick out 'alias' commands. +** +** History: +** 12/27/79 -- written. +*/ + + +# define ALIASFILE "/usr/lib/mailaliases" +# define MAXRCRSN 10 + + +alias() +{ + register addrq *q; + FILE *af; + char line[MAXLINE+1]; + register char *p; + register char *u; + extern int errno; + int didalias; + int gotmatch; + + if (NoAlias) + return (0); + if (Debug) + printf("--- alias ---\n"); + + /* open alias file if not already open */ + if (Debug && (af = fopen("mailaliases", "r")) != NULL) + printf(" [using local alias file]\n"); + else if ((af = fopen(ALIASFILE, "r")) == NULL) + { + if (Debug) + printf("Can't open %s\n", ALIASFILE); + errno = 0; + return; + } + + /* + ** Scan alias file. + ** If we find any user that any line matches any user, we + ** will send to the line rather than to the user. + */ + + didalias = TRUE; + while (didalias) + { + didalias = FALSE; + gotmatch = FALSE; + rewind(af); + while (fgets(line, sizeof line, af) != NULL) + { + /* check for continuation lines */ + if (isspace(line[0])) + { + if (gotmatch) + { + if (Debug) + printf(" ... also aliased to %s", line); + sendto(line); + } + continue; + } + gotmatch = FALSE; + /* comments begin with `#' */ + if (line[0] == '#') + continue; + p = NULL; + for (q = &SendQ; (q = nxtinq(q)) != NULL; ) + { + if ((p = matchalias(valueq(q), line)) != NULL) + break; + } + + if (p != NULL) + { + /* + ** Match on Alias. + ** Deliver to the target list. + ** Remove the alias from the send queue + ** and put it on the Alias queue. + */ + + if (Debug) + printf("%s aliased to %s", valueq(q), p); + tkoffq(q, &SendQ); + putonq(q, &AliasQ); + didalias++; + gotmatch++; + sendto(p); + } + } + } + fclose(af); +} + /* +** MATCHALIAS -- Match name against alias. +** +** The alias is a full alias line, in the format: +** pseudonym:name1,name2,name3,... +** This routine just matches against the pseudonym. +** +** Parameters: +** user -- the user to match against. +** line -- the alias line. +** +** Returns: +** A pointer to the first character after the colon on +** a match. +** NULL otherwise. +** +** Side Effects: +** none +** +** Requires: +** none +** +** Called By: +** alias +** +** History: +** 1/11/80 -- broken from alias +*/ + +matchalias(user, line) + register char *user; + register char *line; +{ + for (; *user != '\0' && *line == *user; line++, user++) + continue; + while (isspace(*line)) + line++; + if (*user == '\0' && *line == ':') + return (++line); + return (NULL); +} + /* +** FORWARD -- Try to forward mail +** +** This is similar but not identical to aliasing. Local +** users may put a file ".userinfo" in their home directory +** saying what account(s) they would like their mail +** forwarded to. This file looks a lot like ARPANET +** mail headers, i.e., each line is +** field-name: value +** This routine is looking for the field "forward-to". +** +** Parameters: +** user -- the name of the user who's mail we +** would like to forward to. +** +** Returns: +** NULL -- we arranged to forward this somewhere, +** so don't send it yourself. +** else -- send it to whoever this returns. +** +** Side Effects: +** New names are added to SendQ. +** +** Requires: +** setpwent (sys) +** getpwname (sys) +** strcpy (sys) +** strcat (sys) +** fopen (sys) +** fgets (sys) +** matchhdr +** sendto +** fclose (sys) +** +** Called By: +** recipient +** +** History: +** 1/23/80 -- written. +*/ + +char * +forward(user) + char *user; +{ + register struct passwd *pw; + char buf[MAXLINE]; + register char *p; + register FILE *uf; + extern struct passwd *getpwnam(); + extern char *matchhdr(); + + /* + ** Find and open the user's .userinfo file. + */ + + setpwent(); + if ((pw = getpwnam(user)) == NULL) + return (user); + strcpy(buf, pw->pw_dir); + strcat(buf, "/.userinfo"); + if ((uf = fopen(buf, "r")) == NULL) + return (user); + + /* + ** Look for forward-to: field. + */ + + while (fgets(buf, sizeof buf, uf) != NULL) + { + if ((p = matchhdr(buf, "forward-to")) == NULL) + continue; + + /* + ** We have a foward entry. + ** Send to the list + */ + + fclose(uf); + if (Debug) + printf("--%s", buf); + sendto(p); + return (NULL); + } + + /* + ** No match -- send to the original user. + */ + + fclose(uf); + return (user); +} diff --git a/usr/src/cmd/delivermail/aliases.5 b/usr/src/cmd/delivermail/aliases.5 new file mode 100644 index 0000000000..f1bc0d65ba --- /dev/null +++ b/usr/src/cmd/delivermail/aliases.5 @@ -0,0 +1,33 @@ +.TH ALIASES 5 12/31/79 +.SH NAME +aliases \- aliases file for delivermail +.SH SYNOPSIS +/usr/lib/aliases +.SH DESCRIPTION +This file describes user id aliases +that will be used +by +.I /etc/delivermail. +It is formatted as a series of lines +of the form +.in +0.5i +name:addr1,addr2,...addrn +.in +The +.I name +is the name to alias, +and the +.I addri +are the addresses to send the message to. +Lines beginning with white space +are continuation lines. +Lines beginning with `\|#\|' +are comments. +.PP +Aliasing occurs only on local names. +Loops can not occur, +since no message will be sent to any person +more than once. +.SH SEE\ ALSO +delivermail(8) +.SH BUGS diff --git a/usr/src/cmd/delivermail/arpa-mailer.8 b/usr/src/cmd/delivermail/arpa-mailer.8 new file mode 100644 index 0000000000..92270f3bc0 --- /dev/null +++ b/usr/src/cmd/delivermail/arpa-mailer.8 @@ -0,0 +1,38 @@ +.TH ARPA-MAILER 8 12/31/79 +.SH NAME +arpa-mailer \- deliver mail to the +.SM ARPANET +.SH SYNOPSIS +/usr/lib/mailers/arpa +.I from-address +.I to-host +.I to-user +.SH DESCRIPTION +.I Arpa-mailer +queues the letter found on its standard input +for delivery to the host and user specified. +The actual delivery will be performed by the +.SM ARPANET +mailer daemon. +.PP +If the letter does not appear to have a full +.SM ARPANET +header, +.I arpa-mailer +will insert ``Date:'' and ``From:'' +fields in the proper format. +The ``From:'' person +is determined by the from-address argument, +with colons translated to periods +and ``@Berkeley'' appended. +The from-address argument +is also used by the +mailer daemon +to return the mail to you +if there is a problem at the receiving host. +.SH FILES +.RI /dev/net/ to-host +.br +/usr/spool/netmail/* +.SH SEE\ ALSO +delivermail(8), mailer(ARPA) diff --git a/usr/src/cmd/delivermail/delivermail.8 b/usr/src/cmd/delivermail/delivermail.8 new file mode 100644 index 0000000000..dc90015124 --- /dev/null +++ b/usr/src/cmd/delivermail/delivermail.8 @@ -0,0 +1,251 @@ +.TH DELIVERMAIL 8 +.SH NAME +delivermail \- deliver mail to arbitrary people +.SH SYNOPSIS +.B /etc/delivermail +[ +.BR \- [ fr ] +.I address +] [ +.B \-a +] [ +.BR \-e [ empqw ] +] [ +.B \-n +] [ +.B \-m +] [ +.B \-s +] [ +.B \-i +] [ +.B \-h +.I N +] address ... +.SH DESCRIPTION +.I Delivermail +delivers a letter to one or more people, +routing the letter over whatever networks +are necessary. +.I Delivermail +will do inter-net forwarding as necessary +to deliver the mail to the correct place. +.PP +.I Delivermail +is not intended as a user interface routine; +it is expected that other programs will provide user-friendly +front ends, +and +.I delivermail +will be used only to deliver pre-formatted messages. +.PP +.I Delivermail +reads its standard input +up to a control-D +or a single dot +and sends a copy of the letter found there +to all of the addresses listed. +If the +.B \-i +flag is given, +single dots are ignored. +It determines the network to use +based on the syntax of the addresses. +Addresses containing the character `@' +or the word ``at'' +are sent to the +.SM ARPANET; +addresses containing `!' +are sent to the +.SM UUCP +net, +and addresses containing `:' or `.' +are sent to the Berkeley network. +Other addresses are assumed to be local. +.PP +Local addresses are looked up in the file +.I /usr/lib/mailaliases +and aliased appropriately. +Aliasing can be prevented by preceeding the address +with a backslash or using the +.B \-n +flag. +Normally the sender is not included in any alias +expansions, e.g., +if `john' sends to `group', +and `group' includes `john' in the expansion, +then the letter will not be delivered to `john'. +The +.B \-m +flag disables this suppression. +.PP +.I Delivermail +computes the person sending the mail +by looking at your login name. +The ``from'' person +can be explicitly specified by using the +.B \-f +flag; +or, if the +.B \-a +flag is given, +delivermail looks in the body of the message +for a ``From:'' or ``Sender:'' +field in +.SM ARPANET +format. +The +.B \-f +and +.B \-a +flags can be used +only by the special users +.I root +and +.I network, +or if the person you are trying to become +is the same as the person you are. +The +.B \-r +flag is entirely equivalent to the +.B \-f +flag; it is provided for ease of interface only. +.PP +The +.BI \-e x +flag controls the disposition of error output, +as follows: +.TP 3n +.B e +Print errors on the standard output, +and echo a copy of the message when done. +It is assumed that a network server will +return the message back to the user. +.TP +.B m +Mail errors back to the user. +.TP +.B p +Print errors on the standard output. +.TP +.B q +Throw errors away; +only exit status is returned. +.TP +.B w +Write errors back to the user's terminal, +but only if the user is still logged in +and write permission is enabled; +otherwise errors are mailed back. +.LP +If the error is not mailed back, +and if the mail originated on the machine where the error occurred, +the letter is appended to the file +.I dead.letter +in the sender's home directory. +.PP +If the first character of the user name +is a vertical bar, +the rest of the user name is used as the name of a program +to pipe the mail to. +It may be necessary to quote the name of the user +to keep +.I delivermail +from supressing the blanks from between arguments. +.PP +The message is normally editted to eliminate ``From'' +lines that might confuse other mailers. +In particular, +``From'' lines in the header are deleted, +and ``From'' lines in the body are prepended by `>'. +The +.B \-s +flag saves ``From'' lines in the header. +.PP +The +.B \-h +flag gives a ``hop-count'', i.e., +a measure of how many times this message +has been processed by +.I delivermail +(presumably on different machines). +Each time +.I delivermail +processes a message, +it increases the hop-count by one; +if it exceeds 30 +.I delivermail +assumes that an alias loop has occured +and it aborts the message. +The hop-count defaults to zero. +.PP +.I Delivermail +returns an exit status +describing what it did. +The codes are defined in +.IR mailexits.h : +.ta 3n +\w'EX_UNAVAILABLE'u+3n +.de XX +.ti \n(.iu +.. +.in +\w'EX_UNAVAILABLE'u+6n +.XX +0 EX_OK Succesful completion on all addresses. +.XX +2 EX_NOUSER User name not recognized. +.XX +3 EX_UNAVAILABLE Catchall meaning necessary resources +were not available. +.XX +4 EX_SYNTAX Syntax error in address. +.XX +5 EX_SOFTWARE Internal software error, +including bad arguments. +.XX +6 EX_OSERR Temporary operating system error, +such as ``cannot fork''. +.XX +7 EX_NOHOST Host name not recognized. +.DT +.PP +.SH FILES +.in +10 +.ti -10 +/usr/lib/mailaliases \- to alias names +.ti -10 +/bin/mail \- to deliver local mail +.ti -10 +/usr/net/bin/sendmail \- to deliver Berkeley mail +.ti -10 +/usr/lib/mailers/arpa \- to deliver +.SM ARPANET +mail +.ti -10 +/usr/lib/mailers/uucp \- to deliver +.SM UUCP +mail +.ti -10 +/tmp/mail* \- temp file +.ti -10 +/tmp/xscript* \- saved transcript +.ti -10 +/dev/log \- to log status (optional) +.in -10 +.SH SEE\ ALSO +mail(1), Mail(UCB), arpa-mailer(8), uucp-mailer(8), +mailaliases(5), userinfo(5) +.SH BUGS +.I Delivermail +sends one copy of the letter +to each user; +it should send one copy +of the letter to each host +and distribute to multiple users there +whenever possible. +.PP +.I Delivermail +assumes the addresses can be represented as one word. +This is incorrect according to the +.SM ARPANET +mail protocol RFC 733 (NIC 41952), +but is consistant with the real world. diff --git a/usr/src/cmd/delivermail/mail-dm.c b/usr/src/cmd/delivermail/mail-dm.c new file mode 100644 index 0000000000..b112b48fd1 --- /dev/null +++ b/usr/src/cmd/delivermail/mail-dm.c @@ -0,0 +1,445 @@ +#include +#include "srvrftp.h" +#include +#include +#include +#include +#include +#include +#include +extern int fout; + /* +Name: + mail + +Function: + handle the MAIL command over the command connection + +Algorithm: + see if we have a known user + + if mailbox file can't be gotten + return + tell him it is ok to go ahead with mail + + while he doesn't type a period + read and write data + say completed + +Parameters: + username in arg + +Returns: + nothing + +Globals: + arg + username= + +Calls: + strmove + getuser + loguser + openmail + closemail + getline + chown (sys) + time (sys) + printf (sys) + getch (util) + putch (util) + +Called by: + main thru command array + +History: + initial coding Mark Kampe UCLA-ATS + modified 4/13/76 by S. F. Holmgren for Illinois version + modified 6/30/76 by S. F. Holmgren to call getmbox + modified 10/18/76 by J. S. Kravitz to improve net mail header + chown removed by R. Balocca @ CAC, Sunday 1977 February 20 + getline removed and limit on line length removed by using + getch and putch added by R. Balocca @ CAC, 1977 March 8 Tuesday + Fixed oversight in above (forgot to translate to ) + 1977 March 10 Thursday by Rick Balocca @ CAC + Added openmail & closemail, added logging, and fixed several + bugs on or about 12/21/79 by Eric Allman, UCB/INGRES. + Changed to always accept mail -- bad mail will be sent back -- + 1/9/80 by Eric Allman, UCB/INGRES. +*/ +#define gt (c = getch()) +mail() +{ + register char *p; /* general use */ + register int c; + int i; + + /* extern struct io_buf obuf; */ + + /* get to open mailbox file descriptor */ + fflush(&fout); + if( (fout = openmail(arg)) < 0 ) + return; + + /* obuf.unused = 0; obuf.addr = 0; /* fake a fcreat */ + + /* say its ok to continue */ + netreply( "350 Enter mail, end with a line containing only `.'\r\n" ); + + for(;;) /* while no error or . */ + { + /* we are at beginning of line */ + + if(gt=='.') /*"."*/ + { + if(gt=='\r') /*".\r"*/ + { + if(gt=='\n') /*".\r\n"*/ + { + /* end of message */ + break; + } + else + { /*".\r"c*/ + putch('.'); + putch('\r'); + } + } + else /*"."c"*/ + putch('.'); + } + /*"-"*/ + /* c */ + for(;;) + { + for(; c != '\r'; gt) + { + if( c < 0 ) + { + /* fflush(&obuf); */ + /* write(obuf.fid, "\n***** Sender aborted connection *****\n", 39); */ + fflush(&fout); + write(fout, "\n***** Sender aborted connection *****\n", 39); + goto out; + } + else + putch(c); + } + + /*"\r"*/ + if( gt == '\n' ) + { /*"\r\n"*/ +crlf: + putch('\n'); + break; + } + else + { /*"\r"c*/ +crc: + putch('\r'); + if(c=='\0') + gt; /* "\r\0" */ + /* is arpa escape for "\r" */ + } + } + } + +out: + fflush(&fout); + if (closemail(fout) >= 0) + netreply("256 Mail accepted\r\n"); +} + + /* +Name: + datamail + +Function: + handle the MLFL command + +Algorithm: + fork + make sure we have a valid user + say bad user and exit + send sock command + open data connection + get open mailbox file descriptor + call rcvdata to receive mail + +Parameters: + username in arg + +Returns: + nothing + +Globals: + arg + +Calls: + fork (sys) + strmove + netreply + sendsock + dataconnection + getmbox + rcvdata + printf (sys) + time (sys) + +Called by: + main thru command array + +History: + initial coding 4/13/76 by S. F. Holmgren + modified 10/18/76 by J. S. Kravitz to put net mail header + chown removed by R. Balocca @ CAC, Sunday 1977 February 20 +*/ +datamail() +{ + register netdata; + /* register mboxfid; */ + register int i; + + i = fork(); + if (i < 0) + { + netreply("455 Mail server temporarily unavailable\r\n"); + return; + } + else if (i == 0) + { + fflush(&fout); + if ((fout = openmail(arg)) < 0) + exit(3); + + /* send sock command */ + sendsock( U4 ); + + /* open data connection */ + netdata = dataconnection( U4 ); + + /* say its ok to proceed */ + numreply( NUM250 ); + + /* get data from net connection and copy to mail file */ + /* rcvdata( netdata,mboxfid ); */ + if (rcvdata(netdata, fout) < 0) + exit(1); + + /* close the mail, see if ok; if so say ok */ + fflush(&fout); + if (closemail(fout) >= 0) + numreply( NUM252 ); + + exit( 0 ); + } +} + /* +** OPENMAIL -- Open a channel to the mail server +** +** Gets the mail server started up ready to handle our +** mail. +** +** Algorithm: +** See if the user is specified. +** If not, send to user "root". +** See if the user exists. +** If not, signal error 450 and return. +** Fork. +** Create a pipe +** Signal "unavailable" and exit on failure. +** Fork. +** Signal "unavailable" and exit on failure +** In child: +** Call mailer: /etc/delivermail is preferred. +** In parent: +** Avoid pipe signals in case delivermail dies. +** Save the childs pid. +** Return file descriptor. +** +** Notes: +** The check to see if the user actually exists should +** go away so that we can do real mail forwarding. +** +** Parameters: +** who -- the user to send the mail to. +** +** Returns: +** File descriptor to send mail to. +** -1 on failure. +** +** Side Effects: +** Forks /etc/delivermail or /bin/mail or /usr/bin/mail. +** Becomes "network" in the child. +** +** Requires: +** strmove +** getuser +** netreply +** pipe (sys) +** fork (sys) +** close (sys) +** dup (sys) +** execl (sys) +** signal (sys) +** exit (sys) +** +** Called By: +** mail +** datamail +** +** History: +** 1/9/80 -- Added 050 & 455 reply messages if execl's +** fail. Eric Allman UCB/INGRES. +** 11/26/79 -- Modified to map upper case to lower +** case. Eric Allman UCB/INGRES. +** 11/10/79 -- Written by Eric Allman UCB/INGRES +** 3/6/80 -- Dropped case mapping; delivermail does +** that now. EPA UCB/INGRES. +*/ + +int Mail_pid; +char *Mail_user; + +openmail(who) + char *who; +{ + register char *w; + register int i; + int pvect[2]; + register char *p; + + w = who; + if (w == 0) + w = "root"; +/* + else + { + for (p = w; *p != '\0'; p++) + { + if (*p >= 'A' && *p <= 'Z') + *p =- 'A' - 'a'; + } + } +*/ + Mail_user = w; + + /* see if the user exists */ + strmove(w, username); +/* + if (getuser(0) == 0) + { + netreply("450 User unknown\r\n"); + return (-1); + } +*/ + + /* try to get a pipe to the mailer */ + if (pipe(pvect) < 0) + { + unavailable: + netreply("455 Mail server temporarily unavailable\r\n"); + return (-1); + } + + /* fork */ + i = fork(); + if (i < 0) + { + /* failure */ + close(pvect[0]); + close(pvect[1]); + goto unavailable; + } + else if (i == 0) + { + /* child */ + close(pvect[1]); + close(0); + dup(pvect[0]); + close(pvect[0]); + setuid(NETUID); + + /* try to call something to deliver the mail */ + execl("/etc/delivermail", "delivermail", "-em", "-a", w, 0); + netreply("050 Not using normal mail server, beware!\r\n"); + execl("/bin/mail", "mail", w, 0); + execl("/usr/bin/mail", "mail", w, 0); + + /* doesn't seem to be anything around */ + netreply("455 Mail server unavailable\r\n"); + exit(3); + } + + /* else parent */ + signal(SIGPIPE, SIG_IGN); + Mail_pid = i; + close(pvect[0]); + return (pvect[1]); +} + /* +** CLOSEMAIL -- Close the mail file and get actual status +** +** The mail file is closed. +** +** Algorithm: +** Wait for the mailer to die. +** If it wasn't there, be non-comittal. +** If it died a violent death, give error. +** +** Parameters: +** fd -- the file descriptor of the mail file. +** +** Returns: +** none. +** +** Side Effects: +** mailer is soaked up. +** +** Requires: +** close (sys) +** wait (sys) +** +** Called By: +** mail +** datamail +** +** History: +** 1/9/80 -- Changed to not check for errors in mailing, +** since these will be mailed back. +** 11/10/79 -- Written by Eric Allman UCB/INGRES. +*/ + +closemail(fd) + int fd; +{ + auto int st; + register int i; + + /* close the pipe -- mail should go away */ + close(fd); + + /* wait for its body */ + while ((i = wait(&st)) != Mail_pid) + { + if (i < 0) + { + /* how did this happen? */ + logmsg(LOG_ERR, "mail from host %d to %s: no child", + openparams.o_frnhost & 0377, Mail_user); + goto unavailable; + } + } + + /* 'st' is now the status of the mailer */ + if ((st & 0377) != 0) + { + logmsg(LOG_ERR, "mail from host %d to %s: status %o", + openparams.o_frnhost & 0377, Mail_user, st); +unavailable: + netreply("455 Mail not delivered -- local system error\r\n"); + return (-1); + } + + return (0); +} diff --git a/usr/src/cmd/delivermail/userinfo.5 b/usr/src/cmd/delivermail/userinfo.5 new file mode 100644 index 0000000000..8a4edc7498 --- /dev/null +++ b/usr/src/cmd/delivermail/userinfo.5 @@ -0,0 +1,55 @@ +.TH USERINFO 5 1/22/80 +.SH NAME +userinfo \- per-user database of personal information +.SH SYNOPSIS +~/.userinfo +.SH DESCRIPTION +The +.I \&.userinfo +database contains a set of miscellaneous information +about each user. +It is formatted as a sequence of lines +of the form ``field-name: value''. +.I Field-name +must begin in the first column, +but there may be spaces before or after the colon. +Spaces in the value field may be significant or not, +depending on the semantics of the particular field. +Fields may be in any order. +Case in field names is ignored. +.PP +The following fields are defined: +.IP name \w'office-address'u+3n +The user's full name. +.IP office-address +The user's office address. +.IP office-phone +The user's office phone number. +.IP home-address +The home address; +lines of the address are separated with semicolons. +.IP home-phone +The home phone number. +.IP forward-to +The address to forward any incoming mail to. +.IP project +The project that this user is associated with. +.IP advisor +This user's advisor or supervisor. +.IP affiliation +A business or technical affiliation +(for outside users). +.PP +Other fields may be defined as needed. +.SH EXAMPLE +.nf +NAME: Eric Allman +Forward-To: ingres:eric +home-phone: (415) 843-9461 +office-address: 380 Cory +office-phone: 2-7520 +Project: INGRES +Advisor: Mike Stonebraker +.fi +.SH SEE\ ALSO +finger(1), delivermail(8) diff --git a/usr/src/cmd/delivermail/v6-mail.c b/usr/src/cmd/delivermail/v6-mail.c new file mode 100644 index 0000000000..5e71bcdf6c --- /dev/null +++ b/usr/src/cmd/delivermail/v6-mail.c @@ -0,0 +1,544 @@ +# + +/* + * mail command usage + * mail [-yn] + * prints your mail + * mail people + * sends standard input to people + * + * mail -r machine user people + * sends mail from the network + * + * if NOTROOT is defined, don't run as root. + */ + +#define SIGINT 2 +#define DIRECT 040000 +#define RMAILCMD "/usr/net/bin/sendmail" +#define GETUID() (getuid() & 0377) +#define SPOOLDIR "/usr/spool/mail/" +#define NOTROOT $ + +struct inode { + char minor; + char major; + int inumber; + int flags; + char nlinks; + char uid; + char gid; + char size0; + int size1; + int addr[8]; + int actime[2]; + int modtime[2]; +} inode; + +char lettmp[] "/tmp/maXXXXX"; +char preptmp[] "/tmp/mbXXXXX"; +int pwfil; +int chew; +int errs; +char *strcat(), *strcpy(); + +main(argc, argv) +char **argv; +{ + register int me; + extern int fout; + int uf, delexit(); + char namebuf[20]; + + mktemp(lettmp); + mktemp(preptmp); + unlink(lettmp); + unlink(preptmp); + me = GETUID(); + if (getname(me, namebuf) < 0) { + printf("Who are you?\n"); + delexit(1); + } + if (argc < 2) + goto hitit; + for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++) + switch(argv[0][1]) { + register char *cp, *np; + + case 'y': + case 'n': + argc++, argv--; +hitit: + printmail(argc, argv, namebuf); + delexit(0); + + case 'r': + if (argc < 2) + continue; + case 'f': + if (argc < 1) + continue; + if (!equal("network", namebuf) && me != 0) { + printf("Nice try!\n"); + delexit(1); + } + chew++; + np = namebuf; + for (cp = argv[1]; *cp; cp++) + *np++ = *cp; + if (argv[0][1] == 'r') + { + argc--, argv++; + *np++ = ':'; + for (cp = argv[1]; *cp; cp++) + *np++ = *cp; + } + *np++ = 0; + argc--, argv++; + continue; + } + if ((signal(SIGINT, 01) & 01) == 0) + signal(SIGINT, delexit); + unlink(lettmp); +# ifdef NOTROOT + fout = creat(lettmp, 0666); +# else + fout = creat(lettmp, 0600); +# endif + if (fout < 0) { + fout = 1; + perror(lettmp); + delexit(1); + } + argc++, argv--; + bulkmail(argc, argv, namebuf); + delexit(0); +} + +printmail(argc, argv, name) +char **argv; +char *name; +{ + extern int fin, fout; + register n, c, f; + char *mname; + + mname = cat(SPOOLDIR, name); + if (stat(mname, &inode)>=0 && inode.nlinks==1 && + fopen(mname, &fin)>=0 && (c = getchar())) { + putchar(c); + getput(); + close(fin); + c = 'x'; + if (argc<2) { + if (ttyn(0)!='x') { + printf("Save?"); + fin = 0; + c = getchar(); + } + } else + c = argv[1][1]; + if (!any(c, "yn")) + delexit(0); + if (c == 'y') { + if (accesss("mbox")) { + printf("Saved mail in 'mbox'\n"); + prepend(mname, "mbox", GETUID()); + unlink(mname); + } else + printf("In wrong directory\n"); + } else + unlink(mname); + } else + printf("No mail.\n"); +} + +bulkmail(argc, argv, from) +char **argv, *from; +{ + extern int fin, fout; + register int c; + register char *cp; + char linebuf[128]; + int tbuf[2], ttyn1; + + fin = 0; + (&fin)[1] = 0; + time(tbuf); + ttyn1 = ttyn(1); + if (ttyn1 < 033) { + ttyn1 =+ 'a' - 1; + ttyn1 =<< 8; + ttyn1 =| '^'; + } + printf("From %s tty%c %s", from, ttyn1, ctime(tbuf)); + + /* + * If delivering mail from the network via mail -r, + * Strip the leading line and throw it away, as long + * as it begins with "From ..." + */ + + if (chew) { + cp = linebuf; + do { + c = getchar(); + if (cp - linebuf < 120) + *cp++ = c; + } while (c != '\n' && c != 0); + *cp = '\0'; + if (linebuf[0] != 'F' || linebuf[1] != 'r' || + linebuf[2] != 'o' || linebuf[3] != 'm') + printf("%s", linebuf); + } + getput(); + putchar('\n'); + flush(); + close(fout); + while (--argc > 0) + sendto(*++argv); + delexit(errs); +} + +sendto(person) +char *person; +{ + static int saved; + extern int fout, fin; + register char *filep; + register int him; + int i; + + if ((person[0] == 'i' || person[0] == 'I') && person[1] == ':') + person += 2; + for (i = 0; person[i] != '\0'; i++) + { + if (person[i] == ':') + { + person[i] = '\0'; + if (equal(person, "ing70") || equal(person, "ingres")) + person += i + 1; + else + person[i] = ':'; + break; + } + } + if (person[i] == ':' || equal(person, "msgs")) + { + int i = fork(); + int s; + + if (i < 0) { + perror("fork"); + goto assback; + } + if (i == 0) { + close(0); + open(lettmp, 0); + if (any(':', person)) { + execl(RMAILCMD, "sendmail", person, 0); + execl("/usr/bin/sendmail", "sendmail", person, 0); + execl("/bin/sendmail", "sendmail", person, 0); + perror("sendmail"); + } else { + execl("/usr/new/msgs", "msgs", "-s", 0); + execl("/usr/ucb/msgs", "msgs", "-s", 0); + execl("/usr/bin/msgs", "msgs", "-s", 0); + } + exit(12); + } + for (;;) { + register int j = wait(&s); + if (j == -1) + goto assback; + if (j == i) + break; + } + if ((s & 0377) != 0 || (s >> 8) == 12) + goto assback; + return; + } + + if ((him = getuserid(person)) == -1) { +assback: + fout = 1; + flush(); + printf("Can't send to %s.\n", person); + errs++; + if (ttyn(0)!='x' && saved==0) { + saved++; + if (accesss("dead.letter")) { + printf("Letter saved in 'dead.letter'\n"); + prepend(lettmp, "dead.letter", GETUID()); + } else + printf("In wrong directory\n"); + } + return; + } + filep = cat(SPOOLDIR, person); + lock(filep); + prepend(lettmp, filep, him); + unlock(); +} + +prepend(from, to, own) +char *from, *to; +{ + extern int fin, fout; + register int sig; + int statb[18]; + + if (stat(to, statb) >= 0 && (statb[2] & 060000) != 0) { + write(2, "Exotic destination\n", 19); + delexit(1); + } + unlink(preptmp); + if (fcreat(preptmp, &fout) < 0) { + fout = 1; + perror("mail"); + delexit(1); + } + chmod(preptmp, 0600); + if (fopen(from, &fin) < 0) { + close(fout); + fout = 1; + perror("mail"); + unlink(preptmp); + return(0); + } + getput(); + close(fin); + fopen(to, &fin); + getput(); + close(fin); + flush(); + close(fout); + sig = signal(SIGINT, 01); + unlink(to); + if (fcreat(to, &fout) < 0) { + unlink(preptmp); + fout = 1; + signal(SIGINT, sig); + return(0); + } +# ifdef NOTROOT + chmod(to, 0666); +# else + chmod(to, 0600); + chown(to, own); +# endif + if(stat(to, &inode) < 0 || inode.nlinks != 1) { + close(fout); + fout = 1; + unlink(preptmp); + signal(SIGINT, sig); + return(0); + } + if (fopen(preptmp, &fin) < 0) { + fout = 1; + perror("mail"); + signal(SIGINT, sig); + errs++; + return(0); + } + getput(); + flush(); + close(fout); + close(fin); + fout = 1; + signal(SIGINT, sig); + return(1); +} + +delexit(ex) +{ + unlock(); + unlink(lettmp); + unlink(preptmp); + exit(ex); +} + +equal(as1, as2) +{ + register char *s1, *s2; + + s1 = as1; + s2 = as2; + while (*s1++ == *s2) + if (*s2++ == 0) + return(1); + return(0); +} + +cat(ap1, ap2) +char *ap1, *ap2; +{ + register char *p1, *p2; + static char fn[32]; + + p1 = ap1; + p2 = fn; + while (*p2++ = *p1++); + p2--; + p1 = ap2; + while (*p2++ = *p1++); + return(fn); +} + +getput() +{ + extern int errno; + register c; + + while(c = getchar()) { + errno = 0; + putchar(c); + if(errno) { + perror("mail"); + delexit(1); + } + } +} + +accesss(s1) +{ + if (access(".", 2) != -1 && (stat(s1, &inode)<0 || access(s1, 2)==0)) + return(1); + return(0); +} + +any(c, str) + char *str; +{ + register char *f; + + f = str; + while (*f) + if (c == *f++) + return(1); + return(0); +} + +char *maillock = ".lock"; /* Lock suffix for mailname */ +char *lockname = "/usr/spool/mail/tmXXXXXX"; +char locktmp[30]; /* Usable lock temporary */ +char curlock[50]; /* Last used name of lock */ +int locked; /* To note that we locked it */ + +/* + * Lock the specified mail file by setting the file mailfile.lock. + * We must, of course, be careful to unlink the lock file by a call + * to unlock before we stop. The algorithm used here is to see if + * the lock exists, and if it does, to check its modify time. If it + * is older than 30 seconds, we assume error and set our own file. + * Otherwise, we wait for 5 seconds and try again. + */ + +lock(file) +char *file; +{ + register int f; + long age; + struct inode sbuf; + long curtime; + + if (file == (char *) 0) { + printf("Locked = %d\n", locked); + return(0); + } + if (locked) + return(0); + strcpy(curlock, file); + strcat(curlock, maillock); + strcpy(locktmp, lockname); + mktemp(locktmp); + unlink(locktmp); + for (;;) { + f = lock1(locktmp, curlock); + if (f == 0) { + locked = 1; + return(0); + } + if (stat(curlock, &sbuf) < 0) + return(0); + time(&curtime); + age = * ((long *) sbuf.modtime); + if (curtime < age + 30) { + sleep(5); + continue; + } + unlink(curlock); + } +} + +/* + * Remove the mail lock, and note that we no longer + * have it locked. + */ + +unlock() +{ + + if (locked) + unlink(curlock); + locked = 0; +} + +/* + * Attempt to set the lock by creating the temporary file, + * then doing a link/unlink. If it fails, return -1 else 0 + */ + +lock1(tempfile, name) + char tempfile[], name[]; +{ + register int fd; + + fd = creat(tempfile, 0); + if (fd < 0) + return(-1); + close(fd); + if (link(tempfile, name) < 0) { + unlink(tempfile); + return(-1); + } + unlink(tempfile); + return(0); +} + +/* + * Concatenate s2 on the end of s1. S1's space must be large enough. + * Return s1. + */ + +char * +strcat(s1, s2) +register char *s1, *s2; +{ + register os1; + + os1 = s1; + while (*s1++) + ; + *--s1; + while (*s1++ = *s2++) + ; + return(os1); +} + +/* + * Copy string s2 to s1. s1 must be large enough. + * return s1 + */ + +char * +strcpy(s1, s2) +register char *s1, *s2; +{ + register os1; + + os1 = s1; + while (*s1++ = *s2++) + ; + return(os1); +}