Beispiel #1
0
/*
 * Send message described by the passed pointer to the
 * passed output buffer.  Return -1 on error.
 * Adjust the status: field if need be.
 * If doign is given, suppress ignored header fields.
 * prefix is a string to prepend to each output line.
 */
int
sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
	    char *prefix)
{
	int count;
	FILE *ibuf;
	char line[LINESIZE];
	char visline[4 * LINESIZE - 3];
	int ishead, infld, ignoring = 0, dostat, firstline;
	char *cp, *cp2;
	int c = 0;
	int length;
	int prefixlen = 0;
	int rval;
	int dovis;
	struct sigaction act, saveint;
	sigset_t oset;

	sendsignal = 0;
	rval = -1;
	dovis = isatty(fileno(obuf));
	sigemptyset(&act.sa_mask);
	act.sa_flags = SA_RESTART;
	act.sa_handler = sendint;
	(void)sigaction(SIGINT, &act, &saveint);
	(void)sigprocmask(SIG_UNBLOCK, &intset, &oset);

	/*
	 * Compute the prefix string, without trailing whitespace
	 */
	if (prefix != NULL) {
		cp2 = 0;
		for (cp = prefix; *cp; cp++)
			if (*cp != ' ' && *cp != '\t')
				cp2 = cp;
		prefixlen = cp2 == 0 ? 0 : cp2 - prefix + 1;
	}
	ibuf = setinput(mp);
	count = mp->m_size;
	ishead = 1;
	dostat = doign == 0 || !isign("status", doign);
	infld = 0;
	firstline = 1;
	/*
	 * Process headers first
	 */
	while (count > 0 && ishead) {
		if (fgets(line, sizeof(line), ibuf) == NULL)
			break;
		count -= length = strlen(line);
		if (firstline) {
			/*
			 * First line is the From line, so no headers
			 * there to worry about
			 */
			firstline = 0;
			ignoring = doign == ignoreall;
		} else if (line[0] == '\n') {
			/*
			 * If line is blank, we've reached end of
			 * headers, so force out status: field
			 * and note that we are no longer in header
			 * fields
			 */
			if (dostat) {
				if (statusput(mp, obuf, prefix) == -1)
					goto out;
				dostat = 0;
			}
			ishead = 0;
			ignoring = doign == ignoreall;
		} else if (infld && (line[0] == ' ' || line[0] == '\t')) {
			/*
			 * If this line is a continuation (via space or tab)
			 * of a previous header field, just echo it
			 * (unless the field should be ignored).
			 * In other words, nothing to do.
			 */
		} else {
			/*
			 * Pick up the header field if we have one.
			 */
			for (cp = line; (c = *cp++) && c != ':' && !isspace(c);)
				;
			cp2 = --cp;
			while (isspace(*cp++))
				;
			if (cp[-1] != ':') {
				/*
				 * Not a header line, force out status:
				 * This happens in uucp style mail where
				 * there are no headers at all.
				 */
				if (dostat) {
					if (statusput(mp, obuf, prefix) == -1)
						goto out;
					dostat = 0;
				}
				if (doign != ignoreall)
					/* add blank line */
					(void)putc('\n', obuf);
				ishead = 0;
				ignoring = 0;
			} else {
				/*
				 * If it is an ignored field and
				 * we care about such things, skip it.
				 */
				*cp2 = 0;	/* temporarily null terminate */
				if (doign && isign(line, doign))
					ignoring = 1;
				else if (strcasecmp(line, "status") == 0) {
					/*
					 * If the field is "status," go compute
					 * and print the real Status: field
					 */
					if (dostat) {
						if (statusput(mp, obuf, prefix) == -1)
							goto out;
						dostat = 0;
					}
					ignoring = 1;
				} else {
					ignoring = 0;
					*cp2 = c;	/* restore */
				}
				infld = 1;
			}
		}
		if (!ignoring) {
			/*
			 * Strip trailing whitespace from prefix
			 * if line is blank.
			 */
			if (prefix != NULL) {
				if (length > 1)
					fputs(prefix, obuf);
				else
					(void)fwrite(prefix, sizeof(*prefix),
							prefixlen, obuf);
			}
			if (dovis) {
				length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH);
				(void)fwrite(visline, sizeof(*visline), length, obuf);
			} else
				(void)fwrite(line, sizeof(*line), length, obuf);
			if (ferror(obuf))
				goto out;
		}
		if (sendsignal == SIGINT)
			goto out;
	}
	/*
	 * Copy out message body
	 */
	if (doign == ignoreall)
		count--;		/* skip final blank line */
	while (count > 0) {
		if (fgets(line, sizeof(line), ibuf) == NULL) {
			c = 0;
			break;
		}
		count -= c = strlen(line);
		if (prefix != NULL) {
			/*
			 * Strip trailing whitespace from prefix
			 * if line is blank.
			 */
			if (c > 1)
				fputs(prefix, obuf);
			else
				(void)fwrite(prefix, sizeof(*prefix),
						prefixlen, obuf);
		}
		/*
		 * We can't read the record file (or inbox for recipient)
		 * properly with 'From ' lines in the message body (from
		 * forwarded messages or sentences starting with "From "),
		 * so we will prepend those lines with a '>'.
		 */
		if (strncmp(line, "From ", 5) == 0)
			(void)fwrite(">", 1, 1, obuf); /* '>' before 'From ' */
		if (dovis) {
			length = strvis(visline, line, VIS_SAFE|VIS_NOSLASH);
			(void)fwrite(visline, sizeof(*visline), length, obuf);
		} else
			(void)fwrite(line, sizeof(*line), c, obuf);
		if (ferror(obuf) || sendsignal == SIGINT)
			goto out;
	}
	if (doign == ignoreall && c > 0 && line[c - 1] != '\n')
		/* no final blank line */
		if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
			goto out;
	rval = 0;
