diff options
Diffstat (limited to 'contrib/sendmail/libsm/smstdio.c')
-rw-r--r-- | contrib/sendmail/libsm/smstdio.c | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/contrib/sendmail/libsm/smstdio.c b/contrib/sendmail/libsm/smstdio.c new file mode 100644 index 0000000..758c936 --- /dev/null +++ b/contrib/sendmail/libsm/smstdio.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2000-2001 Sendmail, Inc. and its suppliers. + * All rights reserved. + * + * 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: smstdio.c,v 1.29 2001/09/11 04:04:49 gshapiro Exp $") +#include <unistd.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <sm/assert.h> +#include <sm/io.h> +#include <sm/string.h> +#include "local.h" + +/* +** Overall: +** This is a file type which implements a layer on top of the system +** stdio. fp->f_cookie is the FILE* of stdio. The cookie may be +** "bound late" because of the manner which Linux implements stdio. +** When binding late (when fp->f_cookie==NULL) then the value of +** fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or +** stderr. +*/ + +/* +** SM_STDIOOPEN -- open a file to system stdio implementation +** +** Parameters: +** fp -- file pointer assign for this open +** info -- info about file to open +** flags -- indicating method of opening +** rpool -- ignored +** +** Returns: +** Failure: -1 +** Success: 0 (zero) +*/ + +/* ARGSUSED3 */ +int +sm_stdioopen(fp, info, flags, rpool) + SM_FILE_T *fp; + const void *info; + int flags; + const void *rpool; +{ + register FILE *s; + char *stdiomode; + + switch (flags) + { + case SM_IO_RDONLY: + stdiomode = "r"; + break; + case SM_IO_WRONLY: + stdiomode = "w"; + break; + case SM_IO_APPEND: + stdiomode = "a"; + break; + case SM_IO_APPENDRW: + stdiomode = "a+"; + break; + case SM_IO_RDWR: + default: + stdiomode = "r+"; + break; + } + + if ((s = fopen((char *)info, stdiomode)) == NULL) + return -1; + fp->f_cookie = s; + return 0; +} + +/* +** SETUP -- assign file type cookie when not already assigned +** +** Parameters: +** fp - the file pointer to get the cookie assigned +** +** Return: +** none. +*/ + +static void +setup(fp) + SM_FILE_T *fp; +{ + if (fp->f_cookie == NULL) + { + switch (fp->f_ival) + { + case 0: + fp->f_cookie = stdin; + break; + case 1: + fp->f_cookie = stdout; + break; + case 2: + fp->f_cookie = stderr; + break; + default: + sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival); + break; + } + } +} + +/* +** SM_STDIOREAD -- read from the file +** +** Parameters: +** fp -- the file pointer +** buf -- location to place the read data +** n - number of bytes to read +** +** Returns: +** result from fread(). +*/ + +ssize_t +sm_stdioread(fp, buf, n) + SM_FILE_T *fp; + char *buf; + size_t n; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fread(buf, 1, n, s); +} + +/* +** SM_STDIOWRITE -- write to the file +** +** Parameters: +** fp -- the file pointer +** buf -- location of data to write +** n - number of bytes to write +** +** Returns: +** result from fwrite(). +*/ + +ssize_t +sm_stdiowrite(fp, buf, n) + SM_FILE_T *fp; + char const *buf; + size_t n; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fwrite(buf, 1, n, s); +} + +/* +** SM_STDIOSEEK -- set position within file +** +** Parameters: +** fp -- the file pointer +** offset -- new location based on 'whence' +** whence -- indicates "base" for 'offset' +** +** Returns: +** result from fseek(). +*/ + +off_t +sm_stdioseek(fp, offset, whence) + SM_FILE_T *fp; + off_t offset; + int whence; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fseek(s, offset, whence); +} + +/* +** SM_STDIOCLOSE -- close the file +** +** Parameters: +** fp -- close file pointer +** +** Return: +** status from fclose() +*/ + +int +sm_stdioclose(fp) + SM_FILE_T *fp; +{ + register FILE *s; + + if (fp->f_cookie == NULL) + setup(fp); + s = fp->f_cookie; + return fclose(s); +} + +/* +** SM_STDIOSETINFO -- set info for this open file +** +** Parameters: +** fp -- the file pointer +** what -- type of information setting +** valp -- memory location of info to set +** +** Return: +** Failure: -1 and sets errno +** Success: none (currently). +*/ + +/* ARGSUSED2 */ +int +sm_stdiosetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_MODE: + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_STDIOGETINFO -- get info for this open file +** +** Parameters: +** fp -- the file pointer +** what -- type of information request +** valp -- memory location to place info +** +** Return: +** Failure: -1 and sets errno +** Success: none (currently). +*/ + +/* ARGSUSED2 */ +int +sm_stdiogetinfo(fp, what, valp) + SM_FILE_T *fp; + int what; + void *valp; +{ + switch (what) + { + case SM_IO_WHAT_MODE: + default: + errno = EINVAL; + return -1; + } +} + +/* +** SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE +** +** Parameters: +** stream -- an open stdio stream, as returned by fopen() +** mode -- the mode argument to fopen() which describes stream +** +** Return: +** On success, return a pointer to an SM_FILE object which +** can be used for reading and writing 'stream'. +** Abort if mode is gibberish or stream is bad. +** Raise an exception if we can't allocate memory. +*/ + +SM_FILE_T * +sm_io_stdioopen(stream, mode) + FILE *stream; + char *mode; +{ + int fd; + bool r, w; + int ioflags; + SM_FILE_T *fp; + + fd = fileno(stream); + SM_REQUIRE(fd >= 0); + + r = w = false; + switch (mode[0]) + { + case 'r': + r = true; + break; + case 'w': + case 'a': + w = true; + break; + default: + sm_abort("sm_io_stdioopen: mode '%s' is bad", mode); + } + if (strchr(&mode[1], '+') != NULL) + r = w = true; + if (r && w) + ioflags = SMRW; + else if (r) + ioflags = SMRD; + else + ioflags = SMWR; + + fp = sm_fp(SmFtRealStdio, ioflags, NULL); + fp->f_file = fd; + fp->f_cookie = stream; + return fp; +} |