8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sendmail / libsm / fvwrite.c
blob4cdd022fe0b1ac65ea0398eb5d314e638b0c3cc6
1 /*
2 * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * Chris Torek.
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include <sm/gen.h>
18 SM_RCSID("@(#)$Id: fvwrite.c,v 1.47 2001/08/27 13:02:20 ca Exp $")
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <string.h>
22 #include <errno.h>
23 #include <signal.h>
24 #include <fcntl.h>
25 #include <sm/io.h>
26 #include <sm/setjmp.h>
27 #include <sm/conf.h>
28 #include "local.h"
29 #include "fvwrite.h"
32 ** SM_FVWRITE -- write memory regions and buffer for file pointer
34 ** Parameters:
35 ** fp -- the file pointer to write to
36 ** timeout -- time length for function to return by
37 ** uio -- the memory regions to write
39 ** Returns:
40 ** Failure: returns SM_IO_EOF and sets errno
41 ** Success: returns 0 (zero)
43 ** This routine is large and unsightly, but most of the ugliness due
44 ** to the different kinds of output buffering handled here.
47 #define COPY(n) (void)memcpy((void *)fp->f_p, (void *)p, (size_t)(n))
48 #define GETIOV(extra_work) \
49 while (len == 0) \
50 { \
51 extra_work; \
52 p = iov->iov_base; \
53 len = iov->iov_len; \
54 iov++; \
57 int
58 sm_fvwrite(fp, timeout, uio)
59 register SM_FILE_T *fp;
60 int timeout;
61 register struct sm_uio *uio;
63 register size_t len;
64 register char *p;
65 register struct sm_iov *iov;
66 register int w, s;
67 char *nl;
68 int nlknown, nldist;
69 int fd;
70 struct timeval to;
72 if (uio->uio_resid == 0)
73 return 0;
75 /* make sure we can write */
76 if (cantwrite(fp))
78 errno = EBADF;
79 return SM_IO_EOF;
82 SM_CONVERT_TIME(fp, fd, timeout, &to);
84 iov = uio->uio_iov;
85 p = iov->iov_base;
86 len = iov->iov_len;
87 iov++;
88 if (fp->f_flags & SMNBF)
90 /* Unbuffered: write up to BUFSIZ bytes at a time. */
93 GETIOV(;);
94 errno = 0; /* needed to ensure EOF correctly found */
95 w = (*fp->f_write)(fp, p, SM_MIN(len, SM_IO_BUFSIZ));
96 if (w <= 0)
98 if (w == 0 && errno == 0)
99 break; /* EOF found */
100 if (IS_IO_ERROR(fd, w, timeout))
101 goto err; /* errno set */
103 /* write would block */
104 SM_IO_WR_TIMEOUT(fp, fd, timeout);
105 w = 0;
107 else
109 p += w;
110 len -= w;
112 } while ((uio->uio_resid -= w) != 0);
114 else if ((fp->f_flags & SMLBF) == 0)
117 ** Not SMLBF (line-buffered). Either SMFBF or SMNOW
118 ** buffered: fill partially full buffer, if any,
119 ** and then flush. If there is no partial buffer, write
120 ** one bf._size byte chunk directly (without copying).
122 ** String output is a special case: write as many bytes
123 ** as fit, but pretend we wrote everything. This makes
124 ** snprintf() return the number of bytes needed, rather
125 ** than the number used, and avoids its write function
126 ** (so that the write function can be invalid).
131 GETIOV(;);
132 if ((((fp->f_flags & (SMALC | SMSTR)) == (SMALC | SMSTR))
133 || ((fp->f_flags & SMNOW) != 0))
134 && (size_t) fp->f_w < len)
136 size_t blen = fp->f_p - fp->f_bf.smb_base;
137 unsigned char *tbase;
138 int tsize;
140 /* Allocate space exponentially. */
141 tsize = fp->f_bf.smb_size;
144 tsize = (tsize << 1) + 1;
145 } while ((size_t) tsize < blen + len);
146 tbase = (unsigned char *) sm_realloc(fp->f_bf.smb_base,
147 tsize + 1);
148 if (tbase == NULL)
150 errno = ENOMEM;
151 goto err; /* errno set */
153 fp->f_w += tsize - fp->f_bf.smb_size;
154 fp->f_bf.smb_base = tbase;
155 fp->f_bf.smb_size = tsize;
156 fp->f_p = tbase + blen;
158 w = fp->f_w;
159 errno = 0; /* needed to ensure EOF correctly found */
160 if (fp->f_flags & SMSTR)
162 if (len < (size_t) w)
163 w = len;
164 COPY(w); /* copy SM_MIN(fp->f_w,len), */
165 fp->f_w -= w;
166 fp->f_p += w;
167 w = len; /* but pretend copied all */
169 else if (fp->f_p > fp->f_bf.smb_base
170 && len > (size_t) w)
172 /* fill and flush */
173 COPY(w);
174 fp->f_p += w;
175 if (sm_flush(fp, &timeout))
176 goto err; /* errno set */
178 else if (len >= (size_t) (w = fp->f_bf.smb_size))
180 /* write directly */
181 w = (*fp->f_write)(fp, p, w);
182 if (w <= 0)
184 if (w == 0 && errno == 0)
185 break; /* EOF found */
186 if (IS_IO_ERROR(fd, w, timeout))
187 goto err; /* errno set */
189 /* write would block */
190 SM_IO_WR_TIMEOUT(fp, fd, timeout);
191 w = 0;
194 else
196 /* fill and done */
197 w = len;
198 COPY(w);
199 fp->f_w -= w;
200 fp->f_p += w;
202 p += w;
203 len -= w;
204 } while ((uio->uio_resid -= w) != 0);
206 if ((fp->f_flags & SMNOW) != 0 && sm_flush(fp, &timeout))
207 goto err; /* errno set */
209 else
212 ** Line buffered: like fully buffered, but we
213 ** must check for newlines. Compute the distance
214 ** to the first newline (including the newline),
215 ** or `infinity' if there is none, then pretend
216 ** that the amount to write is SM_MIN(len,nldist).
219 nlknown = 0;
220 nldist = 0; /* XXX just to keep gcc happy */
223 GETIOV(nlknown = 0);
224 if (!nlknown)
226 nl = memchr((void *)p, '\n', len);
227 nldist = nl != NULL ? nl + 1 - p : len + 1;
228 nlknown = 1;
230 s = SM_MIN(len, ((size_t) nldist));
231 w = fp->f_w + fp->f_bf.smb_size;
232 errno = 0; /* needed to ensure EOF correctly found */
233 if (fp->f_p > fp->f_bf.smb_base && s > w)
235 COPY(w);
236 /* fp->f_w -= w; */
237 fp->f_p += w;
238 if (sm_flush(fp, &timeout))
239 goto err; /* errno set */
241 else if (s >= (w = fp->f_bf.smb_size))
243 w = (*fp->f_write)(fp, p, w);
244 if (w <= 0)
246 if (w == 0 && errno == 0)
247 break; /* EOF found */
248 if (IS_IO_ERROR(fd, w, timeout))
249 goto err; /* errno set */
251 /* write would block */
252 SM_IO_WR_TIMEOUT(fp, fd, timeout);
253 w = 0;
256 else
258 w = s;
259 COPY(w);
260 fp->f_w -= w;
261 fp->f_p += w;
263 if ((nldist -= w) == 0)
265 /* copied the newline: flush and forget */
266 if (sm_flush(fp, &timeout))
267 goto err; /* errno set */
268 nlknown = 0;
270 p += w;
271 len -= w;
272 } while ((uio->uio_resid -= w) != 0);
275 return 0;
277 err:
278 /* errno set before goto places us here */
279 fp->f_flags |= SMERR;
280 return SM_IO_EOF;