190792Sgshapiro/* 2261194Sgshapiro * Copyright (c) 2000-2002, 2004, 2005 Proofpoint, Inc. and its suppliers. 390792Sgshapiro * All rights reserved. 490792Sgshapiro * Copyright (c) 1990, 1993 590792Sgshapiro * The Regents of the University of California. All rights reserved. 690792Sgshapiro * 790792Sgshapiro * This code is derived from software contributed to Berkeley by 890792Sgshapiro * Chris Torek. 990792Sgshapiro * 1090792Sgshapiro * By using this file, you agree to the terms and conditions set 1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of 1290792Sgshapiro * the sendmail distribution. 1390792Sgshapiro */ 1490792Sgshapiro 1590792Sgshapiro#include <sm/gen.h> 16266527SgshapiroSM_IDSTR(id, "@(#)$Id: strio.c,v 1.45 2013-11-22 20:51:43 ca Exp $") 1790792Sgshapiro#include <stdlib.h> 1890792Sgshapiro#include <unistd.h> 1990792Sgshapiro#include <fcntl.h> 2090792Sgshapiro#include <string.h> 2190792Sgshapiro#include <errno.h> 2290792Sgshapiro#include <sm/rpool.h> 2390792Sgshapiro#include <sm/io.h> 2490792Sgshapiro#include <sm/heap.h> 2590792Sgshapiro#include <sm/conf.h> 2690792Sgshapiro#include "local.h" 2790792Sgshapiro 28141858Sgshapirostatic int sm_strsetmode __P((SM_FILE_T*, const int *)); 29141858Sgshapirostatic int sm_strgetmode __P((SM_FILE_T*, int *)); 30141858Sgshapiro 3190792Sgshapiro/* 3290792Sgshapiro** Cookie structure for the "strio" file type 3390792Sgshapiro*/ 3490792Sgshapiro 3590792Sgshapirostruct sm_str_obj 3690792Sgshapiro{ 3794334Sgshapiro char *strio_base; 3894334Sgshapiro char *strio_end; 3994334Sgshapiro size_t strio_size; 4094334Sgshapiro size_t strio_offset; 4194334Sgshapiro int strio_flags; 4294334Sgshapiro const void *strio_rpool; 4390792Sgshapiro}; 4490792Sgshapiro 4590792Sgshapirotypedef struct sm_str_obj SM_STR_OBJ_T; 4690792Sgshapiro 4790792Sgshapiro/* 4890792Sgshapiro** SM_STRGROW -- increase storage space for string 4990792Sgshapiro** 5090792Sgshapiro** Parameters: 5190792Sgshapiro** s -- current cookie 5290792Sgshapiro** size -- new storage size request 5390792Sgshapiro** 5490792Sgshapiro** Returns: 5590792Sgshapiro** true iff successful. 5690792Sgshapiro*/ 5790792Sgshapiro 5890792Sgshapirostatic bool sm_strgrow __P((SM_STR_OBJ_T *, size_t)); 5990792Sgshapiro 6090792Sgshapirostatic bool 6190792Sgshapirosm_strgrow(s, size) 6290792Sgshapiro SM_STR_OBJ_T *s; 6390792Sgshapiro size_t size; 6490792Sgshapiro{ 6590792Sgshapiro register void *p; 6690792Sgshapiro 6790792Sgshapiro if (s->strio_size >= size) 6890792Sgshapiro return true; 6990792Sgshapiro p = sm_realloc(s->strio_base, size); 7090792Sgshapiro if (p == NULL) 7190792Sgshapiro return false; 7290792Sgshapiro s->strio_base = p; 7390792Sgshapiro s->strio_end = s->strio_base + size; 7490792Sgshapiro s->strio_size = size; 7590792Sgshapiro return true; 7690792Sgshapiro} 7790792Sgshapiro 7890792Sgshapiro/* 7990792Sgshapiro** SM_STRREAD -- read a portion of the string 8090792Sgshapiro** 8190792Sgshapiro** Parameters: 8290792Sgshapiro** fp -- the file pointer 8390792Sgshapiro** buf -- location to place read data 8490792Sgshapiro** n -- number of bytes to read 8590792Sgshapiro** 8690792Sgshapiro** Returns: 8790792Sgshapiro** Failure: -1 and sets errno 8890792Sgshapiro** Success: >=0, number of bytes read 8990792Sgshapiro*/ 9090792Sgshapiro 9190792Sgshapirossize_t 9290792Sgshapirosm_strread(fp, buf, n) 9390792Sgshapiro SM_FILE_T *fp; 9490792Sgshapiro char *buf; 9590792Sgshapiro size_t n; 9690792Sgshapiro{ 9790792Sgshapiro register SM_STR_OBJ_T *s = fp->f_cookie; 9890792Sgshapiro int len; 9990792Sgshapiro 10090792Sgshapiro if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW)) 10190792Sgshapiro { 10290792Sgshapiro errno = EBADF; 10390792Sgshapiro return -1; 10490792Sgshapiro } 10590792Sgshapiro len = SM_MIN(s->strio_size - s->strio_offset, n); 10690792Sgshapiro (void) memmove(buf, s->strio_base + s->strio_offset, len); 10790792Sgshapiro s->strio_offset += len; 10890792Sgshapiro return len; 10990792Sgshapiro} 11090792Sgshapiro 11190792Sgshapiro/* 11290792Sgshapiro** SM_STRWRITE -- write a portion of the string 11390792Sgshapiro** 11490792Sgshapiro** Parameters: 11590792Sgshapiro** fp -- the file pointer 11694334Sgshapiro** buf -- location of data for writing 11790792Sgshapiro** n -- number of bytes to write 11890792Sgshapiro** 11990792Sgshapiro** Returns: 12090792Sgshapiro** Failure: -1 and sets errno 12190792Sgshapiro** Success: >=0, number of bytes written 12290792Sgshapiro*/ 12390792Sgshapiro 12490792Sgshapirossize_t 12590792Sgshapirosm_strwrite(fp, buf, n) 12690792Sgshapiro SM_FILE_T *fp; 12790792Sgshapiro char const *buf; 12890792Sgshapiro size_t n; 12990792Sgshapiro{ 13090792Sgshapiro register SM_STR_OBJ_T *s = fp->f_cookie; 13190792Sgshapiro 13290792Sgshapiro if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW)) 13390792Sgshapiro { 13490792Sgshapiro errno = EBADF; 13590792Sgshapiro return -1; 13690792Sgshapiro } 13790792Sgshapiro if (n + s->strio_offset > s->strio_size) 13890792Sgshapiro { 13990792Sgshapiro if (!sm_strgrow(s, n + s->strio_offset)) 14090792Sgshapiro return 0; 14190792Sgshapiro } 14290792Sgshapiro (void) memmove(s->strio_base + s->strio_offset, buf, n); 14390792Sgshapiro s->strio_offset += n; 14490792Sgshapiro return n; 14590792Sgshapiro} 14690792Sgshapiro 14790792Sgshapiro/* 14890792Sgshapiro** SM_STRSEEK -- position the offset pointer for the string 14990792Sgshapiro** 15090792Sgshapiro** Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid 15190792Sgshapiro** values for whence. 15290792Sgshapiro** 15390792Sgshapiro** Parameters: 15490792Sgshapiro** fp -- the file pointer 15590792Sgshapiro** offset -- number of bytes offset from "base" 15690792Sgshapiro** whence -- determines "base" for 'offset' 15790792Sgshapiro** 15890792Sgshapiro** Returns: 15990792Sgshapiro** Failure: -1 and sets errno 16090792Sgshapiro** Success: >=0, number of bytes read 16190792Sgshapiro*/ 16290792Sgshapiro 16390792Sgshapirooff_t 16490792Sgshapirosm_strseek(fp, offset, whence) 16590792Sgshapiro SM_FILE_T *fp; 16690792Sgshapiro off_t offset; 16790792Sgshapiro int whence; 16890792Sgshapiro{ 16990792Sgshapiro register off_t ret; 17090792Sgshapiro register SM_STR_OBJ_T *s = fp->f_cookie; 17190792Sgshapiro 17290792Sgshapiroreseek: 17390792Sgshapiro switch (whence) 17490792Sgshapiro { 17590792Sgshapiro case SM_IO_SEEK_SET: 17690792Sgshapiro ret = offset; 17790792Sgshapiro break; 17890792Sgshapiro case SM_IO_SEEK_CUR: 17990792Sgshapiro ret = s->strio_offset + offset; 18090792Sgshapiro break; 18190792Sgshapiro case SM_IO_SEEK_END: 18290792Sgshapiro ret = s->strio_size; 18390792Sgshapiro break; 18490792Sgshapiro default: 18590792Sgshapiro errno = EINVAL; 18690792Sgshapiro return -1; 18790792Sgshapiro } 18890792Sgshapiro if (ret < 0 || ret > (off_t)(size_t)(-1)) /* XXX ugly */ 18990792Sgshapiro return -1; 19090792Sgshapiro if ((size_t) ret > s->strio_size) 19190792Sgshapiro { 19290792Sgshapiro if (sm_strgrow(s, (size_t)ret)) 19390792Sgshapiro goto reseek; 19490792Sgshapiro 19590792Sgshapiro /* errno set by sm_strgrow */ 19690792Sgshapiro return -1; 19790792Sgshapiro } 19890792Sgshapiro s->strio_offset = (size_t) ret; 19990792Sgshapiro return ret; 20090792Sgshapiro} 20190792Sgshapiro 20290792Sgshapiro/* 20390792Sgshapiro** SM_STROPEN -- open a string file type 20490792Sgshapiro** 20590792Sgshapiro** Parameters: 20690792Sgshapiro** fp -- file pointer open to be associated with 20794334Sgshapiro** info -- initial contents (NULL for none) 20894334Sgshapiro** flags -- flags for methods of access (was mode) 20990792Sgshapiro** rpool -- resource pool to use memory from (if applicable) 21090792Sgshapiro** 21190792Sgshapiro** Results: 21290792Sgshapiro** Success: 0 (zero) 21390792Sgshapiro** Failure: -1 and sets errno 21490792Sgshapiro*/ 21590792Sgshapiro 21690792Sgshapiroint 21790792Sgshapirosm_stropen(fp, info, flags, rpool) 21890792Sgshapiro SM_FILE_T *fp; 21990792Sgshapiro const void *info; 22090792Sgshapiro int flags; 22190792Sgshapiro const void *rpool; 22290792Sgshapiro{ 22390792Sgshapiro register SM_STR_OBJ_T *s; 22490792Sgshapiro 22590792Sgshapiro#if SM_RPOOL 22690792Sgshapiro s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T)); 22790792Sgshapiro#else /* SM_RPOOL */ 22890792Sgshapiro s = sm_malloc(sizeof(SM_STR_OBJ_T)); 22990792Sgshapiro if (s == NULL) 23090792Sgshapiro return -1; 23190792Sgshapiro#endif /* SM_RPOOL */ 23290792Sgshapiro 23390792Sgshapiro fp->f_cookie = s; 23494334Sgshapiro s->strio_rpool = rpool; 23590792Sgshapiro s->strio_offset = 0; 23694334Sgshapiro s->strio_size = 0; 23794334Sgshapiro s->strio_base = NULL; 23890792Sgshapiro s->strio_end = 0; 23994334Sgshapiro 24094334Sgshapiro switch (flags) 24190792Sgshapiro { 24290792Sgshapiro case SM_IO_RDWR: 24390792Sgshapiro s->strio_flags = SMRW; 24490792Sgshapiro break; 24590792Sgshapiro case SM_IO_RDONLY: 24690792Sgshapiro s->strio_flags = SMRD; 24790792Sgshapiro break; 24890792Sgshapiro case SM_IO_WRONLY: 24990792Sgshapiro s->strio_flags = SMWR; 25090792Sgshapiro break; 25190792Sgshapiro case SM_IO_APPEND: 25294334Sgshapiro if (s->strio_rpool == NULL) 25394334Sgshapiro sm_free(s); 25494334Sgshapiro errno = EINVAL; 25590792Sgshapiro return -1; 25690792Sgshapiro default: 25794334Sgshapiro if (s->strio_rpool == NULL) 25894334Sgshapiro sm_free(s); 25990792Sgshapiro errno = EINVAL; 26090792Sgshapiro return -1; 26190792Sgshapiro } 26294334Sgshapiro 26394334Sgshapiro if (info != NULL) 26494334Sgshapiro { 26594334Sgshapiro s->strio_base = sm_strdup_x(info); 26694334Sgshapiro if (s->strio_base == NULL) 26794334Sgshapiro { 26894334Sgshapiro int save_errno = errno; 26994334Sgshapiro 27094334Sgshapiro if (s->strio_rpool == NULL) 27194334Sgshapiro sm_free(s); 27294334Sgshapiro errno = save_errno; 27394334Sgshapiro return -1; 27494334Sgshapiro } 27594334Sgshapiro s->strio_size = strlen(info); 27694334Sgshapiro s->strio_end = s->strio_base + s->strio_size; 27794334Sgshapiro } 27890792Sgshapiro return 0; 27990792Sgshapiro} 28090792Sgshapiro 28190792Sgshapiro/* 28290792Sgshapiro** SM_STRCLOSE -- close the string file type and free resources 28390792Sgshapiro** 28490792Sgshapiro** Parameters: 28590792Sgshapiro** fp -- file pointer 28690792Sgshapiro** 28790792Sgshapiro** Results: 28890792Sgshapiro** Success: 0 (zero) 28990792Sgshapiro*/ 29090792Sgshapiro 29190792Sgshapiroint 29290792Sgshapirosm_strclose(fp) 29390792Sgshapiro SM_FILE_T *fp; 29490792Sgshapiro{ 29590792Sgshapiro SM_STR_OBJ_T *s = fp->f_cookie; 29690792Sgshapiro 29790792Sgshapiro#if !SM_RPOOL 29890792Sgshapiro sm_free(s->strio_base); 29990792Sgshapiro s->strio_base = NULL; 30090792Sgshapiro#endif /* !SM_RPOOL */ 30190792Sgshapiro return 0; 30290792Sgshapiro} 30390792Sgshapiro 30490792Sgshapiro/* 30590792Sgshapiro** SM_STRSETMODE -- set mode info for the file 30690792Sgshapiro** 30790792Sgshapiro** Note: changing the mode can be a safe way to have the "parent" 30890792Sgshapiro** set up a string that the "child" is not to modify 30990792Sgshapiro** 31090792Sgshapiro** Parameters: 31190792Sgshapiro** fp -- the file pointer 31290792Sgshapiro** mode -- location of new mode to set 31390792Sgshapiro** 31490792Sgshapiro** Results: 31590792Sgshapiro** Success: 0 (zero) 31690792Sgshapiro** Failure: -1 and sets errno 31790792Sgshapiro*/ 31890792Sgshapiro 319141858Sgshapirostatic int 32090792Sgshapirosm_strsetmode(fp, mode) 32190792Sgshapiro SM_FILE_T *fp; 32290792Sgshapiro const int *mode; 32390792Sgshapiro{ 32490792Sgshapiro register SM_STR_OBJ_T *s = fp->f_cookie; 32590792Sgshapiro int flags; 32690792Sgshapiro 32790792Sgshapiro switch (*mode) 32890792Sgshapiro { 32990792Sgshapiro case SM_IO_RDWR: 33090792Sgshapiro flags = SMRW; 33190792Sgshapiro break; 33290792Sgshapiro case SM_IO_RDONLY: 33390792Sgshapiro flags = SMRD; 33490792Sgshapiro break; 33590792Sgshapiro case SM_IO_WRONLY: 33690792Sgshapiro flags = SMWR; 33790792Sgshapiro break; 33890792Sgshapiro case SM_IO_APPEND: 33990792Sgshapiro errno = EINVAL; 34090792Sgshapiro return -1; 34190792Sgshapiro default: 34290792Sgshapiro errno = EINVAL; 34390792Sgshapiro return -1; 34490792Sgshapiro } 34590792Sgshapiro s->strio_flags &= ~SMMODEMASK; 34690792Sgshapiro s->strio_flags |= flags; 34790792Sgshapiro return 0; 34890792Sgshapiro} 34990792Sgshapiro 35090792Sgshapiro/* 35190792Sgshapiro** SM_STRGETMODE -- get mode info for the file 35290792Sgshapiro** 35390792Sgshapiro** Parameters: 35490792Sgshapiro** fp -- the file pointer 35590792Sgshapiro** mode -- location to store current mode 35690792Sgshapiro** 35790792Sgshapiro** Results: 35890792Sgshapiro** Success: 0 (zero) 35990792Sgshapiro** Failure: -1 and sets errno 36090792Sgshapiro*/ 36190792Sgshapiro 362157001Sgshapirostatic int 36390792Sgshapirosm_strgetmode(fp, mode) 36490792Sgshapiro SM_FILE_T *fp; 36590792Sgshapiro int *mode; 36690792Sgshapiro{ 36790792Sgshapiro register SM_STR_OBJ_T *s = fp->f_cookie; 36890792Sgshapiro 36990792Sgshapiro switch (s->strio_flags & SMMODEMASK) 37090792Sgshapiro { 37190792Sgshapiro case SMRW: 37290792Sgshapiro *mode = SM_IO_RDWR; 37390792Sgshapiro break; 37490792Sgshapiro case SMRD: 37590792Sgshapiro *mode = SM_IO_RDONLY; 37690792Sgshapiro break; 37790792Sgshapiro case SMWR: 37890792Sgshapiro *mode = SM_IO_WRONLY; 37990792Sgshapiro break; 38090792Sgshapiro default: 38190792Sgshapiro errno = EINVAL; 38290792Sgshapiro return -1; 38390792Sgshapiro } 38490792Sgshapiro return 0; 38590792Sgshapiro} 38690792Sgshapiro 38790792Sgshapiro/* 38890792Sgshapiro** SM_STRSETINFO -- set info for the file 38990792Sgshapiro** 39090792Sgshapiro** Currently only SM_IO_WHAT_MODE is supported for 'what'. 39190792Sgshapiro** 39290792Sgshapiro** Parameters: 39390792Sgshapiro** fp -- the file pointer 39490792Sgshapiro** what -- type of information to set 39590792Sgshapiro** valp -- location to data for doing set 39690792Sgshapiro** 39790792Sgshapiro** Results: 39890792Sgshapiro** Failure: -1 and sets errno 39990792Sgshapiro** Success: sm_strsetmode() return [0 (zero)] 40090792Sgshapiro*/ 40190792Sgshapiro 40290792Sgshapiroint 40390792Sgshapirosm_strsetinfo(fp, what, valp) 40490792Sgshapiro SM_FILE_T *fp; 40590792Sgshapiro int what; 40690792Sgshapiro void *valp; 40790792Sgshapiro{ 40890792Sgshapiro switch(what) 40990792Sgshapiro { 41090792Sgshapiro case SM_IO_WHAT_MODE: 41190792Sgshapiro return sm_strsetmode(fp, (int *) valp); 41290792Sgshapiro default: 41390792Sgshapiro errno = EINVAL; 41490792Sgshapiro return -1; 41590792Sgshapiro } 41690792Sgshapiro} 41790792Sgshapiro 41890792Sgshapiro/* 41990792Sgshapiro** SM_STRGETINFO -- get info for the file 42090792Sgshapiro** 42190792Sgshapiro** Currently only SM_IO_WHAT_MODE is supported for 'what'. 42290792Sgshapiro** 42390792Sgshapiro** Parameters: 42490792Sgshapiro** fp -- the file pointer 42590792Sgshapiro** what -- type of information requested 42690792Sgshapiro** valp -- location to return information in 42790792Sgshapiro** 42890792Sgshapiro** Results: 42990792Sgshapiro** Failure: -1 and sets errno 43090792Sgshapiro** Success: sm_strgetmode() return [0 (zero)] 43190792Sgshapiro*/ 43290792Sgshapiro 43390792Sgshapiroint 43490792Sgshapirosm_strgetinfo(fp, what, valp) 43590792Sgshapiro SM_FILE_T *fp; 43690792Sgshapiro int what; 43790792Sgshapiro void *valp; 43890792Sgshapiro{ 43990792Sgshapiro switch(what) 44090792Sgshapiro { 44190792Sgshapiro case SM_IO_WHAT_MODE: 44290792Sgshapiro return sm_strgetmode(fp, (int *) valp); 44390792Sgshapiro default: 44490792Sgshapiro errno = EINVAL; 44590792Sgshapiro return -1; 44690792Sgshapiro } 44790792Sgshapiro} 44890792Sgshapiro 44990792Sgshapiro/* 45090792Sgshapiro** SM_STRIO_INIT -- initializes a write-only string type 45190792Sgshapiro** 45290792Sgshapiro** Original comments below. This function does not appear to be used anywhere. 45390792Sgshapiro** The same functionality can be done by changing the mode of the file. 45490792Sgshapiro** ------------ 45590792Sgshapiro** sm_strio_init initializes an SM_FILE_T structure as a write-only file 45690792Sgshapiro** that writes into the specified buffer: 45790792Sgshapiro** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer. 45890792Sgshapiro** Attempts to write more than size-1 characters into the buffer will fail 45990792Sgshapiro** silently (no error is reported). 46090792Sgshapiro** - Use sm_io_fflush to nul terminate the string in the buffer 46190792Sgshapiro** (the write pointer is not advanced). 46290792Sgshapiro** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc. 46390792Sgshapiro** 46490792Sgshapiro** Parameters: 46590792Sgshapiro** fp -- file pointer 46690792Sgshapiro** buf -- memory location for stored data 46790792Sgshapiro** size -- size of 'buf' 46890792Sgshapiro** 46990792Sgshapiro** Results: 47090792Sgshapiro** none. 47190792Sgshapiro*/ 47290792Sgshapiro 47390792Sgshapirovoid 47490792Sgshapirosm_strio_init(fp, buf, size) 47590792Sgshapiro SM_FILE_T *fp; 47690792Sgshapiro char *buf; 47790792Sgshapiro size_t size; 47890792Sgshapiro{ 47990792Sgshapiro fp->sm_magic = SmFileMagic; 48090792Sgshapiro fp->f_flags = SMWR | SMSTR; 48190792Sgshapiro fp->f_file = -1; 48290792Sgshapiro fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf; 48390792Sgshapiro fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0); 48490792Sgshapiro fp->f_lbfsize = 0; 48590792Sgshapiro fp->f_r = 0; 48690792Sgshapiro fp->f_read = NULL; 48790792Sgshapiro fp->f_seek = NULL; 48890792Sgshapiro fp->f_getinfo = NULL; 48990792Sgshapiro fp->f_setinfo = NULL; 49090792Sgshapiro} 491