smstdio.c revision 132943
190792Sgshapiro/* 2132943Sgshapiro * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * 590792Sgshapiro * By using this file, you agree to the terms and conditions set 690792Sgshapiro * forth in the LICENSE file which can be found at the top level of 790792Sgshapiro * the sendmail distribution. 890792Sgshapiro */ 990792Sgshapiro 1090792Sgshapiro#include <sm/gen.h> 11132943SgshapiroSM_IDSTR(id, "@(#)$Id: smstdio.c,v 1.33 2004/03/03 19:14:51 ca Exp $") 1290792Sgshapiro#include <unistd.h> 1390792Sgshapiro#include <stdio.h> 1490792Sgshapiro#include <fcntl.h> 1590792Sgshapiro#include <errno.h> 1694334Sgshapiro#include <sys/stat.h> 1790792Sgshapiro#include <sm/assert.h> 1890792Sgshapiro#include <sm/io.h> 1990792Sgshapiro#include <sm/string.h> 2090792Sgshapiro#include "local.h" 2190792Sgshapiro 2290792Sgshapiro/* 2390792Sgshapiro** Overall: 2490792Sgshapiro** This is a file type which implements a layer on top of the system 2590792Sgshapiro** stdio. fp->f_cookie is the FILE* of stdio. The cookie may be 2690792Sgshapiro** "bound late" because of the manner which Linux implements stdio. 2790792Sgshapiro** When binding late (when fp->f_cookie==NULL) then the value of 2890792Sgshapiro** fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or 2990792Sgshapiro** stderr. 3090792Sgshapiro*/ 3190792Sgshapiro 3290792Sgshapiro/* 3390792Sgshapiro** SM_STDIOOPEN -- open a file to system stdio implementation 3490792Sgshapiro** 3590792Sgshapiro** Parameters: 3690792Sgshapiro** fp -- file pointer assign for this open 3790792Sgshapiro** info -- info about file to open 3890792Sgshapiro** flags -- indicating method of opening 3990792Sgshapiro** rpool -- ignored 4090792Sgshapiro** 4190792Sgshapiro** Returns: 4290792Sgshapiro** Failure: -1 4390792Sgshapiro** Success: 0 (zero) 4490792Sgshapiro*/ 4590792Sgshapiro 4690792Sgshapiro/* ARGSUSED3 */ 4790792Sgshapiroint 4890792Sgshapirosm_stdioopen(fp, info, flags, rpool) 4990792Sgshapiro SM_FILE_T *fp; 5090792Sgshapiro const void *info; 5190792Sgshapiro int flags; 5290792Sgshapiro const void *rpool; 5390792Sgshapiro{ 5490792Sgshapiro register FILE *s; 5590792Sgshapiro char *stdiomode; 5690792Sgshapiro 5790792Sgshapiro switch (flags) 5890792Sgshapiro { 5990792Sgshapiro case SM_IO_RDONLY: 6090792Sgshapiro stdiomode = "r"; 6190792Sgshapiro break; 6290792Sgshapiro case SM_IO_WRONLY: 6390792Sgshapiro stdiomode = "w"; 6490792Sgshapiro break; 6590792Sgshapiro case SM_IO_APPEND: 6690792Sgshapiro stdiomode = "a"; 6790792Sgshapiro break; 6890792Sgshapiro case SM_IO_APPENDRW: 6990792Sgshapiro stdiomode = "a+"; 7090792Sgshapiro break; 71120256Sgshapiro#if SM_IO_BINARY != 0 72120256Sgshapiro case SM_IO_RDONLY_B: 73120256Sgshapiro stdiomode = "rb"; 74120256Sgshapiro break; 75120256Sgshapiro case SM_IO_WRONLY_B: 76120256Sgshapiro stdiomode = "wb"; 77120256Sgshapiro break; 78120256Sgshapiro case SM_IO_APPEND_B: 79120256Sgshapiro stdiomode = "ab"; 80120256Sgshapiro break; 81120256Sgshapiro case SM_IO_APPENDRW_B: 82120256Sgshapiro stdiomode = "a+b"; 83120256Sgshapiro break; 84120256Sgshapiro case SM_IO_RDWR_B: 85120256Sgshapiro stdiomode = "r+b"; 86120256Sgshapiro break; 87120256Sgshapiro#endif /* SM_IO_BINARY != 0 */ 8890792Sgshapiro case SM_IO_RDWR: 8990792Sgshapiro default: 9090792Sgshapiro stdiomode = "r+"; 9190792Sgshapiro break; 9290792Sgshapiro } 9390792Sgshapiro 9490792Sgshapiro if ((s = fopen((char *)info, stdiomode)) == NULL) 9590792Sgshapiro return -1; 9690792Sgshapiro fp->f_cookie = s; 9790792Sgshapiro return 0; 9890792Sgshapiro} 9990792Sgshapiro 10090792Sgshapiro/* 10190792Sgshapiro** SETUP -- assign file type cookie when not already assigned 10290792Sgshapiro** 10390792Sgshapiro** Parameters: 10490792Sgshapiro** fp - the file pointer to get the cookie assigned 10590792Sgshapiro** 10690792Sgshapiro** Return: 10790792Sgshapiro** none. 10890792Sgshapiro*/ 10990792Sgshapiro 11090792Sgshapirostatic void 11190792Sgshapirosetup(fp) 11290792Sgshapiro SM_FILE_T *fp; 11390792Sgshapiro{ 11490792Sgshapiro if (fp->f_cookie == NULL) 11590792Sgshapiro { 11690792Sgshapiro switch (fp->f_ival) 11790792Sgshapiro { 11890792Sgshapiro case 0: 11990792Sgshapiro fp->f_cookie = stdin; 12090792Sgshapiro break; 12190792Sgshapiro case 1: 12290792Sgshapiro fp->f_cookie = stdout; 12390792Sgshapiro break; 12490792Sgshapiro case 2: 12590792Sgshapiro fp->f_cookie = stderr; 12690792Sgshapiro break; 12790792Sgshapiro default: 12890792Sgshapiro sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival); 12990792Sgshapiro break; 13090792Sgshapiro } 13190792Sgshapiro } 13290792Sgshapiro} 13390792Sgshapiro 13490792Sgshapiro/* 13590792Sgshapiro** SM_STDIOREAD -- read from the file 13690792Sgshapiro** 13790792Sgshapiro** Parameters: 13890792Sgshapiro** fp -- the file pointer 13990792Sgshapiro** buf -- location to place the read data 14090792Sgshapiro** n - number of bytes to read 14190792Sgshapiro** 14290792Sgshapiro** Returns: 14390792Sgshapiro** result from fread(). 14490792Sgshapiro*/ 14590792Sgshapiro 14690792Sgshapirossize_t 14790792Sgshapirosm_stdioread(fp, buf, n) 14890792Sgshapiro SM_FILE_T *fp; 14990792Sgshapiro char *buf; 15090792Sgshapiro size_t n; 15190792Sgshapiro{ 15290792Sgshapiro register FILE *s; 15390792Sgshapiro 15490792Sgshapiro if (fp->f_cookie == NULL) 15590792Sgshapiro setup(fp); 15690792Sgshapiro s = fp->f_cookie; 15790792Sgshapiro return fread(buf, 1, n, s); 15890792Sgshapiro} 15990792Sgshapiro 16090792Sgshapiro/* 16190792Sgshapiro** SM_STDIOWRITE -- write to the file 16290792Sgshapiro** 16390792Sgshapiro** Parameters: 16490792Sgshapiro** fp -- the file pointer 16590792Sgshapiro** buf -- location of data to write 16690792Sgshapiro** n - number of bytes to write 16790792Sgshapiro** 16890792Sgshapiro** Returns: 16990792Sgshapiro** result from fwrite(). 17090792Sgshapiro*/ 17190792Sgshapiro 17290792Sgshapirossize_t 17390792Sgshapirosm_stdiowrite(fp, buf, n) 17490792Sgshapiro SM_FILE_T *fp; 17590792Sgshapiro char const *buf; 17690792Sgshapiro size_t n; 17790792Sgshapiro{ 17890792Sgshapiro register FILE *s; 17990792Sgshapiro 18090792Sgshapiro if (fp->f_cookie == NULL) 18190792Sgshapiro setup(fp); 18290792Sgshapiro s = fp->f_cookie; 18390792Sgshapiro return fwrite(buf, 1, n, s); 18490792Sgshapiro} 18590792Sgshapiro 18690792Sgshapiro/* 18790792Sgshapiro** SM_STDIOSEEK -- set position within file 18890792Sgshapiro** 18990792Sgshapiro** Parameters: 19090792Sgshapiro** fp -- the file pointer 19190792Sgshapiro** offset -- new location based on 'whence' 19290792Sgshapiro** whence -- indicates "base" for 'offset' 19390792Sgshapiro** 19490792Sgshapiro** Returns: 19590792Sgshapiro** result from fseek(). 19690792Sgshapiro*/ 19790792Sgshapiro 19890792Sgshapirooff_t 19990792Sgshapirosm_stdioseek(fp, offset, whence) 20090792Sgshapiro SM_FILE_T *fp; 20190792Sgshapiro off_t offset; 20290792Sgshapiro int whence; 20390792Sgshapiro{ 20490792Sgshapiro register FILE *s; 20590792Sgshapiro 20690792Sgshapiro if (fp->f_cookie == NULL) 20790792Sgshapiro setup(fp); 20890792Sgshapiro s = fp->f_cookie; 20990792Sgshapiro return fseek(s, offset, whence); 21090792Sgshapiro} 21190792Sgshapiro 21290792Sgshapiro/* 21390792Sgshapiro** SM_STDIOCLOSE -- close the file 21490792Sgshapiro** 21590792Sgshapiro** Parameters: 21690792Sgshapiro** fp -- close file pointer 21790792Sgshapiro** 21890792Sgshapiro** Return: 21990792Sgshapiro** status from fclose() 22090792Sgshapiro*/ 22190792Sgshapiro 22290792Sgshapiroint 22390792Sgshapirosm_stdioclose(fp) 22490792Sgshapiro SM_FILE_T *fp; 22590792Sgshapiro{ 22690792Sgshapiro register FILE *s; 22790792Sgshapiro 22890792Sgshapiro if (fp->f_cookie == NULL) 22990792Sgshapiro setup(fp); 23090792Sgshapiro s = fp->f_cookie; 23190792Sgshapiro return fclose(s); 23290792Sgshapiro} 23390792Sgshapiro 23490792Sgshapiro/* 23590792Sgshapiro** SM_STDIOSETINFO -- set info for this open file 23690792Sgshapiro** 23790792Sgshapiro** Parameters: 23890792Sgshapiro** fp -- the file pointer 23990792Sgshapiro** what -- type of information setting 24090792Sgshapiro** valp -- memory location of info to set 24190792Sgshapiro** 24290792Sgshapiro** Return: 24390792Sgshapiro** Failure: -1 and sets errno 24490792Sgshapiro** Success: none (currently). 24590792Sgshapiro*/ 24690792Sgshapiro 24790792Sgshapiro/* ARGSUSED2 */ 24890792Sgshapiroint 24990792Sgshapirosm_stdiosetinfo(fp, what, valp) 25090792Sgshapiro SM_FILE_T *fp; 25190792Sgshapiro int what; 25290792Sgshapiro void *valp; 25390792Sgshapiro{ 25490792Sgshapiro switch (what) 25590792Sgshapiro { 25690792Sgshapiro case SM_IO_WHAT_MODE: 25790792Sgshapiro default: 25890792Sgshapiro errno = EINVAL; 25990792Sgshapiro return -1; 26090792Sgshapiro } 26190792Sgshapiro} 26290792Sgshapiro 26390792Sgshapiro/* 26490792Sgshapiro** SM_STDIOGETINFO -- get info for this open file 26590792Sgshapiro** 26690792Sgshapiro** Parameters: 26790792Sgshapiro** fp -- the file pointer 26890792Sgshapiro** what -- type of information request 26990792Sgshapiro** valp -- memory location to place info 27090792Sgshapiro** 27190792Sgshapiro** Return: 27290792Sgshapiro** Failure: -1 and sets errno 27390792Sgshapiro** Success: none (currently). 27490792Sgshapiro*/ 27590792Sgshapiro 27690792Sgshapiro/* ARGSUSED2 */ 27790792Sgshapiroint 27890792Sgshapirosm_stdiogetinfo(fp, what, valp) 27990792Sgshapiro SM_FILE_T *fp; 28090792Sgshapiro int what; 28190792Sgshapiro void *valp; 28290792Sgshapiro{ 28390792Sgshapiro switch (what) 28490792Sgshapiro { 28594334Sgshapiro case SM_IO_WHAT_SIZE: 28694334Sgshapiro { 28794334Sgshapiro int fd; 28894334Sgshapiro struct stat st; 28994334Sgshapiro 29094334Sgshapiro if (fp->f_cookie == NULL) 29194334Sgshapiro setup(fp); 29294334Sgshapiro fd = fileno((FILE *) fp->f_cookie); 29394334Sgshapiro if (fd < 0) 29494334Sgshapiro return -1; 29594334Sgshapiro if (fstat(fd, &st) == 0) 29694334Sgshapiro return st.st_size; 29794334Sgshapiro else 29894334Sgshapiro return -1; 29994334Sgshapiro } 30094334Sgshapiro 30190792Sgshapiro case SM_IO_WHAT_MODE: 30290792Sgshapiro default: 30390792Sgshapiro errno = EINVAL; 30490792Sgshapiro return -1; 30590792Sgshapiro } 30690792Sgshapiro} 30790792Sgshapiro 30890792Sgshapiro/* 30990792Sgshapiro** SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE 31090792Sgshapiro** 31190792Sgshapiro** Parameters: 31290792Sgshapiro** stream -- an open stdio stream, as returned by fopen() 31390792Sgshapiro** mode -- the mode argument to fopen() which describes stream 31490792Sgshapiro** 31590792Sgshapiro** Return: 31690792Sgshapiro** On success, return a pointer to an SM_FILE object which 31790792Sgshapiro** can be used for reading and writing 'stream'. 31890792Sgshapiro** Abort if mode is gibberish or stream is bad. 31990792Sgshapiro** Raise an exception if we can't allocate memory. 32090792Sgshapiro*/ 32190792Sgshapiro 32290792SgshapiroSM_FILE_T * 32390792Sgshapirosm_io_stdioopen(stream, mode) 32490792Sgshapiro FILE *stream; 32590792Sgshapiro char *mode; 32690792Sgshapiro{ 32790792Sgshapiro int fd; 32890792Sgshapiro bool r, w; 32990792Sgshapiro int ioflags; 33090792Sgshapiro SM_FILE_T *fp; 33190792Sgshapiro 33290792Sgshapiro fd = fileno(stream); 33390792Sgshapiro SM_REQUIRE(fd >= 0); 33490792Sgshapiro 33590792Sgshapiro r = w = false; 33690792Sgshapiro switch (mode[0]) 33790792Sgshapiro { 33890792Sgshapiro case 'r': 33990792Sgshapiro r = true; 34090792Sgshapiro break; 34190792Sgshapiro case 'w': 34290792Sgshapiro case 'a': 34390792Sgshapiro w = true; 34490792Sgshapiro break; 34590792Sgshapiro default: 34690792Sgshapiro sm_abort("sm_io_stdioopen: mode '%s' is bad", mode); 34790792Sgshapiro } 34890792Sgshapiro if (strchr(&mode[1], '+') != NULL) 34990792Sgshapiro r = w = true; 35090792Sgshapiro if (r && w) 35190792Sgshapiro ioflags = SMRW; 35290792Sgshapiro else if (r) 35390792Sgshapiro ioflags = SMRD; 35490792Sgshapiro else 35590792Sgshapiro ioflags = SMWR; 35690792Sgshapiro 35790792Sgshapiro fp = sm_fp(SmFtRealStdio, ioflags, NULL); 35890792Sgshapiro fp->f_file = fd; 35990792Sgshapiro fp->f_cookie = stream; 36090792Sgshapiro return fp; 36190792Sgshapiro} 362