source: trunk/third/sendmail/libsm/setvbuf.c @ 19204

Revision 19204, 4.2 KB checked in by zacheiss, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r19203, which included commits to RCS files with non-trunk default branches.
Line 
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>
16SM_RCSID("@(#)$Id: setvbuf.c,v 1.1.1.1 2003-04-08 15:06:05 zacheiss Exp $")
17#include <stdlib.h>
18#include <errno.h>
19#include <fcntl.h>
20#include <sm/io.h>
21#include <sm/heap.h>
22#include <sm/assert.h>
23#include <sm/conf.h>
24#include "local.h"
25
26/*
27**  SM_IO_SETVBUF -- set the buffering type for a file
28**
29**  Set one of the different kinds of buffering, optionally including
30**  a buffer.
31**  If 'size' is == 0 then an "optimal" size will be selected.
32**  If 'buf' is == NULL then space will be allocated at 'size'.
33**
34**      Parameters:
35**              fp -- the file that buffering is to be changed for
36**              timeout -- time allowed for completing the function
37**              buf -- buffer to use
38**              mode -- buffering method to use
39**              size -- size of 'buf'
40**
41**      Returns:
42**              Failure: SM_IO_EOF
43**              Success: 0 (zero)
44*/
45
46int
47sm_io_setvbuf(fp, timeout, buf, mode, size)
48        SM_FILE_T *fp;
49        int timeout;
50        char *buf;
51        int mode;
52        size_t size;
53{
54        int ret, flags;
55        size_t iosize;
56        int ttyflag;
57        int fd;
58        struct timeval to;
59
60        SM_REQUIRE_ISA(fp, SmFileMagic);
61
62        /*
63        **  Verify arguments.  The `int' limit on `size' is due to this
64        **  particular implementation.  Note, buf and size are ignored
65        **  when setting SM_IO_NBF.
66        */
67
68        if (mode != SM_IO_NBF)
69                if ((mode != SM_IO_FBF && mode != SM_IO_LBF &&
70                    mode != SM_IO_NOW) || (int) size < 0)
71                        return SM_IO_EOF;
72
73        /*
74        **  Write current buffer, if any.  Discard unread input (including
75        **  ungetc data), cancel line buffering, and free old buffer if
76        **  malloc()ed.  We also clear any eof condition, as if this were
77        **  a seek.
78        */
79
80        ret = 0;
81        SM_CONVERT_TIME(fp, fd, timeout, &to);
82        (void) sm_flush(fp, &timeout);
83        if (HASUB(fp))
84                FREEUB(fp);
85        fp->f_r = fp->f_lbfsize = 0;
86        flags = fp->f_flags;
87        if (flags & SMMBF)
88        {
89                sm_free((void *) fp->f_bf.smb_base);
90                fp->f_bf.smb_base = NULL;
91        }
92        flags &= ~(SMLBF | SMNBF | SMMBF | SMOPT | SMNPT | SMFEOF | SMNOW |
93                   SMFBF);
94
95        /* If setting unbuffered mode, skip all the hard work. */
96        if (mode == SM_IO_NBF)
97                goto nbf;
98
99        /*
100        **  Find optimal I/O size for seek optimization.  This also returns
101        **  a `tty flag' to suggest that we check isatty(fd), but we do not
102        **  care since our caller told us how to buffer.
103        */
104
105        flags |= sm_whatbuf(fp, &iosize, &ttyflag);
106        if (size == 0)
107        {
108                buf = NULL;     /* force local allocation */
109                size = iosize;
110        }
111
112        /* Allocate buffer if needed. */
113        if (buf == NULL)
114        {
115                if ((buf = sm_malloc(size)) == NULL)
116                {
117                        /*
118                        **  Unable to honor user's request.  We will return
119                        **  failure, but try again with file system size.
120                        */
121
122                        ret = SM_IO_EOF;
123                        if (size != iosize)
124                        {
125                                size = iosize;
126                                buf = sm_malloc(size);
127                        }
128                }
129                if (buf == NULL)
130                {
131                        /* No luck; switch to unbuffered I/O. */
132nbf:
133                        fp->f_flags = flags | SMNBF;
134                        fp->f_w = 0;
135                        fp->f_bf.smb_base = fp->f_p = fp->f_nbuf;
136                        fp->f_bf.smb_size = 1;
137                        return ret;
138                }
139                flags |= SMMBF;
140        }
141
142        /*
143        **  Kill any seek optimization if the buffer is not the
144        **  right size.
145        **
146        **  SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
147        */
148
149        if (size != iosize)
150                flags |= SMNPT;
151
152        /*
153        **  Fix up the SM_FILE_T fields, and set sm_cleanup for output flush on
154        **  exit (since we are buffered in some way).
155        */
156
157        if (mode == SM_IO_LBF)
158                flags |= SMLBF;
159        else if (mode == SM_IO_NOW)
160                flags |= SMNOW;
161        else if (mode == SM_IO_FBF)
162                flags |= SMFBF;
163        fp->f_flags = flags;
164        fp->f_bf.smb_base = fp->f_p = (unsigned char *)buf;
165        fp->f_bf.smb_size = size;
166        /* fp->f_lbfsize is still 0 */
167        if (flags & SMWR)
168        {
169                /*
170                **  Begin or continue writing: see sm_wsetup().  Note
171                **  that SMNBF is impossible (it was handled earlier).
172                */
173
174                if (flags & SMLBF)
175                {
176                        fp->f_w = 0;
177                        fp->f_lbfsize = -fp->f_bf.smb_size;
178                }
179                else
180                        fp->f_w = size;
181        }
182        else
183        {
184                /* begin/continue reading, or stay in intermediate state */
185                fp->f_w = 0;
186        }
187
188        atexit(sm_cleanup);
189        return ret;
190}
Note: See TracBrowser for help on using the repository browser.