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. |
---|
6 | * |
---|
7 | * This code is derived from software contributed to Berkeley by |
---|
8 | * Chris Torek. |
---|
9 | * |
---|
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. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <sm/gen.h> |
---|
16 | SM_RCSID("@(#)$Id: wbuf.c,v 1.1.1.1 2003-04-08 15:06:05 zacheiss Exp $") |
---|
17 | #include <errno.h> |
---|
18 | #include <sm/io.h> |
---|
19 | #include "local.h" |
---|
20 | |
---|
21 | /* Note: This function is called from a macro located in <sm/io.h> */ |
---|
22 | |
---|
23 | /* |
---|
24 | ** SM_WBUF -- write character to and flush (likely now full) buffer |
---|
25 | ** |
---|
26 | ** Write the given character into the (probably full) buffer for |
---|
27 | ** the given file. Flush the buffer out if it is or becomes full, |
---|
28 | ** or if c=='\n' and the file is line buffered. |
---|
29 | ** |
---|
30 | ** Parameters: |
---|
31 | ** fp -- the file pointer |
---|
32 | ** timeout -- time to complete operation (milliseconds) |
---|
33 | ** c -- int representation of the character to add |
---|
34 | ** |
---|
35 | ** Results: |
---|
36 | ** Failure: -1 and sets errno |
---|
37 | ** Success: int value of 'c' |
---|
38 | */ |
---|
39 | |
---|
40 | int |
---|
41 | sm_wbuf(fp, timeout, c) |
---|
42 | register SM_FILE_T *fp; |
---|
43 | int timeout; |
---|
44 | register int c; |
---|
45 | { |
---|
46 | register int n; |
---|
47 | |
---|
48 | /* |
---|
49 | ** In case we cannot write, or longjmp takes us out early, |
---|
50 | ** make sure w is 0 (if fully- or un-buffered) or -bf.smb_size |
---|
51 | ** (if line buffered) so that we will get called again. |
---|
52 | ** If we did not do this, a sufficient number of sm_io_putc() |
---|
53 | ** calls might wrap w from negative to positive. |
---|
54 | */ |
---|
55 | |
---|
56 | fp->f_w = fp->f_lbfsize; |
---|
57 | if (cantwrite(fp)) |
---|
58 | { |
---|
59 | errno = EBADF; |
---|
60 | return SM_IO_EOF; |
---|
61 | } |
---|
62 | c = (unsigned char)c; |
---|
63 | |
---|
64 | /* |
---|
65 | ** If it is completely full, flush it out. Then, in any case, |
---|
66 | ** stuff c into the buffer. If this causes the buffer to fill |
---|
67 | ** completely, or if c is '\n' and the file is line buffered, |
---|
68 | ** flush it (perhaps a second time). The second flush will always |
---|
69 | ** happen on unbuffered streams, where bf.smb_size==1; sm_io_flush() |
---|
70 | ** guarantees that sm_io_putc() will always call sm_wbuf() by setting |
---|
71 | ** w to 0, so we need not do anything else. |
---|
72 | ** Note for the timeout, only one of the sm_io_flush's will get called. |
---|
73 | */ |
---|
74 | |
---|
75 | n = fp->f_p - fp->f_bf.smb_base; |
---|
76 | if (n >= fp->f_bf.smb_size) |
---|
77 | { |
---|
78 | if (sm_io_flush(fp, timeout)) |
---|
79 | return SM_IO_EOF; /* sm_io_flush() sets errno */ |
---|
80 | n = 0; |
---|
81 | } |
---|
82 | fp->f_w--; |
---|
83 | *fp->f_p++ = c; |
---|
84 | if (++n == fp->f_bf.smb_size || (fp->f_flags & SMLBF && c == '\n')) |
---|
85 | if (sm_io_flush(fp, timeout)) |
---|
86 | return SM_IO_EOF; /* sm_io_flush() sets errno */ |
---|
87 | return c; |
---|
88 | } |
---|