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

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