[Raw Msg Headers][Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A bunch of problems with zmailer




...
> >   expn and vrfy can be quite expensive in Zmailer, so I normally disable
> > their use.  There is a command-line option that tells the smtpserver to
> > enable vrfy/expn.  The smtpserver actually handles an expn/vrfy request by
> > forking a router,and execs server() in server.cf
> 
> Well, it seems there is another problem. I prints the verifiyed address
> just fine, but then emits "5.4.0 Unable to verify that address":
> 
> expn test1@uni-paderborn.de
> 250-Ursula Schwolle <ulla>
> 250-Swen Thuemmler <swen>
> 250 Ursula Schwolle <ulla>
> 501 5.4.0 Unable to verify that address

	I have now spend a few hours with debuggers on this, and it
	is entirely smtpserver problem.  Investigation continues.
	... fixed it!  Rewrote the interface-routines to get less
	complex logic into response reader.

	Diff at the end.

> Another problem: this does not work from remote:
> 220 uni-paderborn.de ZMailer Server 2.99.42 #1 ESMTP+IDENT ready at Wed, 27 Nov 1996 15:23:44 +0100
> helo linux.uni-paderborn.de
> 250 uni-paderborn.de Hello linux.uni-paderborn.de
> vrfy test1@uni-paderborn.de
> Connection closed by foreign host.
> 
> All I get is a closed connection :(

	Odd..  How about trying to attach a debugger on it before
	doing "helo" ?  Or very least before doing "vrfy" ?

> > > 5. A warning. Don't compile with -xO2 on solaris, this seems to break
> > > mailbox and some other programs. We had some cases of lost mail (most in
> > > combination with elm).
> > 
> >   This would be compiler dependant.  Is this the Sunsoft or GCC compiler?
> > (I guess Sunsoft...)
> 
> Yep, Sunsoft. Next compile will be with gcc.
> 
> >   This isn't needed.  The scheduler will not attempt to establish more
> > than one smtp connection at a time with any particular host.
> 
> Great. But I'm still puzzled by the warning from scheduler. According to
> the manualpage, the expample code should work. Hmm.

	The selector definitions start from column 0, parameters start
	indented at least by one white-space character.
	That is, you really had a selector specification that does not
	have any parameters, then a selector with some:

smtp/*some.pattern
smtp/*other.pattern
	params=....

	... and keep in mind, the documents do describe the old-scheduler,
	though it should not have accepted this either.

> Greetings, Swen

	/Matti Aarnio <mea@nic.funet.fi>

diff -u -r ../zmailer-2.99.42/smtpserver/smtpserver.c ./smtpserver/smtpserver.c
--- ../zmailer-2.99.42/smtpserver/smtpserver.c	Mon Nov 18 09:55:20 1996
+++ ./smtpserver/smtpserver.c	Wed Nov 27 21:20:15 1996
@@ -180,6 +180,7 @@
 char	rhostname[MAXHOSTNAMELEN+1];
 char	ihostaddr[3*4+1*3+2+1 /* == 18 for '[255.255.255.255]' */ +10/*slack*/];
 int	rport;
+int	debug	   = 0;
 int	skeptical  = 1;
 int	checkhelo  = 0;
 int	verbose    = 0;
@@ -368,7 +369,7 @@
 	  exit(1);
 	}
 	/* optarg = NULL; */
