summaryrefslogtreecommitdiff
path: root/sys/src/cmd/upas/send/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/src/cmd/upas/send/main.c')
-rw-r--r--sys/src/cmd/upas/send/main.c425
1 files changed, 207 insertions, 218 deletions
diff --git a/sys/src/cmd/upas/send/main.c b/sys/src/cmd/upas/send/main.c
index dcf518825..77cebc782 100644
--- a/sys/src/cmd/upas/send/main.c
+++ b/sys/src/cmd/upas/send/main.c
@@ -2,94 +2,82 @@
#include "send.h"
/* globals to all files */
-int rmail;
-char *thissys, *altthissys;
-int nflg;
-int xflg;
-int debug;
-int rflg;
-int iflg = 1;
-int nosummary;
+int flagn;
+int flagx;
+int debug;
+int flagi = 1;
+int rmail;
+int nosummary;
+char *thissys;
+char *altthissys;
/* global to this file */
-static String *errstring;
-static message *mp;
-static int interrupt;
-static int savemail;
-static Biobuf in;
-static int forked;
-static int add822headers = 1;
-static String *arglist;
+static String *errstring;
+static message *mp;
+static int interrupt;
+static int savemail;
+static Biobuf in;
+static int forked;
+static int add822headers = 1;
+static String *arglist;
/* predeclared */
-static int send(dest *, message *, int);
-static void lesstedious(void);
-static void save_mail(message *);
-static int complain_mail(dest *, message *);
-static int pipe_mail(dest *, message *);
-static void appaddr(String *, dest *);
-static void mkerrstring(String *, message *, dest *, dest *, char *, int);
-static int replymsg(String *, message *, dest *);
-static int catchint(void*, char*);
+static int send(dest*, message*, int);
+static void lesstedious(void);
+static void save_mail(message*);
+static int complain_mail(dest*, message*);
+static int pipe_mail(dest*, message*);
+static int catchint(void*, char*);
void
usage(void)
{
- fprint(2, "usage: mail [-birtx] list-of-addresses\n");
+ fprint(2, "usage: send [-#bdirx] list-of-addresses\n");
exits("usage");
}
void
main(int argc, char *argv[])
{
- dest *dp=0;
- int checkforward;
- char *base;
int rv;
+ dest *dp;
- /* process args */
ARGBEGIN{
case '#':
- nflg = 1;
+ flagn = 1;
break;
case 'b':
add822headers = 0;
break;
- case 'x':
- nflg = 1;
- xflg = 1;
- break;
case 'd':
debug = 1;
break;
case 'i':
- iflg = 0;
+ flagi = 0;
break;
case 'r':
- rflg = 1;
+ rmail++;
+ break;
+ case 'x':
+ flagn = 1;
+ flagx = 1;
break;
default:
usage();
}ARGEND
- while(*argv){
+ if(*argv == 0)
+ usage();
+ dp = 0;
+ for(; *argv; argv++){
if(shellchars(*argv)){
fprint(2, "illegal characters in destination\n");
exits("syntax");
}
- d_insert(&dp, d_new(s_copy(*argv++)));
+ d_insert(&dp, d_new(s_copy(*argv)));
}
-
- if (dp == 0)
- usage();
arglist = d_to(dp);
- /*
- * get context:
- * - whether we're rmail or mail
- */
- base = basename(argv0);
- checkforward = rmail = (strcmp(base, "rmail")==0) | rflg;
thissys = sysname_read();
altthissys = alt_sysname_read();
if(rmail)
@@ -99,22 +87,22 @@ main(int argc, char *argv[])
* read the mail. If an interrupt occurs while reading, save in
* dead.letter
*/
- if (!nflg) {
+ if (!flagn) {
Binit(&in, 0, OREAD);
if(!rmail)
atnotify(catchint, 1);
- mp = m_read(&in, rmail, !iflg);
+ mp = m_read(&in, rmail, !flagi);
if (mp == 0)
- exit(0);
+ exits(0);
if (interrupt != 0) {
save_mail(mp);
- exit(1);
+ exits("interrupt");
}
} else {
mp = m_new();
if(default_from(mp) < 0){
fprint(2, "%s: can't determine login name\n", argv0);
- exit(1);
+ exits("fail");
}
}
errstring = s_new();
@@ -132,7 +120,7 @@ main(int argc, char *argv[])
* security reasons.
*/
mp->sender = escapespecial(mp->sender);
- if (shellchars(s_to_c(mp->sender)))
+ if(shellchars(s_to_c(mp->sender)))
mp->replyaddr = s_copy("postmaster");
else
mp->replyaddr = s_clone(mp->sender);
@@ -141,21 +129,21 @@ main(int argc, char *argv[])
* reject messages that have been looping for too long
*/
if(mp->received > 32)
- exit(refuse(dp, mp, "possible forward loop", 0, 0));
+ exits(refuse(dp, mp, "possible forward loop", 0, 0)? "refuse": "");
/*
* reject messages that are too long. We don't do it earlier
* in m_read since we haven't set up enough things yet.
*/
if(mp->size < 0)
- exit(refuse(dp, mp, "message too long", 0, 0));
+ exits(refuse(dp, mp, "message too long", 0, 0)? "refuse": "");
- rv = send(dp, mp, checkforward);
+ rv = send(dp, mp, rmail);
if(savemail)
save_mail(mp);
if(mp)
m_free(mp);
- exit(rv);
+ exits(rv? "fail": "");
}
/* send a message to a list of sites */
@@ -183,10 +171,7 @@ send(dest *destp, message *mp, int checkforward)
break;
case d_pipeto:
case d_pipe:
- if (!rmail && !nflg && !forked) {
- forked = 1;
- lesstedious();
- }
+ lesstedious();
errors += pipe_mail(dp, mp);
break;
default:
@@ -206,7 +191,8 @@ lesstedious(void)
if(debug)
return;
-
+ if(rmail || flagn || forked)
+ return;
switch(fork()){
case -1:
break;
@@ -215,9 +201,10 @@ lesstedious(void)
for(i=0; i<3; i++)
close(i);
savemail = 0;
+ forked = 1;
break;
default:
- exit(0);
+ exits("");
}
}
@@ -226,26 +213,23 @@ lesstedious(void)
static void
save_mail(message *mp)
{
+ char buf[Pathlen];
Biobuf *fp;
- String *file;
- file = s_new();
- deadletter(file);
- fp = sysopen(s_to_c(file), "cAt", 0660);
+ mboxpathbuf(buf, sizeof buf, getlog(), "dead.letter");
+ fp = sysopen(buf, "cAt", 0660);
if (fp == 0)
return;
m_bprint(mp, fp);
sysclose(fp);
- fprint(2, "saved in %s\n", s_to_c(file));
- s_free(file);
+ fprint(2, "saved in %s\n", buf);
}
/* remember the interrupt happened */
static int
-catchint(void *a, char *msg)
+catchint(void*, char *msg)
{
- USED(a);
if(strstr(msg, "interrupt") || strstr(msg, "hangup")) {
interrupt = 1;
return 1;
@@ -303,7 +287,7 @@ complain_mail(dest *dp, message *mp)
msg = "unknown d_";
break;
}
- if (nflg) {
+ if (flagn) {
print("%s: %s\n", msg, s_to_c(dp->addr));
return 0;
}
@@ -314,12 +298,22 @@ complain_mail(dest *dp, message *mp)
static int
pipe_mail(dest *dp, message *mp)
{
- dest *next, *list=0;
- String *cmd;
- process *pp;
- int status, r;
+ int status;
char *none;
- String *errstring=s_new();
+ dest *next, *list;
+ process *pp;
+ String *cmd;
+ String *errstring;
+
+ errstring = s_new();
+ list = 0;
+
+ /*
+ * we're just protecting users from their own
+ * pipeto scripts with this none business.
+ * this depends on none being able to append
+ * to a mail file.
+ */
if (dp->status == d_pipeto)
none = "none";
@@ -329,12 +323,12 @@ pipe_mail(dest *dp, message *mp)
* collect the arguments
*/
next = d_rm_same(&dp);
- if(xflg)
+ if(flagx)
cmd = s_new();
else
cmd = s_clone(next->repl1);
for(; next != 0; next = d_rm_same(&dp)){
- if(xflg){
+ if(flagx){
s_append(cmd, s_to_c(next->addr));
s_append(cmd, "\n");
} else {
@@ -346,8 +340,8 @@ pipe_mail(dest *dp, message *mp)
d_insert(&list, next);
}
- if (nflg) {
- if(xflg)
+ if (flagn) {
+ if(flagx)
print("%s", s_to_c(cmd));
else
print("%s\n", s_to_c(cmd));
@@ -375,127 +369,12 @@ pipe_mail(dest *dp, message *mp)
/*
* return status
*/
- if (status != 0) {
- r = refuse(list, mp, s_to_c(errstring), status, 0);
- s_free(errstring);
- return r;
- }
- s_free(errstring);
+ if (status != 0)
+ return refuse(list, mp, s_to_c(errstring), status, 0);
loglist(list, mp, "remote");
return 0;
}
-static void
-appaddr(String *sp, dest *dp)
-{
- dest *parent;
- String *s;
-
- if (dp->parent != 0) {
- for(parent=dp->parent; parent->parent!=0; parent=parent->parent)
- ;
- s = unescapespecial(s_clone(parent->addr));
- s_append(sp, s_to_c(s));
- s_free(s);
- s_append(sp, "' alias `");
- }
- s = unescapespecial(s_clone(dp->addr));
- s_append(sp, s_to_c(s));
- s_free(s);
-}
-
-/*
- * reject delivery
- *
- * returns 0 - if mail has been disposed of
- * other - if mail has not been disposed
- */
-int
-refuse(dest *list, message *mp, char *cp, int status, int outofresources)
-{
- String *errstring=s_new();
- dest *dp;
- int rv;
-
- dp = d_rm(&list);
- mkerrstring(errstring, mp, dp, list, cp, status);
-
- /*
- * log first in case we get into trouble
- */
- logrefusal(dp, mp, s_to_c(errstring));
-
- /*
- * bulk mail is never replied to, if we're out of resources,
- * let the sender try again
- */
- if(rmail){
- /* accept it or request a retry */
- if(outofresources){
- fprint(2, "Mail %s\n", s_to_c(errstring));
- rv = 1; /* try again later */
- } else if(mp->bulk)
- rv = 0; /* silently discard bulk */
- else
- rv = replymsg(errstring, mp, dp); /* try later if we can't reply */
- } else {
- /* aysnchronous delivery only happens if !rmail */
- if(forked){
- /*
- * if spun off for asynchronous delivery, we own the mail now.
- * return it or dump it on the floor. rv really doesn't matter.
- */
- rv = 0;
- if(!outofresources && !mp->bulk)
- replymsg(errstring, mp, dp);
- } else {
- fprint(2, "Mail %s\n", s_to_c(errstring));
- savemail = 1;
- rv = 1;
- }
- }
-
- s_free(errstring);
- return rv;
-}
-
-/* make the error message */
-static void
-mkerrstring(String *errstring, message *mp, dest *dp, dest *list, char *cp, int status)
-{
- dest *next;
- char smsg[64];
- String *sender;
-
- sender = unescapespecial(s_clone(mp->sender));
-
- /* list all aliases */
- s_append(errstring, " from '");
- s_append(errstring, s_to_c(sender));
- s_append(errstring, "'\nto '");
- appaddr(errstring, dp);
- for(next = d_rm(&list); next != 0; next = d_rm(&list)) {
- s_append(errstring, "'\nand '");
- appaddr(errstring, next);
- d_insert(&dp, next);
- }
- s_append(errstring, "'\nfailed with error '");
- s_append(errstring, cp);
- s_append(errstring, "'.\n");
-
- /* >> and | deserve different flavored messages */
- switch(dp->status) {
- case d_pipe:
- s_append(errstring, "The mailer `");
- s_append(errstring, s_to_c(dp->repl1));
- sprint(smsg, "' returned error status %x.\n\n", status);
- s_append(errstring, smsg);
- break;
- }
-
- s_free(sender);
-}
-
/*
* create a new boundary
*/
@@ -542,30 +421,30 @@ replymsg(String *errstring, message *mp, dest *dp)
refp->haveto = 1;
s_append(refp->body, "To: ");
s_append(refp->body, rcvr);
- s_append(refp->body, "\n");
- s_append(refp->body, "Subject: bounced mail\n");
- s_append(refp->body, "MIME-Version: 1.0\n");
- s_append(refp->body, "Content-Type: multipart/mixed;\n");
- s_append(refp->body, "\tboundary=\"");
+ s_append(refp->body, "\n"
+ "Subject: bounced mail\n"
+ "MIME-Version: 1.0\n"
+ "Content-Type: multipart/mixed;\n"
+ "\tboundary=\"");
s_append(refp->body, s_to_c(boundary));
- s_append(refp->body, "\"\n");
- s_append(refp->body, "Content-Disposition: inline\n");
- s_append(refp->body, "\n");
- s_append(refp->body, "This is a multi-part message in MIME format.\n");
- s_append(refp->body, "--");
+ s_append(refp->body, "\"\n"
+ "Content-Disposition: inline\n"
+ "\n"
+ "This is a multi-part message in MIME format.\n"
+ "--");
s_append(refp->body, s_to_c(boundary));
- s_append(refp->body, "\n");
- s_append(refp->body, "Content-Disposition: inline\n");
- s_append(refp->body, "Content-Type: text/plain; charset=\"US-ASCII\"\n");
- s_append(refp->body, "Content-Transfer-Encoding: 7bit\n");
- s_append(refp->body, "\n");
- s_append(refp->body, "The attached mail");
+ s_append(refp->body, "\n"
+ "Content-Disposition: inline\n"
+ "Content-Type: text/plain; charset=\"US-ASCII\"\n"
+ "Content-Transfer-Encoding: 7bit\n"
+ "\n"
+ "The attached mail");
s_append(refp->body, s_to_c(errstring));
s_append(refp->body, "--");
s_append(refp->body, s_to_c(boundary));
- s_append(refp->body, "\n");
- s_append(refp->body, "Content-Type: message/rfc822\n");
- s_append(refp->body, "Content-Disposition: inline\n\n");
+ s_append(refp->body, "\n"
+ "Content-Type: message/rfc822\n"
+ "Content-Disposition: inline\n\n");
s_append(refp->body, s_to_c(mp->body));
s_append(refp->body, "--");
s_append(refp->body, s_to_c(boundary));
@@ -577,3 +456,113 @@ replymsg(String *errstring, message *mp, dest *dp)
d_free(ndp);
return rv;
}
+
+static void
+appaddr(String *sp, dest *dp)
+{
+ dest *p;
+ String *s;
+
+ if (dp->parent != 0) {
+ for(p = dp->parent; p->parent; p = p->parent)
+ ;
+ s = unescapespecial(s_clone(p->addr));
+ s_append(sp, s_to_c(s));
+ s_free(s);
+ s_append(sp, "' alias `");
+ }
+ s = unescapespecial(s_clone(dp->addr));
+ s_append(sp, s_to_c(s));
+ s_free(s);
+}
+
+/* make the error message */
+static void
+mkerrstring(String *errstring, message *mp, dest *dp, dest *list, char *cp, int status)
+{
+ dest *next;
+ char smsg[64];
+ String *sender;
+
+ sender = unescapespecial(s_clone(mp->sender));
+
+ /* list all aliases */
+ s_append(errstring, " from '");
+ s_append(errstring, s_to_c(sender));
+ s_append(errstring, "'\nto '");
+ appaddr(errstring, dp);
+ for(next = d_rm(&list); next != 0; next = d_rm(&list)) {
+ s_append(errstring, "'\nand '");
+ appaddr(errstring, next);
+ d_insert(&dp, next);
+ }
+ s_append(errstring, "'\nfailed with error '");
+ s_append(errstring, cp);
+ s_append(errstring, "'.\n");
+
+ /* >> and | deserve different flavored messages */
+ switch(dp->status) {
+ case d_pipe:
+ s_append(errstring, "The mailer `");
+ s_append(errstring, s_to_c(dp->repl1));
+ sprint(smsg, "' returned error status %x.\n\n", status);
+ s_append(errstring, smsg);
+ break;
+ }
+
+ s_free(sender);
+}
+
+/*
+ * reject delivery
+ *
+ * returns 0 - if mail has been disposed of
+ * other - if mail has not been disposed
+ */
+int
+refuse(dest *list, message *mp, char *cp, int status, int outofresources)
+{
+ int rv;
+ String *errstring;
+ dest *dp;
+
+ errstring = s_new();
+ dp = d_rm(&list);
+ mkerrstring(errstring, mp, dp, list, cp, status);
+
+ /*
+ * log first in case we get into trouble
+ */
+ logrefusal(dp, mp, s_to_c(errstring));
+
+ rv = 1;
+ if(rmail){
+ /* accept it or request a retry */
+ if(outofresources){
+ fprint(2, "Mail %s\n", s_to_c(errstring));
+ } else {
+ /*
+ * reject without generating a reply, smtpd returns
+ * 5.0.0 status when it sees "mail refused"
+ */
+ fprint(2, "mail refused: %s\n", s_to_c(errstring));
+ }
+ } else {
+ /* aysnchronous delivery only happens if !rmail */
+ if(forked){
+ /*
+ * if spun off for asynchronous delivery, we own the mail now.
+ * return it or dump it on the floor. rv really doesn't matter.
+ */
+ rv = 0;
+ if(!outofresources && !mp->bulk)
+ replymsg(errstring, mp, dp);
+ } else {
+ fprint(2, "Mail %s\n", s_to_c(errstring));
+ savemail = 1;
+ }
+ }
+
+ s_free(errstring);
+ return rv;
+}