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

Revision 19204, 9.1 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 * 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_IDSTR(id, "@(#)$Id: strio.c,v 1.1.1.1 2003-04-08 15:07:00 zacheiss Exp $")
17#include <stdlib.h>
18#include <unistd.h>
19#include <fcntl.h>
20#include <string.h>
21#include <errno.h>
22#include <sm/rpool.h>
23#include <sm/io.h>
24#include <sm/heap.h>
25#include <sm/conf.h>
26#include "local.h"
27
28/*
29**  Cookie structure for the "strio" file type
30*/
31
32struct sm_str_obj
33{
34        char            *strio_base;
35        char            *strio_end;
36        size_t          strio_size;
37        size_t          strio_offset;
38        int             strio_flags;
39        const void      *strio_rpool;
40};
41
42typedef struct sm_str_obj SM_STR_OBJ_T;
43
44/*
45**  SM_STRGROW -- increase storage space for string
46**
47**      Parameters:
48**              s -- current cookie
49**              size -- new storage size request
50**
51**      Returns:
52**              true iff successful.
53*/
54
55static bool sm_strgrow __P((SM_STR_OBJ_T *, size_t));
56
57static bool
58sm_strgrow(s, size)
59        SM_STR_OBJ_T *s;
60        size_t size;
61{
62        register void *p;
63
64        if (s->strio_size >= size)
65                return true;
66        p = sm_realloc(s->strio_base, size);
67        if (p == NULL)
68                return false;
69        s->strio_base = p;
70        s->strio_end = s->strio_base + size;
71        s->strio_size = size;
72        return true;
73}
74
75/*
76**  SM_STRREAD -- read a portion of the string
77**
78**      Parameters:
79**              fp -- the file pointer
80**              buf -- location to place read data
81**              n -- number of bytes to read
82**
83**      Returns:
84**              Failure: -1 and sets errno
85**              Success: >=0, number of bytes read
86*/
87
88ssize_t
89sm_strread(fp, buf, n)
90        SM_FILE_T *fp;
91        char *buf;
92        size_t n;
93{
94        register SM_STR_OBJ_T *s = fp->f_cookie;
95        int len;
96
97        if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW))
98        {
99                errno = EBADF;
100                return -1;
101        }
102        len = SM_MIN(s->strio_size - s->strio_offset, n);
103        (void) memmove(buf, s->strio_base + s->strio_offset, len);
104        s->strio_offset += len;
105        return len;
106}
107
108/*
109**  SM_STRWRITE -- write a portion of the string
110**
111**      Parameters:
112**              fp -- the file pointer
113**              buf -- location of data for writing
114**              n -- number of bytes to write
115**
116**      Returns:
117**              Failure: -1 and sets errno
118**              Success: >=0, number of bytes written
119*/
120
121ssize_t
122sm_strwrite(fp, buf, n)
123        SM_FILE_T *fp;
124        char const *buf;
125        size_t n;
126{
127        register SM_STR_OBJ_T *s = fp->f_cookie;
128
129        if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW))
130        {
131                errno = EBADF;
132                return -1;
133        }
134        if (n + s->strio_offset > s->strio_size)
135        {
136                if (!sm_strgrow(s, n + s->strio_offset))
137                        return 0;
138        }
139        (void) memmove(s->strio_base + s->strio_offset, buf, n);
140        s->strio_offset += n;
141        return n;
142}
143
144/*
145**  SM_STRSEEK -- position the offset pointer for the string
146**
147**      Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid
148**      values for whence.
149**
150**      Parameters:
151**              fp -- the file pointer
152**              offset -- number of bytes offset from "base"
153**              whence -- determines "base" for 'offset'
154**
155**      Returns:
156**              Failure: -1 and sets errno
157**              Success: >=0, number of bytes read
158*/
159
160off_t
161sm_strseek(fp, offset, whence)
162        SM_FILE_T *fp;
163        off_t offset;
164        int whence;
165{
166        register off_t ret;
167        register SM_STR_OBJ_T *s = fp->f_cookie;
168
169reseek:
170        switch (whence)
171        {
172          case SM_IO_SEEK_SET:
173                ret = offset;
174                break;
175          case SM_IO_SEEK_CUR:
176                ret = s->strio_offset + offset;
177                break;
178          case SM_IO_SEEK_END:
179                ret = s->strio_size;
180                break;
181          default:
182                errno = EINVAL;
183                return -1;
184        }
185        if (ret < 0 || ret > (off_t)(size_t)(-1))       /* XXX ugly */
186                return -1;
187        if ((size_t) ret > s->strio_size)
188        {
189                if (sm_strgrow(s, (size_t)ret))
190                        goto reseek;
191
192                /* errno set by sm_strgrow */
193                return -1;
194        }
195        s->strio_offset = (size_t) ret;
196        return ret;
197}
198
199/*
200**  SM_STROPEN -- open a string file type
201**
202**      Parameters:
203**              fp -- file pointer open to be associated with
204**              info -- initial contents (NULL for none)
205**              flags -- flags for methods of access (was mode)
206**              rpool -- resource pool to use memory from (if applicable)
207**
208**      Results:
209**              Success: 0 (zero)
210**              Failure: -1 and sets errno
211*/
212
213int
214sm_stropen(fp, info, flags, rpool)
215        SM_FILE_T *fp;
216        const void *info;
217        int flags;
218        const void *rpool;
219{
220        register SM_STR_OBJ_T *s;
221
222#if SM_RPOOL
223        s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T));
224#else /* SM_RPOOL */
225        s = sm_malloc(sizeof(SM_STR_OBJ_T));
226        if (s == NULL)
227                return -1;
228#endif /* SM_RPOOL */
229
230        fp->f_cookie = s;
231        s->strio_rpool = rpool;
232        s->strio_offset = 0;
233        s->strio_size = 0;
234        s->strio_base = NULL;
235        s->strio_end = 0;
236
237        switch (flags)
238        {
239          case SM_IO_RDWR:
240                s->strio_flags = SMRW;
241                break;
242          case SM_IO_RDONLY:
243                s->strio_flags = SMRD;
244                break;
245          case SM_IO_WRONLY:
246                s->strio_flags = SMWR;
247                break;
248          case SM_IO_APPEND:
249                if (s->strio_rpool == NULL)
250                        sm_free(s);
251                errno = EINVAL;
252                return -1;
253          default:
254                if (s->strio_rpool == NULL)
255                        sm_free(s);
256                errno = EINVAL;
257                return -1;
258        }
259
260        if (info != NULL)
261        {
262                s->strio_base = sm_strdup_x(info);
263                if (s->strio_base == NULL)
264                {
265                        int save_errno = errno;
266
267                        if (s->strio_rpool == NULL)
268                                sm_free(s);
269                        errno = save_errno;
270                        return -1;
271                }
272                s->strio_size = strlen(info);
273                s->strio_end = s->strio_base + s->strio_size;
274        }
275        return 0;
276}
277
278/*
279**  SM_STRCLOSE -- close the string file type and free resources
280**
281**      Parameters:
282**              fp -- file pointer
283**
284**      Results:
285**              Success: 0 (zero)
286*/
287
288int
289sm_strclose(fp)
290        SM_FILE_T *fp;
291{
292        SM_STR_OBJ_T *s = fp->f_cookie;
293
294#if !SM_RPOOL
295        sm_free(s->strio_base);
296        s->strio_base = NULL;
297#endif /* !SM_RPOOL */
298        return 0;
299}
300
301/*
302**  SM_STRSETMODE -- set mode info for the file
303**
304**       Note: changing the mode can be a safe way to have the "parent"
305**       set up a string that the "child" is not to modify
306**
307**      Parameters:
308**              fp -- the file pointer
309**              mode -- location of new mode to set
310**
311**      Results:
312**              Success: 0 (zero)
313**              Failure: -1 and sets errno
314*/
315
316int
317sm_strsetmode(fp, mode)
318        SM_FILE_T *fp;
319        const int *mode;
320{
321        register SM_STR_OBJ_T *s = fp->f_cookie;
322        int flags;
323
324        switch (*mode)
325        {
326          case SM_IO_RDWR:
327                flags = SMRW;
328                break;
329          case SM_IO_RDONLY:
330                flags = SMRD;
331                break;
332          case SM_IO_WRONLY:
333                flags = SMWR;
334                break;
335          case SM_IO_APPEND:
336                errno = EINVAL;
337                return -1;
338          default:
339                errno = EINVAL;
340                return -1;
341        }
342        s->strio_flags &= ~SMMODEMASK;
343        s->strio_flags |= flags;
344        return 0;
345}
346
347/*
348**  SM_STRGETMODE -- get mode info for the file
349**
350**      Parameters:
351**              fp -- the file pointer
352**              mode -- location to store current mode
353**
354**      Results:
355**              Success: 0 (zero)
356**              Failure: -1 and sets errno
357*/
358
359int
360sm_strgetmode(fp, mode)
361        SM_FILE_T *fp;
362        int *mode;
363{
364        register SM_STR_OBJ_T *s = fp->f_cookie;
365
366        switch (s->strio_flags & SMMODEMASK)
367        {
368          case SMRW:
369                *mode = SM_IO_RDWR;
370                break;
371          case SMRD:
372                *mode = SM_IO_RDONLY;
373                break;
374          case SMWR:
375                *mode = SM_IO_WRONLY;
376                break;
377          default:
378                errno = EINVAL;
379                return -1;
380        }
381        return 0;
382}
383
384/*
385**  SM_STRSETINFO -- set info for the file
386**
387**      Currently only SM_IO_WHAT_MODE is supported for 'what'.
388**
389**      Parameters:
390**              fp -- the file pointer
391**              what -- type of information to set
392**              valp -- location to data for doing set
393**
394**      Results:
395**              Failure: -1 and sets errno
396**              Success: sm_strsetmode() return [0 (zero)]
397*/
398
399int
400sm_strsetinfo(fp, what, valp)
401        SM_FILE_T *fp;
402        int what;
403        void *valp;
404{
405        switch(what)
406        {
407          case SM_IO_WHAT_MODE:
408                return sm_strsetmode(fp, (int *) valp);
409          default:
410                errno = EINVAL;
411                return -1;
412        }
413}
414
415/*
416**  SM_STRGETINFO -- get info for the file
417**
418**      Currently only SM_IO_WHAT_MODE is supported for 'what'.
419**
420**      Parameters:
421**              fp -- the file pointer
422**              what -- type of information requested
423**              valp -- location to return information in
424**
425**      Results:
426**              Failure: -1 and sets errno
427**              Success: sm_strgetmode() return [0 (zero)]
428*/
429
430int
431sm_strgetinfo(fp, what, valp)
432        SM_FILE_T *fp;
433        int what;
434        void *valp;
435{
436        switch(what)
437        {
438          case SM_IO_WHAT_MODE:
439                return sm_strgetmode(fp, (int *) valp);
440          default:
441                errno = EINVAL;
442                return -1;
443        }
444}
445
446/*
447**  SM_STRIO_INIT -- initializes a write-only string type
448**
449**  Original comments below. This function does not appear to be used anywhere.
450**  The same functionality can be done by changing the mode of the file.
451**  ------------
452** sm_strio_init initializes an SM_FILE_T structure as a write-only file
453** that writes into the specified buffer:
454** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer.
455**   Attempts to write more than size-1 characters into the buffer will fail
456**   silently (no error is reported).
457** - Use sm_io_fflush to nul terminate the string in the buffer
458**   (the write pointer is not advanced).
459** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc.
460**
461**      Parameters:
462**              fp -- file pointer
463**              buf -- memory location for stored data
464**              size -- size of 'buf'
465**
466**      Results:
467**              none.
468*/
469
470void
471sm_strio_init(fp, buf, size)
472        SM_FILE_T *fp;
473        char *buf;
474        size_t size;
475{
476        fp->sm_magic = SmFileMagic;
477        fp->f_flags = SMWR | SMSTR;
478        fp->f_file = -1;
479        fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf;
480        fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0);
481        fp->f_lbfsize = 0;
482        fp->f_r = 0;
483        fp->f_read = NULL;
484        fp->f_seek = NULL;
485        fp->f_getinfo = NULL;
486        fp->f_setinfo = NULL;
487}
Note: See TracBrowser for help on using the repository browser.