-	while ((c = getopt(argc, argv, "aBighl:np:L:M:P:R:s:Vv")) != EOF) {
+	while ((c = getopt(argc, argv, "aBd:ighl:np:L:M:P:R:s:Vv")) != EOF) {
 	  switch (c) {
 	    case 'a':
 		ident_flag = 1;
@@ -376,6 +377,9 @@
 	    case 'B':
 		with_protocol = WITH_BSMTP;
 		break;
+	    case 'd':
+		debug = atoi(optarg);
+		break;
 	    case 'M':
 		maxsize = atoi(optarg);
 		if (maxsize < 0)
@@ -2023,8 +2027,8 @@
 		if ((cfi = STYLE(cfinfo, 'v'))) {
 		  char *s;
 		  if ((s = router(RKEY_VERIFY, 0, cp)) != NULL) {
-		    printf("%s\r\n", s);
-		    free(s);
+		    /* printf("%s\r\n", s);
+		       free(s); */
 		  } else
 		    type(501,m540, "Unable to verify that address");
 		} else
@@ -2055,8 +2059,8 @@
 		    break;
 		  }
 		  if ((s = router(RKEY_EXPAND, 0, cp)) != NULL) {
-		    printf("%s\r\n", s);
-		    free(s);
+		    /* printf("%s\r\n", s);
+		       free(s); */
 		  } else
 		    type(501,m540, "Unable to verify that address");
 		} else
@@ -2370,19 +2374,22 @@
 int  promptlen;
 FILE *tofp, *fromfp;
 
+extern char *mgets __((char **, int *, FILE *));
 char *
-mgets(buf, flagp, fp)
-	char *buf;	/* this is what I returned earlier, if non-null */
+mgets(bufp, flagp, fp)
+	char **bufp;	/* this is what I returned earlier, if non-null */
 	int *flagp;
 	FILE *fp;
 {
 	register int bufsize, c;
 	register char *cp;
-	char *s;
-	static char *obuf = NULL;
-	
-	if (buf != NULL)
-	  free(buf);
+	char *buf;
+	int ccnt = 0;
+
+	if (*bufp != NULL)
+	  free(*bufp);
+	*bufp = NULL;
+
 	if (*flagp) {
 	  *flagp = 0;
 	  return NULL;
@@ -2392,6 +2399,7 @@
 	cp = buf = emalloc(bufsize);
 	while ((c = getc(fp)) != EOF) {
 	  *cp = c;
+	  ++ccnt;
 	  if (c == '\n') {
 	    *flagp = 0;
 	    break;
@@ -2399,31 +2407,31 @@
 	  ++cp;
 	  if (strncmp(cp - promptlen, promptbuf, promptlen) == 0) {
 	    free(buf);
+	    buf = NULL;
 	    *flagp = 1;
-	    break;
+	    return NULL;
 	  }
-	  if (bufsize - 2 < cp - buf) {
-	    bufsize *= 2;
-	    s = erealloc(buf, bufsize);
-	    cp  = s + (cp - buf);
-	    buf = s;
+	  if (bufsize - 2 < ccnt) {
+	    bufsize <<= 1;
+	    buf = erealloc(buf, bufsize);
+	    cp  = buf + ccnt;
 	  }
 	}
+
+	if (buf)
+	  *cp = '\0';
+
+	if (debug && buf)
+	  fprintf(stdout, "000 '%s'\r\n",buf);
+
 	if (c == EOF) {
 	  printf("got EOF!\n");
 	  free(buf);
 	  return NULL;
 	}
-	*cp = '\0';
-	if (obuf == NULL) {
-	  if (*flagp)
-	    return obuf;
-	  obuf = buf;
-	  return mgets((char *)NULL, flagp, fp);
-	}
-	cp = obuf;
-	obuf = *flagp ? NULL : buf;
-	return cp;
+
+	*bufp = buf;
+	return buf;
 }
 
 char *newenviron[] = { "SMTPSERVER=y", (char *)0 };
@@ -2432,7 +2440,7 @@
 callr()
 {
 	int sawend, pid, to[2], from[2];
-	char *buf, *cp;
+	char *bufp, *cp;
 
 	if (pipe(to) < 0 || pipe(from) < 0)
 		return -1;
@@ -2445,12 +2453,12 @@
 	SIGNAL_HANDLE(SIGPIPE, SIG_IGN);
 
 	if (routerprog == NULL) {
-	  if ((buf = getzenv("MAILBIN")) == NULL) {
+	  if ((cp = getzenv("MAILBIN")) == NULL) {
 	    syslog(LOG_ERR, "MAILBIN unspecified in zmailer.conf");
 	    return -1;
 	  }
-	  routerprog = emalloc(strlen(buf)+sizeof "router"+2);
-	  sprintf(routerprog, "%s/router", buf);
+	  routerprog = emalloc(strlen(cp)+sizeof "router"+2);
+	  sprintf(routerprog, "%s/router", cp);
 	}
 
 	if ((pid = fork()) == 0) { /* child */
@@ -2492,16 +2500,18 @@
 		      ROUTER_SERVER, RKEY_INIT, rhostname, ihostaddr);
 	fflush(tofp);
 
-	buf = NULL;
+	bufp = NULL;
 	sawend = 0;
-	while ((buf = mgets(buf, &sawend, fromfp)) != NULL) {
-	  if (strncmp(buf, BADEXEC, strlen(BADEXEC)-2) == 0) {
-	    free(buf);
+	while ((cp = mgets(&bufp, &sawend, fromfp)) != NULL) {
+	  if (strncmp(cp, BADEXEC, strlen(BADEXEC)-2) == 0) {
+	    free(cp);
 	    killr(pid);
 	    return -1;
 	  }
 	  /*printf("241%c%s\n", sawend == 1 ? ' ' : '-', buf);*/
 	}
+	if (bufp)
+	  free(bufp);
 
 	return pid;
 }
@@ -2527,8 +2537,8 @@
 	char *function, *args;
 	int holdlast;
 {
-	char *buf, *holdcp;
-	int sawend;
+	char *bufp, *holdcp, *prevb = NULL;
+	int sawend, anyresult = 0;
 
 	if (args == NULL) {
 	  type(501,NULL,NULL);
@@ -2553,31 +2563,51 @@
 	fprintf(tofp, "\"\n");
 	fflush(tofp);
 
-	buf = holdcp = NULL;
+	bufp = NULL;
+	holdcp = NULL;
 	sawend = 0;
-	while (!sawend && (buf = mgets(buf, &sawend, fromfp)) != NULL) {
+	for (;;) {
 	  /*
 	   * We want to give the router the opportunity to report
 	   * result codes, e.g. for boolean requests.  If the first
 	   * three characters are digits and the 4th a space or '-',
 	   * then pass through.
 	   */
-	  if (strlen(buf) > 4 &&
+	  char *buf = mgets(&bufp, &sawend, fromfp);
+
+	  if (buf && strlen(buf) > 4 &&
 	      isdigit(buf[0]) && isdigit(buf[1]) && isdigit(buf[2])
 	      && (buf[3] == ' ' || buf[3] == '-')) {
 	    if (holdlast && buf[3] == ' ')
 	      holdcp = buf;
 	    else
 	      printf("%s\r\n", buf);
+	    anyresult = 1;
 	  } else {
-	    if (holdlast && sawend)
-	      holdcp = buf;
-	    else
-	      printf("250%c%s\r\n",
-		     sawend == 1 ? ' ' : '-', buf);
+	    if (holdlast && sawend) {
+	      holdcp = prevb;
+	      anyresult = 1;
+	    } else
+	      if (prevb && !sawend) {
+		printf("250-%s\r\n", prevb);
+		anyresult = 1;
+	      } else if (prevb && sawend) {
+		printf("250 %s\r\n", prevb);
+		anyresult = 1;
+	      }
+
+	    if (prevb != holdcp)
+	      free(prevb);
+	    prevb = bufp;
+	    bufp = NULL;
 	  }
+	  if (!buf) break;
 	}
+	if (bufp && bufp != holdcp)
+	  free(bufp);
 	fflush(stdout);
+	if (!holdlast && anyresult)
+	  return "*any*result*"; /* Flag */
 	return holdcp;
 }