Correct conditional to correctly treat segments which end on a boundary.
[dragonfly.git] / contrib / sendmail-8.13.8 / libsm / smstdio.c
1 /*
2  * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
3  *      All rights reserved.
4  *
5  * By using this file, you agree to the terms and conditions set
6  * forth in the LICENSE file which can be found at the top level of
7  * the sendmail distribution.
8  */
9
10 #include <sm/gen.h>
11 SM_IDSTR(id, "@(#)$Id: smstdio.c,v 1.34 2004/08/03 20:46:34 ca Exp $")
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <errno.h>
16 #include <sys/stat.h>
17 #include <sm/assert.h>
18 #include <sm/io.h>
19 #include <sm/string.h>
20 #include "local.h"
21
22 static void     setup __P((SM_FILE_T *));
23
24 /*
25 ** Overall:
26 **      This is a file type which implements a layer on top of the system
27 **      stdio. fp->f_cookie is the FILE* of stdio. The cookie may be
28 **      "bound late" because of the manner which Linux implements stdio.
29 **      When binding late  (when fp->f_cookie==NULL) then the value of
30 **      fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or
31 **      stderr.
32 */
33
34 /*
35 **  SM_STDIOOPEN -- open a file to system stdio implementation
36 **
37 **      Parameters:
38 **              fp -- file pointer assign for this open
39 **              info -- info about file to open
40 **              flags -- indicating method of opening
41 **              rpool -- ignored
42 **
43 **      Returns:
44 **              Failure: -1
45 **              Success: 0 (zero)
46 */
47
48 /* ARGSUSED3 */
49 int
50 sm_stdioopen(fp, info, flags, rpool)
51         SM_FILE_T *fp;
52         const void *info;
53         int flags;
54         const void *rpool;
55 {
56         register FILE *s;
57         char *stdiomode;
58
59         switch (flags)
60         {
61           case SM_IO_RDONLY:
62                 stdiomode = "r";
63                 break;
64           case SM_IO_WRONLY:
65                 stdiomode = "w";
66                 break;
67           case SM_IO_APPEND:
68                 stdiomode = "a";
69                 break;
70           case SM_IO_APPENDRW:
71                 stdiomode = "a+";
72                 break;
73 #if SM_IO_BINARY != 0
74           case SM_IO_RDONLY_B:
75                 stdiomode = "rb";
76                 break;
77           case SM_IO_WRONLY_B:
78                 stdiomode = "wb";
79                 break;
80           case SM_IO_APPEND_B:
81                 stdiomode = "ab";
82                 break;
83           case SM_IO_APPENDRW_B:
84                 stdiomode = "a+b";
85                 break;
86           case SM_IO_RDWR_B:
87                 stdiomode = "r+b";
88                 break;
89 #endif /* SM_IO_BINARY != 0 */
90           case SM_IO_RDWR:
91           default:
92                 stdiomode = "r+";
93                 break;
94         }
95
96         if ((s = fopen((char *)info, stdiomode)) == NULL)
97                 return -1;
98         fp->f_cookie = s;
99         return 0;
100 }
101
102 /*
103 **  SETUP -- assign file type cookie when not already assigned
104 **
105 **      Parameters:
106 **              fp - the file pointer to get the cookie assigned
107 **
108 **      Return:
109 **              none.
110 */
111
112 static void
113 setup(fp)
114         SM_FILE_T *fp;
115 {
116         if (fp->f_cookie == NULL)
117         {
118                 switch (fp->f_ival)
119                 {
120                   case 0:
121                         fp->f_cookie = stdin;
122                         break;
123                   case 1:
124                         fp->f_cookie = stdout;
125                         break;
126                   case 2:
127                         fp->f_cookie = stderr;
128                         break;
129                   default:
130                         sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival);
131                         break;
132                 }
133         }
134 }
135
136 /*
137 **  SM_STDIOREAD -- read from the file
138 **
139 **      Parameters:
140 **              fp -- the file pointer
141 **              buf -- location to place the read data
142 **              n - number of bytes to read
143 **
144 **      Returns:
145 **              result from fread().
146 */
147
148 ssize_t
149 sm_stdioread(fp, buf, n)
150         SM_FILE_T *fp;
151         char *buf;
152         size_t n;
153 {
154         register FILE *s;
155
156         if (fp->f_cookie == NULL)
157                 setup(fp);
158         s = fp->f_cookie;
159         return fread(buf, 1, n, s);
160 }
161
162 /*
163 **  SM_STDIOWRITE -- write to the file
164 **
165 **      Parameters:
166 **              fp -- the file pointer
167 **              buf -- location of data to write
168 **              n - number of bytes to write
169 **
170 **      Returns:
171 **              result from fwrite().
172 */
173
174 ssize_t
175 sm_stdiowrite(fp, buf, n)
176         SM_FILE_T *fp;
177         char const *buf;
178         size_t n;
179 {
180         register FILE *s;
181
182         if (fp->f_cookie == NULL)
183                 setup(fp);
184         s = fp->f_cookie;
185         return fwrite(buf, 1, n, s);
186 }
187
188 /*
189 **  SM_STDIOSEEK -- set position within file
190 **
191 **      Parameters:
192 **              fp -- the file pointer
193 **              offset -- new location based on 'whence'
194 **              whence -- indicates "base" for 'offset'
195 **
196 **      Returns:
197 **              result from fseek().
198 */
199
200 off_t
201 sm_stdioseek(fp, offset, whence)
202         SM_FILE_T *fp;
203         off_t offset;
204         int whence;
205 {
206         register FILE *s;
207
208         if (fp->f_cookie == NULL)
209                 setup(fp);
210         s = fp->f_cookie;
211         return fseek(s, offset, whence);
212 }
213
214 /*
215 **  SM_STDIOCLOSE -- close the file
216 **
217 **      Parameters:
218 **              fp -- close file pointer
219 **
220 **      Return:
221 **              status from fclose()
222 */
223
224 int
225 sm_stdioclose(fp)
226         SM_FILE_T *fp;
227 {
228         register FILE *s;
229
230         if (fp->f_cookie == NULL)
231                 setup(fp);
232         s = fp->f_cookie;
233         return fclose(s);
234 }
235
236 /*
237 **  SM_STDIOSETINFO -- set info for this open file
238 **
239 **      Parameters:
240 **              fp -- the file pointer
241 **              what -- type of information setting
242 **              valp -- memory location of info to set
243 **
244 **      Return:
245 **              Failure: -1 and sets errno
246 **              Success: none (currently).
247 */
248
249 /* ARGSUSED2 */
250 int
251 sm_stdiosetinfo(fp, what, valp)
252         SM_FILE_T *fp;
253         int what;
254         void *valp;
255 {
256         switch (what)
257         {
258           case SM_IO_WHAT_MODE:
259           default:
260                 errno = EINVAL;
261                 return -1;
262         }
263 }
264
265 /*
266 **  SM_STDIOGETINFO -- get info for this open file
267 **
268 **      Parameters:
269 **              fp -- the file pointer
270 **              what -- type of information request
271 **              valp -- memory location to place info
272 **
273 **      Return:
274 **              Failure: -1 and sets errno
275 **              Success: none (currently).
276 */
277
278 /* ARGSUSED2 */
279 int
280 sm_stdiogetinfo(fp, what, valp)
281         SM_FILE_T *fp;
282         int what;
283         void *valp;
284 {
285         switch (what)
286         {
287           case SM_IO_WHAT_SIZE:
288           {
289                   int fd;
290                   struct stat st;
291
292                   if (fp->f_cookie == NULL)
293                           setup(fp);
294                   fd = fileno((FILE *) fp->f_cookie);
295                   if (fd < 0)
296                           return -1;
297                   if (fstat(fd, &st) == 0)
298                           return st.st_size;
299                   else
300                           return -1;
301           }
302
303           case SM_IO_WHAT_MODE:
304           default:
305                 errno = EINVAL;
306                 return -1;
307         }
308 }
309
310 /*
311 **  SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE
312 **
313 **      Parameters:
314 **              stream -- an open stdio stream, as returned by fopen()
315 **              mode -- the mode argument to fopen() which describes stream
316 **
317 **      Return:
318 **              On success, return a pointer to an SM_FILE object which
319 **              can be used for reading and writing 'stream'.
320 **              Abort if mode is gibberish or stream is bad.
321 **              Raise an exception if we can't allocate memory.
322 */
323
324 SM_FILE_T *
325 sm_io_stdioopen(stream, mode)
326         FILE *stream;
327         char *mode;
328 {
329         int fd;
330         bool r, w;
331         int ioflags;
332         SM_FILE_T *fp;
333
334         fd = fileno(stream);
335         SM_REQUIRE(fd >= 0);
336
337         r = w = false;
338         switch (mode[0])
339         {
340           case 'r':
341                 r = true;
342                 break;
343           case 'w':
344           case 'a':
345                 w = true;
346                 break;
347           default:
348                 sm_abort("sm_io_stdioopen: mode '%s' is bad", mode);
349         }
350         if (strchr(&mode[1], '+') != NULL)
351                 r = w = true;
352         if (r && w)
353                 ioflags = SMRW;
354         else if (r)
355                 ioflags = SMRD;
356         else
357                 ioflags = SMWR;
358
359         fp = sm_fp(SmFtRealStdio, ioflags, NULL);
360         fp->f_file = fd;
361         fp->f_cookie = stream;
362         return fp;
363 }