Index: ssmtp-2.62/ssmtp.c
===================================================================
--- ssmtp-2.62.orig/ssmtp.c 2008-11-09 11:30:12.000000000 +0200
+++ ssmtp-2.62/ssmtp.c 2008-11-21 11:37:53.000000000 +0200
@@ -343,28 +343,26 @@
/*
standardise() -- Trim off '\n's and double leading dots
*/
-void standardise(char *str)
+bool_t standardise(char *str, bool_t *linestart)
{
size_t sl;
char *p;
-
- if((p = strchr(str, '\n'))) {
- *p = (char)NULL;
- }
+ bool_t leadingdot = False;
/* Any line beginning with a dot has an additional dot inserted;
- not just a line consisting solely of a dot. Thus we have to slide
- the buffer down one */
- sl = strlen(str);
+ not just a line consisting solely of a dot. Thus we have to move
+ the buffer start up one */
- if(*str == '.') {
- if((sl + 2) > BUF_SZ) {
- die("standardise() -- Buffer overflow");
- }
- (void)memmove((str + 1), str, (sl + 1)); /* Copy trailing \0 */
+ if(*linestart && *str == '.') {
+ leadingdot = True;
+ }
+ *linestart = False;
- *str = '.';
+ if((p = strchr(str, '\n'))) {
+ *p = (char)NULL;
+ *linestart = True;
}
+ return(leadingdot);
}
/*
@@ -1359,12 +1357,12 @@
*/
ssize_t smtp_write(int fd, char *format, ...)
{
- char buf[(BUF_SZ + 1)];
+ char buf[(BUF_SZ + 2)];
va_list ap;
ssize_t outbytes = 0;
va_start(ap, format);
- if(vsnprintf(buf, (BUF_SZ - 2), format, ap) == -1) {
+ if(vsnprintf(buf, (BUF_SZ - 1), format, ap) == -1) {
die("smtp_write() -- vsnprintf() failed");
}
va_end(ap);
@@ -1402,16 +1400,18 @@
*/
int ssmtp(char *argv[])
{
- char buf[(BUF_SZ + 1)], *p, *q;
+ char b[(BUF_SZ + 2)], *buf = b+1, *p, *q;
#ifdef MD5AUTH
char challenge[(BUF_SZ + 1)];
#endif
struct passwd *pw;
int i, sock;
uid_t uid;
- bool_t minus_v_save;
+ bool_t minus_v_save, leadingdot, linestart = True;
int timeout = 0;
+ int bufsize = sizeof(b)-1;
+ b[0] = '.';
outbytes = 0;
ht = &headers;
@@ -1494,12 +1494,12 @@
}
strncpy(challenge, strchr(buf,' ') + 1, sizeof(challenge));
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, bufsize);
crammd5(challenge, auth_user, auth_pass, buf);
}
else {
#endif
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, bufsize);
to64frombits(buf, auth_user, strlen(auth_user));
if (use_oldauth) {
outbytes += smtp_write(sock, "AUTH LOGIN %s", buf);
@@ -1511,7 +1511,7 @@
die("Server didn't like our AUTH LOGIN (%s)", buf);
}
/* we assume server asked us for Username */
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, bufsize);
to64frombits(buf, auth_user, strlen(auth_user));
outbytes += smtp_write(sock, buf);
}
@@ -1520,7 +1520,7 @@
if(smtp_read(sock, buf) != 3) {
die("Server didn't accept AUTH LOGIN (%s)", buf);
}
- memset(buf, 0, sizeof(buf));
+ memset(buf, 0, bufsize);
to64frombits(buf, auth_pass, strlen(auth_pass));
#ifdef MD5AUTH
@@ -1629,28 +1629,40 @@
stdio functions like fgets in the first place */
fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
- /* don't hang forever when reading from stdin */
- while(!feof(stdin) && timeout < MEDWAIT) {
- if (!fgets(buf, sizeof(buf), stdin)) {
+ while(!feof(stdin)) {
+ if (!fgets(buf, bufsize, stdin)) {
/* if nothing was received, then no transmission
* over smtp should be done */
sleep(1);
- timeout++;
+ /* don't hang forever when reading from stdin */
+ if (++timeout >= MEDWAIT) {
+ log_event(LOG_ERR, "killed: timeout on stdin while reading body -- message saved to dead.letter.");
+ die("Timeout on stdin while reading body");
+ }
continue;
}
/* Trim off \n, double leading .'s */
- standardise(buf);
-
- outbytes += smtp_write(sock, "%s", buf);
+ leadingdot = standardise(buf, &linestart);
+ if (linestart || feof(stdin)) {
+ linestart = True;
+ outbytes += smtp_write(sock, "%s", leadingdot ? b : buf);
+ } else {
+ if (log_level > 0) {
+ log_event(LOG_INFO, "Sent a very long line in chunks");
+ }
+ if (leadingdot) {
+ outbytes += fd_puts(sock, b, sizeof(b));
+ } else {
+ outbytes += fd_puts(sock, buf, bufsize);
+ }
+ }
(void)alarm((unsigned) MEDWAIT);
}
- /* End of body */
-
- if (timeout >= MEDWAIT) {
- log_event(LOG_ERR, "killed: timeout on stdin while reading body -- message saved to dead.letter.");
- die("Timeout on stdin while reading body");
+ if(!linestart) {
+ smtp_write(sock, "");
}
+ /* End of body */
outbytes += smtp_write(sock, ".");
(void)alarm((unsigned) MAXWAIT);