diff options
Diffstat (limited to 'sendmail/libsm/strio.c')
-rw-r--r-- | sendmail/libsm/strio.c | 490 |
1 files changed, 490 insertions, 0 deletions
diff --git a/sendmail/libsm/strio.c b/sendmail/libsm/strio.c new file mode 100644 index 0000000..75f3764 --- /dev/null +++ b/sendmail/libsm/strio.c @@ -0,0 +1,490 @@ +/* + * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers. + * All rights reserved. + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * By using this file, you agree to the terms and conditions set + * forth in the LICENSE file which can be found at the top level of + * the sendmail distribution. + */ + +#include <sm/gen.h> +SM_IDSTR(id, "@(#)$Id: strio.c,v 1.44 2005/06/09 21:40:19 ca Exp $") +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <sm/rpool.h> +#include <sm/io.h> +#include <sm/heap.h> +#include <sm/conf.h> +#include "local.h" + +static int sm_strsetmode __P((SM_FILE_T*, const int *)); +static int sm_strgetmode __P((SM_FILE_T*, int *)); + +/* +** Cookie structure for the "strio" file type +*/ + +struct sm_str_obj +{ + char *strio_base; + char *strio_end; + size_t strio_size; + size_t strio_offset; + int strio_flags; + const void *strio_rpool; +}; + +typedef struct sm_str_obj SM_STR_OBJ_T; + +/* +** SM_STRGROW -- increase storage space for string +** +** Parameters: +** s -- current cookie +** size -- new storage size request +** +** Returns: +** true iff successful. +*/ + +static bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); + +static bool +sm_strgrow(s, size) + SM_STR_OBJ_T *s; + size_t size; +{ + register void *p; + + if (s->strio_size >= size) + return true; + p = sm_realloc(s->strio_base, size); + if (p == NULL) + return false; + s->strio_base = p; + s->strio_end = s->strio_base + size; + s->strio_size = size; + return true; +} + +/* +** SM_STRREAD -- read a portion of the string +** +** Parameters: +** fp -- the file pointer +** buf -- location to place read data +** n -- number of bytes to read +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes read +*/ + +ssize_t +sm_strread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + int len; + + if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) + { + errno = EBADF; + return -1; + } + len = SM_MIN(s->strio_size - s->strio_offset, n); + (void) memmove(buf, s->strio_base + s->strio_offset, len); + s->strio_offset += len; + return len; +} + +/* +** SM_STRWRITE -- write a portion of the string +** +** Parameters: +** fp -- the file pointer +** buf -- location of data for writing +** n -- number of bytes to write +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes written +*/ + +ssize_t +sm_strwrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + + if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) + { + errno = EBADF; + return -1; + } + if (n + s->strio_offset > s->strio_size) + { + if (!sm_strgrow(s, n + s->strio_offset)) + return 0; + } + (void) memmove(s->strio_base + s->strio_offset, buf, n); + s->strio_offset += n; + return n; +} + +/* +** SM_STRSEEK -- position the offset pointer for the string +** +** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid +** values for whence. +** +** Parameters: +** fp -- the file pointer +** offset -- number of bytes offset from "base" +** whence -- determines "base" for 'offset' +** +** Returns: +** Failure: -1 and sets errno +** Success: >=0, number of bytes read +*/ + +off_t +sm_strseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + register off_t ret; + register SM_STR_OBJ_T *s = fp->f_cookie; + +reseek: + switch (whence) + { + case SM_IO_SEEK_SET: + ret = offset; + break; + case SM_IO_SEEK_CUR: + ret = s->strio_offset + offset; + break; + case SM_IO_SEEK_END: + ret = s->strio_size; + break; + default: + errno = EINVAL; + return -1; + } + if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ + return -1; + if ((size_t) ret > s->strio_size) + { + if (sm_strgrow(s, (size_t)ret)) + goto reseek; + + /* errno set by sm_strgrow */ + return -1; + } + s->strio_offset = (size_t) ret; + return ret; +} + +/* +** SM_STROPEN -- open a string file type +** +** Parameters: +** fp -- file pointer open to be associated with +** info -- initial contents (NULL for none) +** flags -- flags for methods of access (was mode) +** rpool -- resource pool to use memory from (if applicable) +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +int +sm_stropen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + register SM_STR_OBJ_T *s; + +#if SM_RPOOL + s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); +#else /* SM_RPOOL */ + s = sm_malloc(sizeof(SM_STR_OBJ_T)); + if (s == NULL) + return -1; +#endif /* SM_RPOOL */ + + fp->f_cookie = s; + s->strio_rpool = rpool; + s->strio_offset = 0; + s->strio_size = 0; + s->strio_base = NULL; + s->strio_end = 0; + + switch (flags) + { + case SM_IO_RDWR: + s->strio_flags = SMRW; + break; + case SM_IO_RDONLY: + s->strio_flags = SMRD; + break; + case SM_IO_WRONLY: + s->strio_flags = SMWR; + break; + case SM_IO_APPEND: + if (s->strio_rpool == NULL) + sm_free(s); + errno = EINVAL; + return -1; + default: + if (s->strio_rpool == NULL) + sm_free(s); + errno = EINVAL; + return -1; + } + + if (info != NULL) + { + s->strio_base = sm_strdup_x(info); + if (s->strio_base == NULL) + { + int save_errno = errno; + + if (s->strio_rpool == NULL) + sm_free(s); + errno = save_errno; + return -1; + } + s->strio_size = strlen(info); + s->strio_end = s->strio_base + s->strio_size; + } + return 0; +} + +/* +** SM_STRCLOSE -- close the string file type and free resources +** +** Parameters: +** fp -- file pointer +** +** Results: +** Success: 0 (zero) +*/ + +int +sm_strclose(fp) + SM_FILE_T *fp; +{ + SM_STR_OBJ_T *s = fp->f_cookie; + +#if !SM_RPOOL + sm_free(s->strio_base); + s->strio_base = NULL; +#endif /* !SM_RPOOL */ + return 0; +} + +/* +** SM_STRSETMODE -- set mode info for the file +** +** Note: changing the mode can be a safe way to have the "parent" +** set up a string that the "child" is not to modify +** +** Parameters: +** fp -- the file pointer +** mode -- location of new mode to set +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +static int +sm_strsetmode(fp, mode) + SM_FILE_T *fp; + const int *mode; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + int flags; + + switch (*mode) + { + case SM_IO_RDWR: + flags = SMRW; + break; + case SM_IO_RDONLY: + flags = SMRD; + break; + case SM_IO_WRONLY: + flags = SMWR; + break; + case SM_IO_APPEND: + errno = EINVAL; + return -1; + default: + errno = EINVAL; + return -1; + } + s->strio_flags &= ~SMMODEMASK; + s->strio_flags |= flags; + return 0; +} + +/* +** SM_STRGETMODE -- get mode info for the file +** +** Parameters: +** fp -- the file pointer +** mode -- location to store current mode +** +** Results: +** Success: 0 (zero) +** Failure: -1 and sets errno +*/ + +static int +sm_strgetmode(fp, mode) + SM_FILE_T *fp; + int *mode; +{ + register SM_STR_OBJ_T *s = fp->f_cookie; + + switch (s->strio_flags & SMMODEMASK) + { + case SMRW: + *mode = SM_IO_RDWR; + break; + case SMRD: + *mode = SM_IO_RDONLY; + break; + case SMWR: + *mode = SM_IO_WRONLY; + break; + default: + errno = EINVAL; + return -1; + } + return 0; +} + +/* +** SM_STRSETINFO -- set info for the file +** +** Currently only SM_IO_WHAT_MODE is supported for 'what'. +** +** Parameters: +** fp -- the file pointer +** what -- type of information to set +** valp -- location to data for doing set +** +** Results: +** Failure: -1 and sets errno +** Success: sm_strsetmode() return [0 (zero)] +*/ + +int +sm_strsetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch(what) + { + case SM_IO_WHAT_MODE: + return sm_strsetmode(fp, (int *) valp); + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STRGETINFO -- get info for the file +** +** Currently only SM_IO_WHAT_MODE is supported for 'what'. +** +** Parameters: +** fp -- the file pointer +** what -- type of information requested +** valp -- location to return information in +** +** Results: +** Failure: -1 and sets errno +** Success: sm_strgetmode() return [0 (zero)] +*/ + +int +sm_strgetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch(what) + { + case SM_IO_WHAT_MODE: + return sm_strgetmode(fp, (int *) valp); + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STRIO_INIT -- initializes a write-only string type +** +** Original comments below. This function does not appear to be used anywhere. +** The same functionality can be done by changing the mode of the file. +** ------------ +** sm_strio_init initializes an SM_FILE_T structure as a write-only file +** that writes into the specified buffer: +** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. +** Attempts to write more than size-1 characters into the buffer will fail +** silently (no error is reported). +** - Use sm_io_fflush to nul terminate the string in the buffer +** (the write pointer is not advanced). +** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. +** +** Parameters: +** fp -- file pointer +** buf -- memory location for stored data +** size -- size of 'buf' +** +** Results: +** none. +*/ + +void +sm_strio_init(fp, buf, size) + SM_FILE_T *fp; + char *buf; + size_t size; +{ + fp->sm_magic = SmFileMagic; + fp->f_flags = SMWR | SMSTR; + fp->f_file = -1; + fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; + fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); + fp->f_lbfsize = 0; + fp->f_r = 0; + fp->f_read = NULL; + fp->f_seek = NULL; + fp->f_getinfo = NULL; + fp->f_setinfo = NULL; +} |