Commit Diff


commit - d0d15c12d43d201cf916ebfff157b976c8f3b6a1
commit + 5cc53af92d6bfae8b930d3c9154c8ed44e1feb09
blob - acb155f522481ef45297362b77581924b3dabd51
blob + 2a6925d2b57e6fc1ba724b4387368f8572579102
--- src/cmd/upas/common/common.h
+++ src/cmd/upas/common/common.h
@@ -18,6 +18,8 @@ enum
 	Elemlen= 28,
 	Errlen=	128,
 	Pathlen= 256,
+	
+	RetryCode = 2,
 };
 
 /*
blob - cf56c8693fb4e850f3dda1ffcbf78a5fea1f8fb1
blob + a1c29517632d90c7da52e549da612fd1870f88d4
--- src/cmd/upas/common/libsys.c
+++ src/cmd/upas/common/libsys.c
@@ -1,3 +1,7 @@
+#include <u.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <netdb.h>
 #include "common.h"
 #include <auth.h>
 #include <ndb.h>
@@ -407,6 +411,7 @@ sysdirreadall(int fd, Dir **d)
 /*
  *  read in the system name
  */
+static char *unix_hostname_read(void);
 extern char *
 sysname_read(void)
 {
@@ -424,20 +429,27 @@ sysname_read(void)
 extern char *
 alt_sysname_read(void)
 {
+	char *cp;
 	static char name[128];
-	int n, fd;
 
-	fd = open("/dev/sysname", OREAD);
-	if(fd < 0)
-		return 0;
-	n = read(fd, name, sizeof(name)-1);
-	close(fd);
-	if(n <= 0)
-		return 0;
-	name[n] = 0;
+	cp = getenv("sysname");
+	if(cp == 0 || *cp == 0)
+		cp = unix_hostname_read();
+	if(cp == 0 || *cp == 0)
+		return 0;
+	strecpy(name, name+sizeof name, cp);
 	return name;
 }
+static char *
+unix_hostname_read(void)
+{
+	static char hostname[256];
 
+	if(gethostname(hostname, sizeof hostname) < 0)
+		return nil;
+	return hostname;
+}
+
 /*
  *  get all names
  */
@@ -445,57 +457,49 @@ extern char**
 sysnames_read(void)
 {
 	static char **namev;
-	Ndbtuple *t, *nt;
-	Ndb* db;
-	Ndbs s;
-	int n;
-	char *cp;
+	struct hostent *h;
+	char **p, **a;
 
 	if(namev)
 		return namev;
 
-/* XXX */
-	/* free(csgetvalue(0, "sys", alt_sysname_read(), "dom", &t));  jpc */
-	db = ndbopen(unsharp("#9/ndb/local"));
-	free(ndbgetvalue(db, &s, "sys", sysname(),"dom", &t));
-	/* t = nil; /* jpc */
-	/* fprint(2,"csgetvalue called: fixme"); /* jpc */
+	h = gethostbyname(alt_sysname_read());
+	for(p=h->h_aliases; *p; p++)
+		;
+	
+	namev = malloc((2+p-h->h_aliases)*sizeof namev[0]);
+	if(namev == 0)
+		return 0;
 
-	n = 0;
-	for(nt = t; nt; nt = nt->entry)
-		if(strcmp(nt->attr, "dom") == 0)
-			n++;
-
-	namev = (char**)malloc(sizeof(char *)*(n+3));
-
-	if(namev){
-		n = 0;
-		namev[n++] = strdup(sysname_read());
-		cp = alt_sysname_read();
-		if(cp)
-			namev[n++] = strdup(cp);
-		for(nt = t; nt; nt = nt->entry)
-			if(strcmp(nt->attr, "dom") == 0)
-				namev[n++] = strdup(nt->val);
-		namev[n] = 0;
-	}
-	if(t)
-		ndbfree(t);
+	a = namev;
+	*a++ = strdup(h->h_name);
+	for(p=h->h_aliases; *p; p++)
+		*a++ = strdup(*p);
+	*a = 0;
 
 	return namev;
 }
 
 /*
- *  read in the domain name
+ *  read in the domain name.
+ *  chop off beginning pieces until we find one with an mx record.
  */
 extern char *
 domainname_read(void)
 {
-	char **namev;
+	char **namev, *p;
+	Ndbtuple *t;
 
-	for(namev = sysnames_read(); *namev; namev++)
-		if(strchr(*namev, '.'))
-			return *namev;
+	for(namev = sysnames_read(); *namev; namev++){
+		if(strchr(*namev, '.')){
+			for(p=*namev-1; p && *++p; p=strchr(p, '.')){
+				if((t = dnsquery(nil, p, "mx")) != nil){
+					ndbfree(t);
+					return p;
+				}
+			}
+		}
+	}
 	return 0;
 }
 
@@ -608,36 +612,12 @@ sysisdir(char *file)
 }
 
 /*
- * kill a process or process group
- */
-
-static int
-stomp(int pid, char *file)
-{
-	char name[64];
-	int fd;
-
-	snprint(name, sizeof(name), "/proc/%d/%s", pid, file);
-	fd = open(name, 1);
-	if(fd < 0)
-		return -1;
-	if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){
-		close(fd);
-		return -1;
-	}
-	close(fd);
-	return 0;
-	
-}
-
-/*
  *  kill a process
  */
 extern int
 syskill(int pid)
 {
-	return stomp(pid, "note");
-	
+	return postnote(PNPROC, pid, "kill");
 }
 
 /*
@@ -646,7 +626,7 @@ syskill(int pid)
 extern int
 syskillpg(int pid)
 {
-	return stomp(pid, "notepg");
+	return postnote(PNGROUP, pid, "kill");
 }
 
 extern int
@@ -723,12 +703,24 @@ sysfiles(void)
 extern String *
 mboxpath(char *path, char *user, String *to, int dot)
 {
-	upasconfig();
-
+	char *dir;
+	String *s;
+	
 	if (dot || *path=='/' || strncmp(path, "./", 2) == 0
 			      || strncmp(path, "../", 3) == 0) {
 		to = s_append(to, path);
 	} else {
+		if ((dir = homedir(user)) != nil) {
+			s = s_copy(dir);
+			s_append(s, "/mail/");
+			if(access(s_to_c(s), AEXIST) >= 0){
+				to = s_append(to, s_to_c(s));
+				s_free(s);
+				to = s_append(to, path);
+				return to;
+			}
+			s_free(s);
+		}
 		to = s_append(to, MAILROOT);
 		to = s_append(to, "/box/");
 		to = s_append(to, user);
@@ -755,13 +747,6 @@ deadletter(String *to)		/* pass in sender??? */
 	return mboxpath("dead.letter", cp, to, 0);
 }
 