out:
	sendsignal = 0;
	(void)sigprocmask(SIG_SETMASK, &oset, NULL);
	(void)sigaction(SIGINT, &saveint, NULL);
	return(rval);
}
Beispiel #2
0
/*
 * Send message described by the passed pointer to the
 * passed output buffer.  Return -1 on error.
 * Adjust the status: field if need be.
 * If doign is given, suppress ignored header fields.
 * prefix is a string to prepend to each output line.
 */
int
sendmessage(struct message *mp, FILE *obuf, struct ignoretab *doign,
	char *prefix)
{
	long count;
	FILE *ibuf;
	char *cp, *cp2, line[LINESIZE];
	int ishead, infld, ignoring, dostat, firstline;
	int c = 0, length, prefixlen;

	/*
	 * Compute the prefix string, without trailing whitespace
	 */
	if (prefix != NULL) {
		cp2 = 0;
		for (cp = prefix; *cp != '\0'; cp++)
			if (*cp != ' ' && *cp != '\t')
				cp2 = cp;
		prefixlen = cp2 == NULL ? 0 : cp2 - prefix + 1;
	}
	ibuf = setinput(mp);
	count = mp->m_size;
	ishead = 1;
	dostat = doign == 0 || !isign("status", doign);
	infld = 0;
	firstline = 1;
	/*
	 * Process headers first
	 */
	while (count > 0 && ishead) {
		if (fgets(line, sizeof(line), ibuf) == NULL)
			break;
		count -= length = strlen(line);
		if (firstline) {
			/*
			 * First line is the From line, so no headers
			 * there to worry about
			 */
			firstline = 0;
			ignoring = doign == ignoreall;
		} else if (line[0] == '\n') {
			/*
			 * If line is blank, we've reached end of
			 * headers, so force out status: field
			 * and note that we are no longer in header
			 * fields
			 */
			if (dostat) {
				statusput(mp, obuf, prefix);
				dostat = 0;
			}
			ishead = 0;
			ignoring = doign == ignoreall;
		} else if (infld && (line[0] == ' ' || line[0] == '\t')) {
			/*
			 * If this line is a continuation (via space or tab)
			 * of a previous header field, just echo it
			 * (unless the field should be ignored).
			 * In other words, nothing to do.
			 */
		} else {
			/*
			 * Pick up the header field if we have one.
			 */
			for (cp = line; (c = *cp++) != '\0' && c != ':' &&
			    !isspace((unsigned char)c);)
				;
			cp2 = --cp;
			while (isspace((unsigned char)*cp++))
				;
			if (cp[-1] != ':') {
				/*
				 * Not a header line, force out status:
				 * This happens in uucp style mail where
				 * there are no headers at all.
				 */
				if (dostat) {
					statusput(mp, obuf, prefix);
					dostat = 0;
				}
				if (doign != ignoreall)
					/* add blank line */
					(void)putc('\n', obuf);
				ishead = 0;
				ignoring = 0;
			} else {
				/*
				 * If it is an ignored field and
				 * we care about such things, skip it.
				 */
				*cp2 = '\0';	/* temporarily null terminate */
				if (doign && isign(line, doign))
					ignoring = 1;
				else if ((line[0] == 's' || line[0] == 'S') &&
					 strcasecmp(line, "status") == 0) {
					/*
					 * If the field is "status," go compute
					 * and print the real Status: field
					 */
					if (dostat) {
						statusput(mp, obuf, prefix);
						dostat = 0;
					}
					ignoring = 1;
				} else {
					ignoring = 0;
					*cp2 = c;	/* restore */
				}
				infld = 1;
			}
		}
		if (!ignoring) {
			/*
			 * Strip trailing whitespace from prefix
			 * if line is blank.
			 */
			if (prefix != NULL) {
				if (length > 1)
					fputs(prefix, obuf);
				else
					(void)fwrite(prefix, sizeof(*prefix),
					    prefixlen, obuf);
			}
			(void)fwrite(line, sizeof(*line), length, obuf);
			if (ferror(obuf))
				return (-1);
		}
	}
	/*
	 * Copy out message body
	 */
	if (doign == ignoreall)
		count--;		/* skip final blank line */
	if (prefix != NULL)
		while (count > 0) {
			if (fgets(line, sizeof(line), ibuf) == NULL) {
				c = 0;
				break;
			}
			count -= c = strlen(line);
			/*
			 * Strip trailing whitespace from prefix
			 * if line is blank.
			 */
			if (c > 1)
				fputs(prefix, obuf);
			else
				(void)fwrite(prefix, sizeof(*prefix),
				    prefixlen, obuf);
			(void)fwrite(line, sizeof(*line), c, obuf);
			if (ferror(obuf))
				return (-1);
		}
	else
		while (count > 0) {
			c = count < LINESIZE ? count : LINESIZE;
			if ((c = fread(line, sizeof(*line), c, ibuf)) <= 0)
				break;
			count -= c;
			if (fwrite(line, sizeof(*line), c, obuf) != c)
				return (-1);
		}
	if (doign == ignoreall && c > 0 && line[c - 1] != '\n')
		/* no final blank line */
		if ((c = getc(ibuf)) != EOF && putc(c, obuf) == EOF)
			return (-1);
	return (0);
}
Beispiel #3
0
/*
 * Send message described by the passed pointer to the
 * passed output buffer.  Return -1 on error, but normally
 * the number of lines written.  Adjust the status: field
 * if need be.  If doign is set, suppress ignored header fields.
 * Call (*fp)(line, obuf) to print the line.
 */
