/*
* Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
* All rights reserved.
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* By using this file, you agree to the terms and conditions set
* forth in the LICENSE file which can be found at the top level of
* the sendmail distribution.
*/
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <fcntl.h>
#include "local.h"
#include "fvwrite.h"
/*
** SM_FVWRITE -- write memory regions and buffer for file pointer
**
** Parameters:
** fp -- the file pointer to write to
** timeout -- time length for function to return by
** uio -- the memory regions to write
**
** Returns:
** Failure: returns SM_IO_EOF and sets errno
** Success: returns 0 (zero)
**
** This routine is large and unsightly, but most of the ugliness due
** to the different kinds of output buffering handled here.
*/
while (len == 0) \
{ \
extra_work; \
iov++; \
}
int
int timeout;
{
register char *p;
register int w, s;
char *nl;
int fd;
return 0;
/* make sure we can write */
{
return SM_IO_EOF;
}
iov++;
{
/* Unbuffered: write up to BUFSIZ bytes at a time. */
do
{
GETIOV(;);
errno = 0; /* needed to ensure EOF correctly found */
if (w <= 0)
{
if (w == 0 && errno == 0)
break; /* EOF found */
goto err; /* errno set */
/* write would block */
w = 0;
}
else
{
p += w;
len -= w;
}
}
{
/*
** Not SMLBF (line-buffered). Either SMFBF or SMNOW
** buffered: fill partially full buffer, if any,
** and then flush. If there is no partial buffer, write
** one bf._size byte chunk directly (without copying).
**
** String output is a special case: write as many bytes
** as fit, but pretend we wrote everything. This makes
** snprintf() return the number of bytes needed, rather
** than the number used, and avoids its write function
** (so that the write function can be invalid).
*/
do
{
GETIOV(;);
{
unsigned char *tbase;
int tsize;
/* Allocate space exponentially. */
do
{
tsize + 1);
{
goto err; /* errno set */
}
}
errno = 0; /* needed to ensure EOF correctly found */
{
w = len;
COPY(w); /* copy SM_MIN(fp->f_w,len), */
w = len; /* but pretend copied all */
}
{
/* fill and flush */
COPY(w);
goto err; /* errno set */
}
{
/* write directly */
if (w <= 0)
{
if (w == 0 && errno == 0)
break; /* EOF found */
goto err; /* errno set */
/* write would block */
w = 0;
}
}
else
{
/* fill and done */
w = len;
COPY(w);
}
p += w;
len -= w;
goto err; /* errno set */
}
else
{
/*
** Line buffered: like fully buffered, but we
** must check for newlines. Compute the distance
** to the first newline (including the newline),
** or `infinity' if there is none, then pretend
** that the amount to write is SM_MIN(len,nldist).
*/
nlknown = 0;
nldist = 0; /* XXX just to keep gcc happy */
do
{
if (!nlknown)
{
nlknown = 1;
}
errno = 0; /* needed to ensure EOF correctly found */
{
COPY(w);
/* fp->f_w -= w; */
goto err; /* errno set */
}
{
if (w <= 0)
{
if (w == 0 && errno == 0)
break; /* EOF found */
goto err; /* errno set */
/* write would block */
w = 0;
}
}
else
{
w = s;
COPY(w);
}
if ((nldist -= w) == 0)
{
/* copied the newline: flush and forget */
goto err; /* errno set */
nlknown = 0;
}
p += w;
len -= w;
}
return 0;
err:
/* errno set before goto places us here */
return SM_IO_EOF;
}