-char *
-homedir(char *user)
-{
-	USED(user);
-	return getenv("home");
-}
-
 String *
 readlock(String *file)
 {
@@ -776,56 +761,48 @@ readlock(String *file)
 String *
 username(String *from)
 {
-	int n;
-	Biobuf *bp;
-	char *p, *q;
-	String *s;
+	String* s;
+	struct passwd* pw;
 
-	bp = Bopen("/adm/keys.who", OREAD);
-	if(bp == 0)
-		bp = Bopen("/adm/netkeys.who", OREAD);
-	if(bp == 0)
-		return 0;
+	setpwent();
+	while((pw = getpwent()) != nil){
+		if(strcmp(s_to_c(from), pw->pw_name) == 0){
+			s = s_new();
+			s_append(s, "\"");
+			s_append(s, pw->pw_gecos);
+			s_append(s, "\"");
+			return s;
+		}
+	}
+	return nil;
+}
 
-	s = 0;
-	n = strlen(s_to_c(from));
-	for(;;) {
-		p = Brdline(bp, '\n');
-		if(p == 0)
-			break;
-		p[Blinelen(bp)-1] = 0;
-		if(strncmp(p, s_to_c(from), n))
-			continue;
-		p += n;
-		if(*p != ' ' && *p != '\t')	/* must be full match */
-			continue;
-		while(*p && (*p == ' ' || *p == '\t'))
-				p++;
-		if(*p == 0)
-			continue;
-		for(q = p; *q; q++)
-			if(('0' <= *q && *q <= '9') || *q == '<')
-				break;
-		while(q > p && q[-1] != ' ' && q[-1] != '\t')
-			q--;
-		while(q > p && (q[-1] == ' ' || q[-1] == '\t'))
-			q--;
-		*q = 0;
-		s = s_new();
-		s_append(s, "\"");
-		s_append(s, p);
-		s_append(s, "\"");
-		break;
-	}
-	Bterm(bp);
-	return s;
+char *
+homedir(char *user)
+{
+	static char buf[1024];
+	struct passwd* pw;
+
+	setpwent();
+	while((pw = getpwent()) != nil)
+		if(strcmp(user, pw->pw_name) == 0){
+			strecpy(buf, buf+sizeof buf, pw->pw_dir);
+			return buf;
+		}
+	return nil;
 }
 
 char *
 remoteaddr(int fd, char *dir)
 {
-	/* XXX should call netconninfo */
-	return "";
+	char *raddr;
+	NetConnInfo *nci;
+	
+	if((nci = getnetconninfo(dir, fd)) == nil)
+		return nil;
+	raddr = strdup(nci->raddr);
+	freenetconninfo(nci);
+	return raddr;
 }
 
 //  create a file and 
blob - 0ed3a8a62f14de02c78a999b5e164a2ac4ca5757
blob + 2df5a98731fc02620edb8bde4ab0b096e644f65f
--- src/cmd/upas/marshal/marshal.c
+++ src/cmd/upas/marshal/marshal.c
@@ -1104,7 +1104,7 @@ sendmail(Addr *to, Addr *cc, int *pid, char *rcvr)
 		exec(s_to_c(cmd), av);
 		exec("myupassend", av);
 		exec(unsharp("#9/bin/upas/send"), av);
-		fatal("execing: %r");
+		fatal("exec: %r");
 		break;
 	default:
 		if(rcvr != nil)
blob - 7ab055ed84f83bb06937185fdf8419b817ffbbe1
blob + e7f35284b8ef2b7fb19c2e9c2d4cdd896f4fae1f
--- src/cmd/upas/q/runq.c
+++ src/cmd/upas/q/runq.c
@@ -513,7 +513,7 @@ dofile(Dir *dp)
 		if(wm->msg[0]){
 			if(debug)
 				fprint(2, "[%d] wm->msg == %s\n", getpid(), wm->msg);
-			if(!Rflag && strstr(wm->msg, "Retry")==0){
+			if(!Rflag && atoi(wm->msg) != RetryCode){
 				/* return the message and remove it */
 				if(returnmail(av, dp->name, wm->msg) != 0)
 					logit("returnmail failed", dp->name, av);
blob - 56fddba3a531d83108fc9c3a1df9246c1f4b0873
blob + afd93e3bee92debb91fbafa1a85da9b4727c1cea
--- src/cmd/upas/send/message.c
+++ src/cmd/upas/send/message.c
@@ -2,7 +2,7 @@
 #include "send.h"
 
 #include "../smtp/smtp.h"
-#include "../smtp/y.tab.h"
+#include "../smtp/rfc822.tab.h"
 
 /* global to this file */
 static Reprog *rfprog;
blob - 2feacbf21d6c0aa180fb16c59f26a8b37e6da002
blob + 3f30d4f3aa0d0e0eee788df78e07854e961905aa
--- src/cmd/upas/send/rewrite.c
+++ src/cmd/upas/send/rewrite.c
@@ -301,6 +301,7 @@ substitute(String *source, Resub *subexp, message *mp)
 			sp = getrcvar(sp+1, &s);
 			s_append(stp, s);
 			free(s);
+			sp--;	/* counter sp++ below */
 		} else
 			s_putc(stp, *sp);
 		sp++;
blob - a3a3f4d46f8f82c7ed3e7fbb185204abef6f1431
blob + 1efd145718db661f984f9fd6d5d254416983290a
--- src/cmd/upas/smtp/greylist.c
+++ src/cmd/upas/smtp/greylist.c
@@ -241,7 +241,6 @@ isrcptrecent(char *rcpt)
 void
 vfysenderhostok(void)
 {
-	char *fqdn;
 	int recent = 0;
 	Link *l;
 
@@ -258,7 +257,7 @@ vfysenderhostok(void)
 
 		if (fd >= 0) {
 			seek(fd, 0, 2);			/* paranoia */
-			fprint(fd, "# %s\n%s\n\n", fqdn, nci->rsys);
+			fprint(fd, "# unknown\n%s\n\n", nci->rsys);
 			close(fd);
 		}
 	} else {
blob - ae272c7d0fba50f54b7785184686eb890e06ae8d
blob + 31c6e5ba6991f3774eff051373e2ac7ac3401624
--- src/cmd/upas/smtp/mxdial.c
+++ src/cmd/upas/smtp/mxdial.c
@@ -22,7 +22,6 @@ Ndb *db;
 extern int debug;
 
 static int	mxlookup(DS*, char*);
-static int	mxlookup1(DS*, char*);
 static int	compar(const void*, const void*);
 static int	callmx(DS*, char*, char*);
 static void expand_meta(DS *ds);
@@ -113,83 +112,28 @@ callmx(DS *ds, char *dest, char *domain)
 }
 
 /*
- *  call the dns process and have it try to resolve the mx request
- *
- *  this routine knows about the firewall and tries inside and outside
- *  dns's seperately.
+ *  use dns to resolve the mx request
  */
 static int
 mxlookup(DS *ds, char *domain)
 {
-	int n;
-
-	/* just in case we find no domain name */
-	strcpy(domain, ds->host);
-
-	if(ds->netdir){
-		n = mxlookup1(ds, domain);
-	} else {
-		ds->netdir = "/net";
-		n = mxlookup1(ds, domain);
-		if(n == 0) {
-			ds->netdir = "/net.alt";
-			n = mxlookup1(ds, domain);
-		}
-	}
-
-	return n;
-}
-
-static int
-mxlookup1(DS *ds, char *domain)
-{
-	char buf[1024];
-	char dnsname[Maxstring];
-	char *fields[4];
-	int i, n, fd, nmx;
-
-	snprint(dnsname, sizeof dnsname, "%s/dns", ds->netdir);
-
-	fd = open(dnsname, ORDWR);
-	if(fd < 0)
-		return 0;
-
+	int i, n, nmx;
+	Ndbtuple *t, *tmx, *tpref, *tip;
+	
+	ds->netdir = "/net";
 	nmx = 0;
-	snprint(buf, sizeof(buf), "%s mx", ds->host);
-	if(debug)
-		fprint(2, "sending %s '%s'\n", dnsname, buf);
-	n = write(fd, buf, strlen(buf));
-	if(n < 0){
-		rerrstr(buf, sizeof buf);
-		if(debug)
-			fprint(2, "dns: %s\n", buf);
-		if(strstr(buf, "dns failure")){
-			/* if dns fails for the mx lookup, we have to stop */
-			close(fd);
-			return -1;
+	if((t = dnsquery(nil, ds->host, "mx")) != nil){
+		for(tmx=t; (tmx=ndbfindattr(tmx->entry, nil, "mx")) != nil && nmx<Nmx; ){
+			for(tpref=tmx->line; tpref != tmx; tpref=tmx->line){
+				if(strcmp(tpref->attr, "pref") == 0){
+					strncpy(mx[nmx].host, tmx->val, sizeof(mx[n].host)-1);
+					mx[nmx].pref = atoi(tpref->val);
+					nmx++;
+					break;
+				}
+			}	
 		}
-	} else {
-		/*
-		 *  get any mx entries
-		 */
-		seek(fd, 0, 0);
-		while(nmx < Nmx && (n = read(fd, buf, sizeof(buf)-1)) > 0){
-			buf[n] = 0;
-			if(debug)
-				fprint(2, "dns mx: %s\n", buf);
-			n = getfields(buf, fields, 4, 1, " \t");
-			if(n < 4)
-				continue;
-
-			if(strchr(domain, '.') == 0)
-				strcpy(domain, fields[0]);
-
-			strncpy(mx[nmx].host, fields[3], sizeof(mx[n].host)-1);
-			mx[nmx].pref = atoi(fields[2]);
-			nmx++;
-		}
-		if(debug)
-			fprint(2, "dns mx; got %d entries\n", nmx);
+		ndbfree(t);
 	}
 
 	/*
@@ -210,20 +154,16 @@ mxlookup1(DS *ds, char *domain)
 	 * look up all ip addresses
 	 */
 	for(i = 0; i < nmx; i++){
-		seek(fd, 0, 0);
-		snprint(buf, sizeof buf, "%s ip", mx[i].host);
-		mx[i].ip[0] = 0;
-		if(write(fd, buf, strlen(buf)) < 0)
+		if((t = dnsquery(nil, mx[i].host, "ip")) == nil)
 			goto no;
-		seek(fd, 0, 0);
-		if((n = read(fd, buf, sizeof buf-1)) < 0)
+		if((tip = ndbfindattr(t, nil, "ip")) == nil){
+			ndbfree(t);
 			goto no;
-		buf[n] = 0;
-		if(getfields(buf, fields, 4, 1, " \t") < 3)
-			goto no;
-		strncpy(mx[i].ip, fields[2], sizeof(mx[i].ip)-1);
+		}
+		strncpy(mx[i].ip, tip->val, sizeof(mx[i].ip)-1);
+		ndbfree(t);
 		continue;
-
+	
 	no:
 		/* remove mx[i] and go around again */
 		nmx--;
@@ -274,74 +214,17 @@ dial_string_parse(char *str, DS *ds)
 		expand_meta(ds);
 }
 
-#if 0 /* jpc */
 static void
 expand_meta(DS *ds)
 {
-	char buf[128], cs[128], *net, *p;
-	int fd, n;
-
-	net = ds->netdir;
-	if(!net)
-		net = "/net";
-
-	if(debug)
-		fprint(2, "expanding %s!%s\n", net, ds->host);
-	snprint(cs, sizeof(cs), "%s/cs", net);
-	if((fd = open(cs, ORDWR)) == -1){
-		if(debug)
-			fprint(2, "open %s: %r\n", cs);
-		syslog(0, "smtp", "cannot open %s: %r", cs);
-		return;
-	}
-
-	snprint(buf, sizeof(buf), "!ipinfo %s", ds->host+1);	// +1 to skip $
-	if(write(fd, buf, strlen(buf)) <= 0){
-		if(debug)
-			fprint(2, "write %s: %r\n", cs);
-		syslog(0, "smtp", "%s to %s - write failed: %r", buf, cs);
-		close(fd);
-		return;
-	}
-
-	seek(fd, 0, 0);
-	if((n = read(fd, ds->expand, sizeof(ds->expand)-1)) < 0){
-		if(debug)
-			fprint(2, "read %s: %r\n", cs);
-		syslog(0, "smtp", "%s - read failed: %r", cs);
-		close(fd);
-		return;
-	}
-	close(fd);
-
-	ds->expand[n] = 0;
-	if((p = strchr(ds->expand, '=')) == nil){
-		if(debug)
-			fprint(2, "response %s: %s\n", cs, ds->expand);
-		syslog(0, "smtp", "%q from %s - bad response: %r", ds->expand, cs);
-		return;
-	}
-	ds->host = p+1;
-
-	/* take only first one returned (quasi-bug) */
-	if((p = strchr(ds->host, ' ')) != nil)
-		*p = 0;
-}
-#endif /* jpc */
-
-/* XXX */
-static void
-expand_meta(DS *ds)
-{
-	Ndb *db;
+	static Ndb *db;
 	Ndbs s;
 	char *sys, *smtpserver;
 
+	/* can't ask cs, so query database directly. */
 	sys = sysname();
-	db = ndbopen(unsharp("#9/ndb/local"));
-	fprint(2,"%s",ds->host);
+	if(db == nil)
+		db = ndbopen(0);
 	smtpserver = ndbgetvalue(db, &s, "sys", sys, "smtp", nil);
-	snprint(ds->host,128,"%s",smtpserver);
-	fprint(2," exanded to %s\n",ds->host);
-
+	snprint(ds->host, 128, "%s", smtpserver);
 }
blob - cddbbc0fae671d8a9ff7a56ae8d6267461491a8a
blob + a31a0e67b20868f78bf3afa07852d35e9a22ae77
--- src/cmd/upas/smtp/rfc822.tab.h
+++ src/cmd/upas/smtp/rfc822.tab.h
@@ -1,98 +1,25 @@
-/* A Bison parser, made by GNU Bison 2.0.  */
-
-/* Skeleton parser for Yacc-like parsing with Bison,
-   Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, when this file is copied by Bison into a
-   Bison output file, you may use that output file without restriction.
-   This special exception was added by the Free Software Foundation
-   in version 1.24 of Bison.  */
-
-/* Tokens.  */
-#ifndef YYTOKENTYPE
-# define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     WORD = 258,
-     DATE = 259,
-     RESENT_DATE = 260,
-     RETURN_PATH = 261,
-     FROM = 262,
-     SENDER = 263,
-     REPLY_TO = 264,
-     RESENT_FROM = 265,
-     RESENT_SENDER = 266,
-     RESENT_REPLY_TO = 267,
-     SUBJECT = 268,
-     TO = 269,
-     CC = 270,
-     BCC = 271,
-     RESENT_TO = 272,
-     RESENT_CC = 273,
-     RESENT_BCC = 274,
-     REMOTE = 275,
-     PRECEDENCE = 276,
-     MIMEVERSION = 277,
-     CONTENTTYPE = 278,
-     MESSAGEID = 279,
-     RECEIVED = 280,
-     MAILER = 281,
-     BADTOKEN = 282
-   };
-#endif
-#define WORD 258
-#define DATE 259
-#define RESENT_DATE 260
-#define RETURN_PATH 261
-#define FROM 262
-#define SENDER 263
-#define REPLY_TO 264
-#define RESENT_FROM 265
-#define RESENT_SENDER 266
-#define RESENT_REPLY_TO 267
-#define SUBJECT 268
-#define TO 269
-#define CC 270
-#define BCC 271
-#define RESENT_TO 272
-#define RESENT_CC 273
-#define RESENT_BCC 274
-#define REMOTE 275
-#define PRECEDENCE 276
-#define MIMEVERSION 277
-#define CONTENTTYPE 278
-#define MESSAGEID 279
-#define RECEIVED 280
-#define MAILER 281
-#define BADTOKEN 282
-
-
-
-
-#if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED)
-typedef int YYSTYPE;
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
-# define YYSTYPE_IS_DECLARED 1
-# define YYSTYPE_IS_TRIVIAL 1
-#endif
-
-extern YYSTYPE yylval;
-
-
-
+#define	WORD	57346
+#define	DATE	57347
+#define	RESENT_DATE	57348
+#define	RETURN_PATH	57349
+#define	FROM	57350
+#define	SENDER	57351
+#define	REPLY_TO	57352
+#define	RESENT_FROM	57353
+#define	RESENT_SENDER	57354
+#define	RESENT_REPLY_TO	57355
+#define	SUBJECT	57356
+#define	TO	57357
+#define	CC	57358
+#define	BCC	57359
+#define	RESENT_TO	57360
+#define	RESENT_CC	57361
+#define	RESENT_BCC	57362
+#define	REMOTE	57363
+#define	PRECEDENCE	57364
+#define	MIMEVERSION	57365
+#define	CONTENTTYPE	57366
+#define	MESSAGEID	57367
+#define	RECEIVED	57368
+#define	MAILER	57369
+#define	BADTOKEN	57370
blob - fb00cd5f5f99014d5fb2acb596609c4c0eee9077
blob + 0661f4c6544368c9760152ed7590b4fd4c73a0d2
--- src/cmd/upas/smtp/smtp.c
+++ src/cmd/upas/smtp/smtp.c
@@ -5,6 +5,7 @@
 #include <libsec.h>
 #include <auth.h>
 #include <ndb.h>
+#include <thread.h>
 
 static	char*	connect(char*);
 static	char*	dotls(char*);
@@ -59,7 +60,7 @@ void
 usage(void)
 {
 	fprint(2, "usage: smtp [-adips] [-uuser] [-hhost] [.domain] net!host[!service] sender rcpt-list\n");
-	exits(Giveup); 
+	threadexitsall(Giveup); 
 }
 
 int
@@ -70,17 +71,16 @@ timeout(void *x, char *msg)
 	if(strstr(msg, "alarm")){
 		fprint(2, "smtp timeout: connection to %s timed out\n", farend);
 		if(quitting)
-			exits(quitrv);
-		exits(Retry);
+			threadexitsall(quitrv);
+		threadexitsall(Retry);
 	}
 	if(strstr(msg, "closed pipe")){
-			/* call _exits() to prevent Bio from trying to flush closed pipe */
 		fprint(2, "smtp timeout: connection closed to %s\n", farend);
 		if(quitting){
 			syslog(0, "smtp.fail", "closed pipe to %s", farend);
-			_exits(quitrv);
+			threadexitsall(quitrv);
 		}
-		_exits(Retry);
+		threadexitsall(Retry);
 	}
 	return 0;
 }
@@ -96,6 +96,14 @@ removenewline(char *p)
 		p[n] = 0;
 }
 
+int
+exitcode(char *s)
+{
+	if(strstr(s, "Retry"))	/* known to runq */
+		return RetryCode;
+	return 1;
+}
+
 void
 threadmain(int argc, char **argv)
 {
@@ -171,7 +179,7 @@ threadmain(int argc, char **argv)
 	if(*argv == 0)
 		usage();
 	addr = *argv++; argc--;
-	// expand $smtp if necessary XXX
+	// expand $smtp if necessary
 	addr = expand_addr(addr);
 	farend = addr;
 
@@ -199,12 +207,12 @@ threadmain(int argc, char **argv)
 		rv = data(from, &bfile);
 		if(rv != 0)
 			goto error;
-		exits(0);
+		threadexitsall(0);
 	}
 
 	/* mxdial uses its own timeout handler */
 	if((rv = connect(addr)) != 0)
-		exits(rv);
+		threadexitsall(rv);
 
 	/* 10 minutes to get through the initial handshake */
 	atnotify(timeout, 1);
@@ -238,7 +246,7 @@ threadmain(int argc, char **argv)
 
 	if(ping){
 		quit(0);
-		exits(0);
+		threadexitsall(0);
 	}
 
 	rv = data(from, &bfile);
@@ -246,7 +254,7 @@ threadmain(int argc, char **argv)
 		goto error;
 	quit(0);
 	if(rcvrs == ok)
-		exits(0);
+		threadexitsall(0);
 
 	/*
 	 *  here when some but not all rcvrs failed
@@ -258,7 +266,7 @@ threadmain(int argc, char **argv)
 			fprint(2, "  mail to %s failed: %s", argv[i], errs[i]);
 		}
 	}
-	exits(Giveup);
+	threadexitsall(Giveup);
 
 	/*
 	 *  here when all rcvrs failed
@@ -271,7 +279,7 @@ error:
 	fprint(2, "%s connect to %s:\n%s\n", thedate(), addr, s_to_c(reply));
 	if(!filter)
 		quit(rv);
-	exits(rv);
+	threadexitsall(rv);
 }
 
 /*
@@ -319,6 +327,8 @@ dotls(char *me)
 	int fd;
 	uchar hash[SHA1dlen];
 
+	return Giveup;
+
 	c = mallocz(sizeof(*c), 1);	/* Note: not freed on success */
 	if (c == nil)
 		return Giveup;
@@ -1097,27 +1107,44 @@ dBputc(int x)
 	return Bputc(&bout, x);
 }
 
-/* XXX */
 char* 
-expand_addr(char* a)
+expand_addr(char *addr)
 {
+	static char buf[256];
+	char *p, *q, *name, *sys;
+	Ndbtuple *t;
 	Ndb *db;
-	Ndbs s;
-	char *sys, *ret, *proto, *host;
-
-	proto = strtok(a,"!");
-	if ( strcmp(proto,"net") != 0 ) {
-		fprint(2,"unknown proto %s\n",proto);
+	
+	p = strchr(addr, '!');
+	if(p){
+		q = strchr(p+1, '!');
+		name = p+1;
+	}else{
+		name = addr;
+		q = nil;
 	}
-	host = strtok(0,"!");
-	if ( strcmp(host,"$smtp") == 0 ) {
-		sys = sysname();
-		db = ndbopen(unsharp("#9/ndb/local"));
-		host = ndbgetvalue(db, &s, "sys", sys, "smtp", nil);
-	}
-	ret = malloc(strlen(proto)+strlen(host)+2);
-	sprint(ret,"%s!%s",proto,host);
 
-	return ret;
-
+	if(name[0] != '$')
+		return addr;
+	name++;
+	if(q)
+		*q = 0;
+		
+	sys = sysname();
+	db = ndbopen(0);
+	t = ndbipinfo(db, "sys", sys, &name, 1);
+	if(t == nil){
+		ndbclose(db);
+		if(q)
+			*q = '!';
+		return addr;
+	}
+	
+	*(name-1) = 0;
+	if(q)
+		*q = '!';
+	else
+		q = "";
+	snprint(buf, sizeof buf, "%s%s%s", addr, t->val, q);
+	return buf;
 }
blob - 7b54b3cfff06ce499ce78254f2813bd3fe7ceede
blob + e59dbddd2ae63c26d0e94675e086be081e8e3cbd
--- src/cmd/upas/smtp/smtpd.c
+++ src/cmd/upas/smtp/smtpd.c
@@ -7,6 +7,7 @@
 #include <mp.h>
 #include <libsec.h>
 #include <auth.h>
+#include <thread.h>
 #include "../smtp/rfc822.tab.h"
 
 #define DBGMX 1
@@ -84,11 +85,11 @@ s_error(char *f, char *status)
 	else
 		reply("452 out of memory %s\r\n", errbuf);
 	syslog(0, "smtpd", "++Malloc failure %s [%s]", him, nci->rsys);
-	exits(status);
+	threadexitsall(status);
 }
 
 void
-main(int argc, char **argv)
+threadmain(int argc, char **argv)
 {
 	char *p, buf[1024];
 	char *netdir;
@@ -137,6 +138,8 @@ main(int argc, char **argv)
 		passwordinclear = 1;
 		break;
 	case 'c':
+		fprint(2, "tls is not available\n");
+		threadexitsall("no tls");
 		tlscert = ARGF();
 		break;
 	case 't':
@@ -145,7 +148,7 @@ main(int argc, char **argv)
 		break;
 	default:
 		fprint(2, "usage: smtpd [-dfhrs] [-n net] [-c cert]\n");
-		exits("usage");
+		threadexitsall("usage");
 	}ARGEND;
 
 	nci = getnetconninfo(netdir, 0);
@@ -179,7 +182,7 @@ main(int argc, char **argv)
 	atnotify(catchalarm, 1);
 	alarm(45*60*1000);
 	zzparse();
-	exits(0);
+	threadexitsall(0);
 }
 
 void
@@ -276,7 +279,7 @@ hello(String *himp, int extended)
 				syslog(0, "smtpd", "Hung up on %s; claimed to be %s",
 					nci->rsys, him);
 				reply("554 Liar!\r\n");
-				exits("client pretended to be us");
+				threadexitsall("client pretended to be us");
 				return;
 			}
 		}
