strio.c revision 141858
1239278Sgonzo/*
2239278Sgonzo * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
3239278Sgonzo *      All rights reserved.
4239278Sgonzo * Copyright (c) 1990, 1993
5239278Sgonzo *	The Regents of the University of California.  All rights reserved.
6239278Sgonzo *
7239278Sgonzo * This code is derived from software contributed to Berkeley by
8239278Sgonzo * Chris Torek.
9239278Sgonzo *
10239278Sgonzo * By using this file, you agree to the terms and conditions set
11239278Sgonzo * forth in the LICENSE file which can be found at the top level of
12239278Sgonzo * the sendmail distribution.
13239278Sgonzo */
14239278Sgonzo
15239278Sgonzo#include <sm/gen.h>
16239278SgonzoSM_IDSTR(id, "@(#)$Id: strio.c,v 1.43 2004/08/03 20:48:30 ca Exp $")
17239278Sgonzo#include <stdlib.h>
18239278Sgonzo#include <unistd.h>
19239278Sgonzo#include <fcntl.h>
20239278Sgonzo#include <string.h>
21239278Sgonzo#include <errno.h>
22239278Sgonzo#include <sm/rpool.h>
23239278Sgonzo#include <sm/io.h>
24239278Sgonzo#include <sm/heap.h>
25239278Sgonzo#include <sm/conf.h>
26239278Sgonzo#include "local.h"
27239278Sgonzo
28239278Sgonzostatic int	sm_strsetmode __P((SM_FILE_T*, const int *));
29239278Sgonzostatic int	sm_strgetmode __P((SM_FILE_T*, int *));
30239278Sgonzo
31239278Sgonzo/*
32239278Sgonzo**  Cookie structure for the "strio" file type
33239278Sgonzo*/
34239278Sgonzo
35239278Sgonzostruct sm_str_obj
36239278Sgonzo{
37239278Sgonzo	char		*strio_base;
38239278Sgonzo	char		*strio_end;
39239278Sgonzo	size_t		strio_size;
40239278Sgonzo	size_t		strio_offset;
41239278Sgonzo	int		strio_flags;
42239278Sgonzo	const void	*strio_rpool;
43239278Sgonzo};
44239278Sgonzo
45239278Sgonzotypedef struct sm_str_obj SM_STR_OBJ_T;
46239278Sgonzo
47239278Sgonzo/*
48239278Sgonzo**  SM_STRGROW -- increase storage space for string
49239278Sgonzo**
50239278Sgonzo**	Parameters:
51239278Sgonzo**		s -- current cookie
52239278Sgonzo**		size -- new storage size request
53239278Sgonzo**
54239278Sgonzo**	Returns:
55239278Sgonzo**		true iff successful.
56239278Sgonzo*/
57239278Sgonzo
58239278Sgonzostatic bool sm_strgrow __P((SM_STR_OBJ_T *, size_t));
59239278Sgonzo
60239278Sgonzostatic bool
61239278Sgonzosm_strgrow(s, size)
62239278Sgonzo	SM_STR_OBJ_T *s;
63239278Sgonzo	size_t size;
64239278Sgonzo{
65239278Sgonzo	register void *p;
66239278Sgonzo
67239278Sgonzo	if (s->strio_size >= size)
68239278Sgonzo		return true;
69239278Sgonzo	p = sm_realloc(s->strio_base, size);
70239278Sgonzo	if (p == NULL)
71239278Sgonzo		return false;
72239278Sgonzo	s->strio_base = p;
73239278Sgonzo	s->strio_end = s->strio_base + size;
74239278Sgonzo	s->strio_size = size;
75239278Sgonzo	return true;
76239278Sgonzo}
77239278Sgonzo
78239278Sgonzo/*
79239278Sgonzo**  SM_STRREAD -- read a portion of the string
80239278Sgonzo**
81239278Sgonzo**	Parameters:
82239278Sgonzo**		fp -- the file pointer
83239278Sgonzo**		buf -- location to place read data
84239278Sgonzo**		n -- number of bytes to read
85239278Sgonzo**
86239278Sgonzo**	Returns:
87239278Sgonzo**		Failure: -1 and sets errno
88239278Sgonzo**		Success: >=0, number of bytes read
89239278Sgonzo*/
90239278Sgonzo
91239278Sgonzossize_t
92239278Sgonzosm_strread(fp, buf, n)
93239278Sgonzo	SM_FILE_T *fp;
94239278Sgonzo	char *buf;
95239278Sgonzo	size_t n;
96239278Sgonzo{
97239278Sgonzo	register SM_STR_OBJ_T *s = fp->f_cookie;
98239278Sgonzo	int len;
99239278Sgonzo
100239278Sgonzo	if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW))
101239278Sgonzo	{
102239278Sgonzo		errno = EBADF;
103239278Sgonzo		return -1;
104239278Sgonzo	}
105239278Sgonzo	len = SM_MIN(s->strio_size - s->strio_offset, n);
106239278Sgonzo	(void) memmove(buf, s->strio_base + s->strio_offset, len);
107239278Sgonzo	s->strio_offset += len;
108239278Sgonzo	return len;
109239278Sgonzo}
110239278Sgonzo
111239278Sgonzo/*
112239278Sgonzo**  SM_STRWRITE -- write a portion of the string
113239278Sgonzo**
114239278Sgonzo**	Parameters:
115239278Sgonzo**		fp -- the file pointer
116239278Sgonzo**		buf -- location of data for writing
117239278Sgonzo**		n -- number of bytes to write
118239278Sgonzo**
119239278Sgonzo**	Returns:
120239278Sgonzo**		Failure: -1 and sets errno
121239278Sgonzo**		Success: >=0, number of bytes written
122239278Sgonzo*/
123239278Sgonzo
124239278Sgonzossize_t
125239278Sgonzosm_strwrite(fp, buf, n)
126239278Sgonzo	SM_FILE_T *fp;
127239278Sgonzo	char const *buf;
128239278Sgonzo	size_t n;
129239278Sgonzo{
130239278Sgonzo	register SM_STR_OBJ_T *s = fp->f_cookie;
131239278Sgonzo
132239278Sgonzo	if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW))
133239278Sgonzo	{
134239278Sgonzo		errno = EBADF;
135239278Sgonzo		return -1;
136239278Sgonzo	}
137239278Sgonzo	if (n + s->strio_offset > s->strio_size)
138239278Sgonzo	{
139239278Sgonzo		if (!sm_strgrow(s, n + s->strio_offset))
140239278Sgonzo			return 0;
141239278Sgonzo	}
142239278Sgonzo	(void) memmove(s->strio_base + s->strio_offset, buf, n);
143239278Sgonzo	s->strio_offset += n;
144239278Sgonzo	return n;
145239278Sgonzo}
146239278Sgonzo
147239278Sgonzo/*
148239278Sgonzo**  SM_STRSEEK -- position the offset pointer for the string
149239278Sgonzo**
150239278Sgonzo**	Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid
151239278Sgonzo**	values for whence.
152239278Sgonzo**
153239278Sgonzo**	Parameters:
154239278Sgonzo**		fp -- the file pointer
155239278Sgonzo**		offset -- number of bytes offset from "base"
156239278Sgonzo**		whence -- determines "base" for 'offset'
157239278Sgonzo**
158239278Sgonzo**	Returns:
159239278Sgonzo**		Failure: -1 and sets errno
160239278Sgonzo**		Success: >=0, number of bytes read
161239278Sgonzo*/
162239278Sgonzo
163239278Sgonzooff_t
164239278Sgonzosm_strseek(fp, offset, whence)
165239278Sgonzo	SM_FILE_T *fp;
166239278Sgonzo	off_t offset;
167239278Sgonzo	int whence;
168239278Sgonzo{
169261410Sian	register off_t ret;
170261410Sian	register SM_STR_OBJ_T *s = fp->f_cookie;
171261410Sian
172261410Sianreseek:
173239278Sgonzo	switch (whence)
174239278Sgonzo	{
175239278Sgonzo	  case SM_IO_SEEK_SET:
176239278Sgonzo		ret = offset;
177239278Sgonzo		break;
178239278Sgonzo	  case SM_IO_SEEK_CUR:
179239278Sgonzo		ret = s->strio_offset + offset;
180239278Sgonzo		break;
181239278Sgonzo	  case SM_IO_SEEK_END:
182239278Sgonzo		ret = s->strio_size;
183239278Sgonzo		break;
184239278Sgonzo	  default:
185239278Sgonzo		errno = EINVAL;
186239278Sgonzo		return -1;
187239278Sgonzo	}
188239278Sgonzo	if (ret < 0 || ret > (off_t)(size_t)(-1))	/* XXX ugly */
189239278Sgonzo		return -1;
190239278Sgonzo	if ((size_t) ret > s->strio_size)
191239278Sgonzo	{
192239278Sgonzo		if (sm_strgrow(s, (size_t)ret))
193239278Sgonzo			goto reseek;
194239278Sgonzo
195239278Sgonzo		/* errno set by sm_strgrow */
196239278Sgonzo		return -1;
197239278Sgonzo	}
198239278Sgonzo	s->strio_offset = (size_t) ret;
199239278Sgonzo	return ret;
200239278Sgonzo}
201239278Sgonzo
202239278Sgonzo/*
203239278Sgonzo**  SM_STROPEN -- open a string file type
204239278Sgonzo**
205239278Sgonzo**	Parameters:
206239278Sgonzo**		fp -- file pointer open to be associated with
207239278Sgonzo**		info -- initial contents (NULL for none)
208239278Sgonzo**		flags -- flags for methods of access (was mode)
209239278Sgonzo**		rpool -- resource pool to use memory from (if applicable)
210239278Sgonzo**
211239278Sgonzo**	Results:
212239278Sgonzo**		Success: 0 (zero)
213239278Sgonzo**		Failure: -1 and sets errno
214239278Sgonzo*/
215239278Sgonzo
216239278Sgonzoint
217239278Sgonzosm_stropen(fp, info, flags, rpool)
218239278Sgonzo	SM_FILE_T *fp;
219239278Sgonzo	const void *info;
220239278Sgonzo	int flags;
221239278Sgonzo	const void *rpool;
222239278Sgonzo{
223239278Sgonzo	register SM_STR_OBJ_T *s;
224239278Sgonzo
225239278Sgonzo#if SM_RPOOL
226239278Sgonzo	s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T));
227239278Sgonzo#else /* SM_RPOOL */
228239278Sgonzo	s = sm_malloc(sizeof(SM_STR_OBJ_T));
229239278Sgonzo	if (s == NULL)
230239278Sgonzo		return -1;
231239278Sgonzo#endif /* SM_RPOOL */
232239278Sgonzo
233239278Sgonzo	fp->f_cookie = s;
234239278Sgonzo	s->strio_rpool = rpool;
235239278Sgonzo	s->strio_offset = 0;
236239278Sgonzo	s->strio_size = 0;
237239278Sgonzo	s->strio_base = NULL;
238239278Sgonzo	s->strio_end = 0;
239239278Sgonzo
240239278Sgonzo	switch (flags)
241239278Sgonzo	{
242239278Sgonzo	  case SM_IO_RDWR:
243239278Sgonzo		s->strio_flags = SMRW;
244239278Sgonzo		break;
245239278Sgonzo	  case SM_IO_RDONLY:
246239278Sgonzo		s->strio_flags = SMRD;
247239278Sgonzo		break;
248239278Sgonzo	  case SM_IO_WRONLY:
249239278Sgonzo		s->strio_flags = SMWR;
250239278Sgonzo		break;
251239278Sgonzo	  case SM_IO_APPEND:
252239278Sgonzo		if (s->strio_rpool == NULL)
253239278Sgonzo			sm_free(s);
254239278Sgonzo		errno = EINVAL;
255239278Sgonzo		return -1;
256239278Sgonzo	  default:
257239278Sgonzo		if (s->strio_rpool == NULL)
258239278Sgonzo			sm_free(s);
259239278Sgonzo		errno = EINVAL;
260239278Sgonzo		return -1;
261239278Sgonzo	}
262239278Sgonzo
263239278Sgonzo	if (info != NULL)
264239278Sgonzo	{
265239278Sgonzo		s->strio_base = sm_strdup_x(info);
266239278Sgonzo		if (s->strio_base == NULL)
267239278Sgonzo		{
268239278Sgonzo			int save_errno = errno;
269239278Sgonzo
270239278Sgonzo			if (s->strio_rpool == NULL)
271239278Sgonzo				sm_free(s);
272239278Sgonzo			errno = save_errno;
273239278Sgonzo			return -1;
274239278Sgonzo		}
275239278Sgonzo		s->strio_size = strlen(info);
276239278Sgonzo		s->strio_end = s->strio_base + s->strio_size;
277239278Sgonzo	}
278239278Sgonzo	return 0;
279239278Sgonzo}
280239278Sgonzo
281239278Sgonzo/*
282239278Sgonzo**  SM_STRCLOSE -- close the string file type and free resources
283239278Sgonzo**
284239278Sgonzo**	Parameters:
285239278Sgonzo**		fp -- file pointer
286239278Sgonzo**
287239278Sgonzo**	Results:
288239278Sgonzo**		Success: 0 (zero)
289239278Sgonzo*/
290239278Sgonzo
291239278Sgonzoint
292239278Sgonzosm_strclose(fp)
293239278Sgonzo	SM_FILE_T *fp;
294239278Sgonzo{
295239278Sgonzo	SM_STR_OBJ_T *s = fp->f_cookie;
296239278Sgonzo
297239278Sgonzo#if !SM_RPOOL
298239278Sgonzo	sm_free(s->strio_base);
299239278Sgonzo	s->strio_base = NULL;
300239278Sgonzo#endif /* !SM_RPOOL */
301239278Sgonzo	return 0;
302239278Sgonzo}
303239278Sgonzo
304239278Sgonzo/*
305239278Sgonzo**  SM_STRSETMODE -- set mode info for the file
306239278Sgonzo**
307239278Sgonzo**	 Note: changing the mode can be a safe way to have the "parent"
308239278Sgonzo**	 set up a string that the "child" is not to modify
309239278Sgonzo**
310239278Sgonzo**	Parameters:
311239278Sgonzo**		fp -- the file pointer
312239278Sgonzo**		mode -- location of new mode to set
313239278Sgonzo**
314239278Sgonzo**	Results:
315239278Sgonzo**		Success: 0 (zero)
316239278Sgonzo**		Failure: -1 and sets errno
317239278Sgonzo*/
318239278Sgonzo
319239278Sgonzostatic int
320239278Sgonzosm_strsetmode(fp, mode)
321239278Sgonzo	SM_FILE_T *fp;
322239278Sgonzo	const int *mode;
323239278Sgonzo{
324239278Sgonzo	register SM_STR_OBJ_T *s = fp->f_cookie;
325239278Sgonzo	int flags;
326239278Sgonzo
327239278Sgonzo	switch (*mode)
328239278Sgonzo	{
329239278Sgonzo	  case SM_IO_RDWR:
330239278Sgonzo		flags = SMRW;
331239278Sgonzo		break;
332239278Sgonzo	  case SM_IO_RDONLY:
333239278Sgonzo		flags = SMRD;
334239278Sgonzo		break;
335239278Sgonzo	  case SM_IO_WRONLY:
336239278Sgonzo		flags = SMWR;
337239278Sgonzo		break;
338239278Sgonzo	  case SM_IO_APPEND:
339239278Sgonzo		errno = EINVAL;
340239278Sgonzo		return -1;
341239278Sgonzo	  default:
342239278Sgonzo		errno = EINVAL;
343239278Sgonzo		return -1;
344239278Sgonzo	}
345239278Sgonzo	s->strio_flags &= ~SMMODEMASK;
346239278Sgonzo	s->strio_flags |= flags;
347239278Sgonzo	return 0;
348239278Sgonzo}
349239278Sgonzo
350239278Sgonzo/*
351239278Sgonzo**  SM_STRGETMODE -- get mode info for the file
352239278Sgonzo**
353239278Sgonzo**	Parameters:
354239278Sgonzo**		fp -- the file pointer
355239278Sgonzo**		mode -- location to store current mode
356239278Sgonzo**
357239278Sgonzo**	Results:
358239278Sgonzo**		Success: 0 (zero)
359239278Sgonzo**		Failure: -1 and sets errno
360239278Sgonzo*/
361239278Sgonzo
362239278Sgonzoint
363239278Sgonzosm_strgetmode(fp, mode)
364239278Sgonzo	SM_FILE_T *fp;
365239278Sgonzo	int *mode;
366239278Sgonzo{
367239278Sgonzo	register SM_STR_OBJ_T *s = fp->f_cookie;
368239278Sgonzo
369239278Sgonzo	switch (s->strio_flags & SMMODEMASK)
370239278Sgonzo	{
371239278Sgonzo	  case SMRW:
372239278Sgonzo		*mode = SM_IO_RDWR;
373239278Sgonzo		break;
374239278Sgonzo	  case SMRD:
375239278Sgonzo		*mode = SM_IO_RDONLY;
376239278Sgonzo		break;
377239278Sgonzo	  case SMWR:
378239278Sgonzo		*mode = SM_IO_WRONLY;
379239278Sgonzo		break;
380239278Sgonzo	  default:
381239278Sgonzo		errno = EINVAL;
382239278Sgonzo		return -1;
383239278Sgonzo	}
384239278Sgonzo	return 0;
385239278Sgonzo}
386239278Sgonzo
387239278Sgonzo/*
388239278Sgonzo**  SM_STRSETINFO -- set info for the file
389239278Sgonzo**
390239278Sgonzo**	Currently only SM_IO_WHAT_MODE is supported for 'what'.
391239278Sgonzo**
392239278Sgonzo**	Parameters:
393239278Sgonzo**		fp -- the file pointer
394239278Sgonzo**		what -- type of information to set
395239278Sgonzo**		valp -- location to data for doing set
396239278Sgonzo**
397239278Sgonzo**	Results:
398239278Sgonzo**		Failure: -1 and sets errno
399239278Sgonzo**		Success: sm_strsetmode() return [0 (zero)]
400239278Sgonzo*/
401239278Sgonzo
402239278Sgonzoint
403239278Sgonzosm_strsetinfo(fp, what, valp)
404239278Sgonzo	SM_FILE_T *fp;
405239278Sgonzo	int what;
406239278Sgonzo	void *valp;
407239278Sgonzo{
408239278Sgonzo	switch(what)
409239278Sgonzo	{
410239278Sgonzo	  case SM_IO_WHAT_MODE:
411239278Sgonzo		return sm_strsetmode(fp, (int *) valp);
412239278Sgonzo	  default:
413239278Sgonzo		errno = EINVAL;
414239278Sgonzo		return -1;
415239278Sgonzo	}
416239278Sgonzo}
417239278Sgonzo
418239278Sgonzo/*
419239278Sgonzo**  SM_STRGETINFO -- get info for the file
420239278Sgonzo**
421239278Sgonzo**	Currently only SM_IO_WHAT_MODE is supported for 'what'.
422239278Sgonzo**
423239278Sgonzo**	Parameters:
424239278Sgonzo**		fp -- the file pointer
425239278Sgonzo**		what -- type of information requested
426239278Sgonzo**		valp -- location to return information in
427239278Sgonzo**
428239278Sgonzo**	Results:
429239278Sgonzo**		Failure: -1 and sets errno
430239278Sgonzo**		Success: sm_strgetmode() return [0 (zero)]
431239278Sgonzo*/
432239278Sgonzo
433239278Sgonzoint
434239278Sgonzosm_strgetinfo(fp, what, valp)
435239278Sgonzo	SM_FILE_T *fp;
436239278Sgonzo	int what;
437239278Sgonzo	void *valp;
438239278Sgonzo{
439239278Sgonzo	switch(what)
440239278Sgonzo	{
441239278Sgonzo	  case SM_IO_WHAT_MODE:
442239278Sgonzo		return sm_strgetmode(fp, (int *) valp);
443239278Sgonzo	  default:
444239278Sgonzo		errno = EINVAL;
445239278Sgonzo		return -1;
446239278Sgonzo	}
447239278Sgonzo}
448239278Sgonzo
449239278Sgonzo/*
450239278Sgonzo**  SM_STRIO_INIT -- initializes a write-only string type
451239278Sgonzo**
452239278Sgonzo**  Original comments below. This function does not appear to be used anywhere.
453239278Sgonzo**  The same functionality can be done by changing the mode of the file.
454239278Sgonzo**  ------------
455239278Sgonzo** sm_strio_init initializes an SM_FILE_T structure as a write-only file
456239278Sgonzo** that writes into the specified buffer:
457239278Sgonzo** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer.
458239278Sgonzo**   Attempts to write more than size-1 characters into the buffer will fail
459239278Sgonzo**   silently (no error is reported).
460239278Sgonzo** - Use sm_io_fflush to nul terminate the string in the buffer
461239278Sgonzo**   (the write pointer is not advanced).
462239278Sgonzo** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc.
463239278Sgonzo**
464239278Sgonzo**	Parameters:
465239278Sgonzo**		fp -- file pointer
466239278Sgonzo**		buf -- memory location for stored data
467239278Sgonzo**		size -- size of 'buf'
468239278Sgonzo**
469239278Sgonzo**	Results:
470239278Sgonzo**		none.
471239278Sgonzo*/
472239278Sgonzo
473239278Sgonzovoid
474239278Sgonzosm_strio_init(fp, buf, size)
475239278Sgonzo	SM_FILE_T *fp;
476239278Sgonzo	char *buf;
477239278Sgonzo	size_t size;
478239278Sgonzo{
479239278Sgonzo	fp->sm_magic = SmFileMagic;
480239278Sgonzo	fp->f_flags = SMWR | SMSTR;
481239278Sgonzo	fp->f_file = -1;
482239278Sgonzo	fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf;
483239278Sgonzo	fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0);
484239278Sgonzo	fp->f_lbfsize = 0;
485239278Sgonzo	fp->f_r = 0;
486239278Sgonzo	fp->f_read = NULL;
487239278Sgonzo	fp->f_seek = NULL;
488239278Sgonzo	fp->f_getinfo = NULL;
489239278Sgonzo	fp->f_setinfo = NULL;
490239278Sgonzo}
491239278Sgonzo