diff options
Diffstat (limited to 'imap/imapwrite.c')
| -rw-r--r-- | imap/imapwrite.c | 225 | 
1 files changed, 225 insertions, 0 deletions
| diff --git a/imap/imapwrite.c b/imap/imapwrite.c new file mode 100644 index 0000000..6167fa8 --- /dev/null +++ b/imap/imapwrite.c @@ -0,0 +1,225 @@ +/* +** Copyright 1998 - 2006 Double Precision, Inc. +** See COPYING for distribution information. +*/ + +#if	HAVE_CONFIG_H +#include	"config.h" +#endif +#include	<stdio.h> +#include	<stdlib.h> +#include	<string.h> +#include	<errno.h> +#if	HAVE_UNISTD_H +#include	<unistd.h> +#endif +#include	<sys/types.h> +#if TIME_WITH_SYS_TIME +#include        <sys/time.h> +#include        <time.h> +#else +#if HAVE_SYS_TIME_H +#include        <sys/time.h> +#else +#include        <time.h> +#endif +#endif + +#include	"imapwrite.h" + + +static char outbuf[BUFSIZ];	/* Ye olde output buffer */ +static size_t outbuf_cnt=0;	/* How much stuff's in ye olde output buffer */ + +extern FILE *debugfile; + +extern unsigned long bytes_sent_count; /* counter for sent bytes (imapwrite.c) */ + +extern void disconnected(); + +void writeflush() +{ +const char *p=outbuf; +unsigned s=outbuf_cnt; +time_t	t, tend; +fd_set	fds; +struct	timeval	tv; +int	n; + +	if (s == 0)	return; +	time(&t); +	tend=t+SOCKET_TIMEOUT; +	if (debugfile) +	{ +		fprintf(debugfile, "WRITE: "); +		if (fwrite(p, 1, s, debugfile) == 1) +			fprintf(debugfile, "\n"); +		fflush(debugfile); +	} +	while (t < tend) +	{ +		FD_ZERO(&fds); +		FD_SET(1, &fds); +		tv.tv_sec=tend-t; +		tv.tv_usec=0; +		/* BUG: if client closes connection BEFORE we flush it, select "stucks" +		 * until timeout. To workaround this, we should "write" first, and then +		 * if we get EPIPE connection is already closed. Othervise, try select +		 */ +		if ((n=write(1, p, s)) <= 0) +		{ +			if (errno == EPIPE || +				select(2, 0, &fds, 0, &tv) <= 0 || +				!FD_ISSET(1, &fds) || +				(n=write(1, p, s)) <= 0) +			{ +				disconnected(); +				return; +			} +		} +		bytes_sent_count += n; +		p += n; +		s -= n; +		if (s == 0)	break; +		time(&t); +	} +	if (s)	disconnected(); +	outbuf_cnt=0; +} + +void writemem(const char *s, size_t l) +{ +size_t	n; + +	while (l) +	{ +		n=sizeof(outbuf) - outbuf_cnt; + +		if (n >= l) +		{ +			memcpy(outbuf+outbuf_cnt, s, l); +			outbuf_cnt += l; +			break; +		} +		if (n == 0) +		{ +			writeflush(); +			continue; +		} +		if (n > l)	n=l; +		memcpy(outbuf+outbuf_cnt, s, n); +		outbuf_cnt += n; +		l -= n; +		s += n; +	} +} + +void writes(const char *s) +{ +	writemem(s, strlen(s)); +} + +void writen(unsigned long n) +{ +char	buf[40]; + +	sprintf(buf, "%lu", n); +	writemem(buf, strlen(buf)); +} + +void writeqs(const char *s) +{ +size_t	i=strlen(s), j; + +	while (i) +	{ +		for (j=0; j<i; j++) +		{ +			if ( s[j] == '"' || s[j] == '\\') +			{ +				writemem(s, j); +				writemem("\\", 1); +				writemem(s+j, 1); +				++j; +				s += j; +				i -= j; +				j=0; +				break; +			} +#if 0 +			if (s[j] == '&') +			{ +				writemem(s, j); +				writemem("&-", 2); +				++j; +				s += j; +				i -= j; +				j=0; +				break; +			} + +			if (s[j] < ' ' || s[j] >= 0x7F) +			{ +			char	*q; + +				writemem(s, j); +				++j; +				s += j; +				i -= j; +				for (j=0; j<i; j++) +					if (s[j] >= ' ' && s[j] < 0x7F) +						break; +				q=imap_utf7_encode(s, j); +				if (!q)	write_error_exit(0); +				writemem("&", 1); +				writes(q); +				writemem("-", 1); +				s += j; +				i -= j; +				j=0; +				break; +			} +#endif +		} +		writemem(s, j); +		s += j; +		i -= j; +	} +} + +void write_error_exit(const char *funcname) +{ +	outbuf_cnt=0; +	writes("* BYE [ALERT] Fatal error: "); +	if (funcname && *funcname) +	{ +		writes(funcname); +		writes(": "); +	} + +	if (errno) +	{ +#if	HAVE_STRERROR +	const	char *p; + +		p=strerror(errno); +#else +	char	p[40]; + +		sprintf(p, "Error %d", (int)errno); +#endif + + +		writes(p); +	} +	writes("\r\n"); +	writeflush(); + +	if (funcname && *funcname) +	{ +		fprintf(stderr, "ERR: %s: %s\n", getenv("AUTHENTICATED"), +			funcname); +		fflush(stderr); +	} +	_exit(1); +} | 