@@ -533,7 +536,7 @@ quit(void)
 {
 	reply("221 Successful termination\r\n");
 	close(0);
-	exits(0);
+	threadexitsall(0);
 }
 
 void
@@ -1063,6 +1066,7 @@ sendermxcheck(void)
 	char *who;
 	int pid;
 	Waitmsg *w;
+	static char *validate;
 
 	who = s_to_c(senders.first->p);
 	if(strcmp(who, "/dev/null") == 0){
@@ -1074,7 +1078,9 @@ sendermxcheck(void)
 		return 0;
 	}
 
-	if(access("/mail/lib/validatesender", AEXEC) < 0)
+	if(validate == nil)
+		validate = unsharp("#9/mail/lib/validatesender");
+	if(access(validate, AEXEC) < 0)
 		return 0;
 
 	senddom = strdup(who);
@@ -1095,9 +1101,9 @@ sendermxcheck(void)
 		 * Could add an option with the remote IP address
 		 * to allow validatesender to implement SPF eventually.
 		 */
-		execl("/mail/lib/validatesender", "validatesender", 
+		execl(validate, "validatesender", 
 			"-n", nci->root, senddom, user, nil);
-		_exits("exec validatesender: %r");
+		threadexitsall("exec validatesender: %r");
 	default:
 		break;
 	}
@@ -1265,7 +1271,7 @@ rejectcheck(void)
 	if(rejectcount > MAXREJECTS){
 		syslog(0, "smtpd", "Rejected (%s/%s)", him, nci->rsys);
 		reply("554 too many errors.  transaction failed.\r\n");
-		exits("errcount");
+		threadexitsall("errcount");
 	}
 	if(hardreject){
 		rejectcount++;
@@ -1344,7 +1350,7 @@ starttls(void)
 		/* force the client to hang up */
 		close(Bfildes(&bin));		/* probably fd 0 */
 		close(1);
-		exits("tls failed");
+		threadexitsall("tls failed");
 	}
 	Bterm(&bin);
 	Binit(&bin, fd, OREAD);