long
msend(
	struct message *mailp,
	FILE *obuf,
	int flag,
	int (*fp)(const char *, FILE *))
{
	register struct message *mp;
	long clen, n, c;
	FILE *ibuf;
	char line[LINESIZE], field[BUFSIZ];
	int ishead, infld, fline, dostat, doclen, nread, unused;
	char *cp, *cp2;
	int doign = flag & M_IGNORE;
	int oldign = 0;	/* previous line was ignored */
	long lc;

	mp = mailp;
	if (mp->m_clen == 0)
		setclen(mp);
	ibuf = setinput(mp);
	c = mp->m_size;
	ishead = 1;
	dostat = 1;
	doclen = 1;
	infld = 0;
	fline = 1;
	lc = 0;
	clearerr(obuf);
	while (c > 0L) {
		nread = getaline(line, LINESIZE, ibuf, &unused);
		c -= nread;
		lc++;
		if (ishead) {
			/*
			 * First line is the From line, so no headers
			 * there to worry about
			 */
			if (fline) {
				fline = 0;
				goto writeit;
			}
			/*
			 * If line is blank, we've reached end of
			 * headers, so force out status: field
			 * and note that we are no longer in header
			 * fields.  Also force out Content-Length: field.
			 */
			if (line[0] == '\n') {
				if (dostat) {
					statusput(mailp, obuf, doign, fp);
					dostat = 0;
				}
				if (doclen &&
				    !isign("content-length", flag&M_SAVING)) {
					snprintf(field, sizeof (field),
						"Content-Length: %ld\n",
						mp->m_clen - 1);
					(*fp)(field, obuf);
					if (ferror(obuf))
						return(-1);
					doclen = 0;
				}
				ishead = 0;
				goto writeit;
			}
			/*
			 * If this line is a continuation
			 * of a previous header field, just echo it.
			 */
			if (isspace(line[0]) && infld)
				if (oldign)
					continue;
				else
					goto writeit;
			infld = 0;
			/*
			 * If we are no longer looking at real
			 * header lines, force out status:
			 * This happens in uucp style mail where
			 * there are no headers at all.
			 */
			if (!headerp(line)) {
				if (dostat) {
					statusput(mailp, obuf, doign, fp);
					dostat = 0;
				}
				(*fp)("\n", obuf);
				ishead = 0;
				goto writeit;
			}
			infld++;
			/*
			 * Pick up the header field.
			 * If it is an ignored field and
			 * we care about such things, skip it.
			 */
			cp = line;
			cp2 = field;
			while (*cp && *cp != ':' && !isspace(*cp))
				*cp2++ = *cp++;
			*cp2 = 0;
			oldign = doign && isign(field, flag&M_SAVING);
			if (oldign)
				continue;
			/*
			 * If the field is "status," go compute and print the
			 * real Status: field
			 */
			if (icequal(field, "status")) {
				if (dostat) {
					statusput(mailp, obuf, doign, fp);
					dostat = 0;
				}
				continue;
			}
			if (icequal(field, "content-length")) {
				if (doclen) {
					snprintf(line, sizeof (line),
						"Content-Length: %ld\n",
						mp->m_clen - 1);
					(*fp)(line, obuf);
					if (ferror(obuf))
						return(-1);
					doclen = 0;
				}
				continue;
			}
		}
writeit:
		if (!ishead && !mp->m_text && mp->m_clen != 0) {
			if (line[0] == '\n')
				putc('\n', obuf);
			clen = mp->m_clen-1;
			for (;;) {
				n = clen < sizeof line ? clen : sizeof line;
				if ((n = fread(line, 1, (int)n, ibuf)) <= 0) {
					fprintf(stderr, gettext(
					    "\t(Unexpected end-of-file).\n"));
					clen = 0;
				} else {
					if (fwrite(line, 1, (int)n, obuf) != n) {
						fprintf(stderr, gettext(
					"\tError writing to the new file.\n"));
						fflush(obuf);
						if (fferror(obuf))
							return (-1);
					}
				}
				clen -= n;
				if (clen <= 0) {
					break;
				}
			}
			c = 0L;
		} else {
			(*fp)(line, obuf);
			if (ferror(obuf))
				return(-1);
		}
	}
	fflush(obuf);
	if (ferror(obuf))
		return(-1);
	if (ishead && (mailp->m_flag & MSTATUS))
		printf(gettext("failed to fix up status field\n"));
	return(lc);
}