strio.c revision 157002
1260684Skaiw/*
2260684Skaiw * Copyright (c) 2000-2002, 2004, 2005 Sendmail, Inc. and its suppliers.
3260684Skaiw *      All rights reserved.
4260684Skaiw * Copyright (c) 1990, 1993
5260684Skaiw *	The Regents of the University of California.  All rights reserved.
6260684Skaiw *
7260684Skaiw * This code is derived from software contributed to Berkeley by
8260684Skaiw * Chris Torek.
9260684Skaiw *
10260684Skaiw * By using this file, you agree to the terms and conditions set
11260684Skaiw * forth in the LICENSE file which can be found at the top level of
12260684Skaiw * the sendmail distribution.
13260684Skaiw */
14260684Skaiw
15260684Skaiw#include <sm/gen.h>
16260684SkaiwSM_IDSTR(id, "@(#)$Id: strio.c,v 1.44 2005/06/09 21:40:19 ca Exp $")
17260684Skaiw#include <stdlib.h>
18260684Skaiw#include <unistd.h>
19260684Skaiw#include <fcntl.h>
20260684Skaiw#include <string.h>
21260684Skaiw#include <errno.h>
22260684Skaiw#include <sm/rpool.h>
23260684Skaiw#include <sm/io.h>
24260684Skaiw#include <sm/heap.h>
25260684Skaiw#include <sm/conf.h>
26260684Skaiw#include "local.h"
27260684Skaiw
28260684Skaiwstatic int	sm_strsetmode __P((SM_FILE_T*, const int *));
29260684Skaiwstatic int	sm_strgetmode __P((SM_FILE_T*, int *));
30295577Semaste
31260684Skaiw/*
32260684Skaiw**  Cookie structure for the "strio" file type
33260684Skaiw*/
34260684Skaiw
35260684Skaiwstruct sm_str_obj
36260684Skaiw{
37260684Skaiw	char		*strio_base;
38260684Skaiw	char		*strio_end;
39260684Skaiw	size_t		strio_size;
40260684Skaiw	size_t		strio_offset;
41260684Skaiw	int		strio_flags;
42260684Skaiw	const void	*strio_rpool;
43260684Skaiw};
44260684Skaiw
45295577Semastetypedef struct sm_str_obj SM_STR_OBJ_T;
46260684Skaiw
47260684Skaiw/*
48295577Semaste**  SM_STRGROW -- increase storage space for string
49260684Skaiw**
50260684Skaiw**	Parameters:
51295577Semaste**		s -- current cookie
52260684Skaiw**		size -- new storage size request
53260684Skaiw**
54260684Skaiw**	Returns:
55260684Skaiw**		true iff successful.
56260684Skaiw*/
57260684Skaiw
58260684Skaiwstatic bool sm_strgrow __P((SM_STR_OBJ_T *, size_t));
59260684Skaiw
60260684Skaiwstatic bool
61260684Skaiwsm_strgrow(s, size)
62260684Skaiw	SM_STR_OBJ_T *s;
63260684Skaiw	size_t size;
64260684Skaiw{
65260684Skaiw	register void *p;
66260684Skaiw
67260684Skaiw	if (s->strio_size >= size)
68260684Skaiw		return true;
69260684Skaiw	p = sm_realloc(s->strio_base, size);
70260684Skaiw	if (p == NULL)
71260684Skaiw		return false;
72260684Skaiw	s->strio_base = p;
73260684Skaiw	s->strio_end = s->strio_base + size;
74260684Skaiw	s->strio_size = size;
75260684Skaiw	return true;
76260684Skaiw}
77295577Semaste
78260684Skaiw/*
79260684Skaiw**  SM_STRREAD -- read a portion of the string
80295577Semaste**
81260684Skaiw**	Parameters:
82260684Skaiw**		fp -- the file pointer
83295577Semaste**		buf -- location to place read data
84260684Skaiw**		n -- number of bytes to read
85260684Skaiw**
86260684Skaiw**	Returns:
87260684Skaiw**		Failure: -1 and sets errno
88260684Skaiw**		Success: >=0, number of bytes read
89260684Skaiw*/
90260684Skaiw
91260684Skaiwssize_t
92260684Skaiwsm_strread(fp, buf, n)
93260684Skaiw	SM_FILE_T *fp;
94260684Skaiw	char *buf;
95260684Skaiw	size_t n;
96260684Skaiw{
97260684Skaiw	register SM_STR_OBJ_T *s = fp->f_cookie;
98260684Skaiw	int len;
99260684Skaiw
100260684Skaiw	if (!(s->strio_flags & SMRD) && !(s->strio_flags & SMRW))
101260684Skaiw	{
102260684Skaiw		errno = EBADF;
103260684Skaiw		return -1;
104260684Skaiw	}
105260684Skaiw	len = SM_MIN(s->strio_size - s->strio_offset, n);
106260684Skaiw	(void) memmove(buf, s->strio_base + s->strio_offset, len);
107260684Skaiw	s->strio_offset += len;
108260684Skaiw	return len;
109260684Skaiw}
110260684Skaiw
111260684Skaiw/*
112260684Skaiw**  SM_STRWRITE -- write a portion of the string
113260684Skaiw**
114260684Skaiw**	Parameters:
115260684Skaiw**		fp -- the file pointer
116260684Skaiw**		buf -- location of data for writing
117260684Skaiw**		n -- number of bytes to write
118260684Skaiw**
119260684Skaiw**	Returns:
120260684Skaiw**		Failure: -1 and sets errno
121260684Skaiw**		Success: >=0, number of bytes written
122260684Skaiw*/
123260684Skaiw
124260684Skaiwssize_t
125260684Skaiwsm_strwrite(fp, buf, n)
126260684Skaiw	SM_FILE_T *fp;
127260684Skaiw	char const *buf;
128260684Skaiw	size_t n;
129260684Skaiw{
130260684Skaiw	register SM_STR_OBJ_T *s = fp->f_cookie;
131260684Skaiw
132260684Skaiw	if (!(s->strio_flags & SMWR) && !(s->strio_flags & SMRW))
133260684Skaiw	{
134260684Skaiw		errno = EBADF;
135260684Skaiw		return -1;
136260684Skaiw	}
137260684Skaiw	if (n + s->strio_offset > s->strio_size)
138260684Skaiw	{
139260684Skaiw		if (!sm_strgrow(s, n + s->strio_offset))
140260684Skaiw			return 0;
141260684Skaiw	}
142260684Skaiw	(void) memmove(s->strio_base + s->strio_offset, buf, n);
143260684Skaiw	s->strio_offset += n;
144260684Skaiw	return n;
145260684Skaiw}
146260684Skaiw
147260684Skaiw/*
148260684Skaiw**  SM_STRSEEK -- position the offset pointer for the string
149260684Skaiw**
150260684Skaiw**	Only SM_IO_SEEK_SET, SM_IO_SEEK_CUR and SM_IO_SEEK_END are valid
151260684Skaiw**	values for whence.
152260684Skaiw**
153260684Skaiw**	Parameters:
154260684Skaiw**		fp -- the file pointer
155260684Skaiw**		offset -- number of bytes offset from "base"
156260684Skaiw**		whence -- determines "base" for 'offset'
157260684Skaiw**
158260684Skaiw**	Returns:
159260684Skaiw**		Failure: -1 and sets errno
160260684Skaiw**		Success: >=0, number of bytes read
161260684Skaiw*/
162260684Skaiw
163260684Skaiwoff_t
164260684Skaiwsm_strseek(fp, offset, whence)
165260684Skaiw	SM_FILE_T *fp;
166260684Skaiw	off_t offset;
167260684Skaiw	int whence;
168260684Skaiw{
169260684Skaiw	register off_t ret;
170260684Skaiw	register SM_STR_OBJ_T *s = fp->f_cookie;
171260684Skaiw
172260684Skaiwreseek:
173260684Skaiw	switch (whence)
174260684Skaiw	{
175260684Skaiw	  case SM_IO_SEEK_SET:
176260684Skaiw		ret = offset;
177260684Skaiw		break;
178260684Skaiw	  case SM_IO_SEEK_CUR:
179260684Skaiw		ret = s->strio_offset + offset;
180295577Semaste		break;
181260684Skaiw	  case SM_IO_SEEK_END:
182260684Skaiw		ret = s->strio_size;
183260684Skaiw		break;
184295577Semaste	  default:
185260684Skaiw		errno = EINVAL;
186260684Skaiw		return -1;
187295577Semaste	}
188260684Skaiw	if (ret < 0 || ret > (off_t)(size_t)(-1))	/* XXX ugly */
189260684Skaiw		return -1;
190260684Skaiw	if ((size_t) ret > s->strio_size)
191260684Skaiw	{
192260684Skaiw		if (sm_strgrow(s, (size_t)ret))
193260684Skaiw			goto reseek;
194260684Skaiw
195260684Skaiw		/* errno set by sm_strgrow */
196260684Skaiw		return -1;
197260684Skaiw	}
198260684Skaiw	s->strio_offset = (size_t) ret;
199260684Skaiw	return ret;
200260684Skaiw}
201260684Skaiw
202260684Skaiw/*
203260684Skaiw**  SM_STROPEN -- open a string file type
204260684Skaiw**
205260684Skaiw**	Parameters:
206260684Skaiw**		fp -- file pointer open to be associated with
207260684Skaiw**		info -- initial contents (NULL for none)
208260684Skaiw**		flags -- flags for methods of access (was mode)
209260684Skaiw**		rpool -- resource pool to use memory from (if applicable)
210260684Skaiw**
211260684Skaiw**	Results:
212260684Skaiw**		Success: 0 (zero)
213260684Skaiw**		Failure: -1 and sets errno
214260684Skaiw*/
215260684Skaiw
216260684Skaiwint
217260684Skaiwsm_stropen(fp, info, flags, rpool)
218260684Skaiw	SM_FILE_T *fp;
219260684Skaiw	const void *info;
220260684Skaiw	int flags;
221260684Skaiw	const void *rpool;
222260684Skaiw{
223260684Skaiw	register SM_STR_OBJ_T *s;
224260684Skaiw
225260684Skaiw#if SM_RPOOL
226260684Skaiw	s = sm_rpool_malloc_x(rpool, sizeof(SM_STR_OBJ_T));
227260684Skaiw#else /* SM_RPOOL */
228260684Skaiw	s = sm_malloc(sizeof(SM_STR_OBJ_T));
229260684Skaiw	if (s == NULL)
230260684Skaiw		return -1;
231260684Skaiw#endif /* SM_RPOOL */
232260684Skaiw
233260684Skaiw	fp->f_cookie = s;
234295577Semaste	s->strio_rpool = rpool;
235260684Skaiw	s->strio_offset = 0;
236260684Skaiw	s->strio_size = 0;
237260684Skaiw	s->strio_base = NULL;
238260684Skaiw	s->strio_end = 0;
239295577Semaste
240260684Skaiw	switch (flags)
241260684Skaiw	{
242260684Skaiw	  case SM_IO_RDWR:
243295577Semaste		s->strio_flags = SMRW;
244260684Skaiw		break;
245260684Skaiw	  case SM_IO_RDONLY:
246260684Skaiw		s->strio_flags = SMRD;
247260684Skaiw		break;
248260684Skaiw	  case SM_IO_WRONLY:
249260684Skaiw		s->strio_flags = SMWR;
250260684Skaiw		break;
251260684Skaiw	  case SM_IO_APPEND:
252260684Skaiw		if (s->strio_rpool == NULL)
253260684Skaiw			sm_free(s);
254260684Skaiw		errno = EINVAL;
255260684Skaiw		return -1;
256260684Skaiw	  default:
257260684Skaiw		if (s->strio_rpool == NULL)
258260684Skaiw			sm_free(s);
259260684Skaiw		errno = EINVAL;
260260684Skaiw		return -1;
261260684Skaiw	}
262260684Skaiw
263260684Skaiw	if (info != NULL)
264260684Skaiw	{
265260684Skaiw		s->strio_base = sm_strdup_x(info);
266260684Skaiw		if (s->strio_base == NULL)
267260684Skaiw		{
268260684Skaiw			int save_errno = errno;
269260684Skaiw
270260684Skaiw			if (s->strio_rpool == NULL)
271260684Skaiw				sm_free(s);
272260684Skaiw			errno = save_errno;
273260684Skaiw			return -1;
274260684Skaiw		}
275260684Skaiw		s->strio_size = strlen(info);
276260684Skaiw		s->strio_end = s->strio_base + s->strio_size;
277260684Skaiw	}
278260684Skaiw	return 0;
279260684Skaiw}
280260684Skaiw
281260684Skaiw/*
282260684Skaiw**  SM_STRCLOSE -- close the string file type and free resources
283260684Skaiw**
284260684Skaiw**	Parameters:
285260684Skaiw**		fp -- file pointer
286260684Skaiw**
287260684Skaiw**	Results:
288260684Skaiw**		Success: 0 (zero)
289260684Skaiw*/
290260684Skaiw
291260684Skaiwint
292260684Skaiwsm_strclose(fp)
293260684Skaiw	SM_FILE_T *fp;
294260684Skaiw{
295260684Skaiw	SM_STR_OBJ_T *s = fp->f_cookie;
296260684Skaiw
297260684Skaiw#if !SM_RPOOL
298260684Skaiw	sm_free(s->strio_base);
299260684Skaiw	s->strio_base = NULL;
300260684Skaiw#endif /* !SM_RPOOL */
301260684Skaiw	return 0;
302260684Skaiw}
303260684Skaiw
304260684Skaiw/*
305260684Skaiw**  SM_STRSETMODE -- set mode info for the file
306260684Skaiw**
307260684Skaiw**	 Note: changing the mode can be a safe way to have the "parent"
308260684Skaiw**	 set up a string that the "child" is not to modify
309260684Skaiw**
310260684Skaiw**	Parameters:
311260684Skaiw**		fp -- the file pointer
312260684Skaiw**		mode -- location of new mode to set
313260684Skaiw**
314260684Skaiw**	Results:
315260684Skaiw**		Success: 0 (zero)
316260684Skaiw**		Failure: -1 and sets errno
317260684Skaiw*/
318260684Skaiw
319260684Skaiwstatic int
320260684Skaiwsm_strsetmode(fp, mode)
321260684Skaiw	SM_FILE_T *fp;
322260684Skaiw	const int *mode;
323260684Skaiw{
324260684Skaiw	register SM_STR_OBJ_T *s = fp->f_cookie;
325260684Skaiw	int flags;
326260684Skaiw
327260684Skaiw	switch (*mode)
328260684Skaiw	{
329260684Skaiw	  case SM_IO_RDWR:
330260684Skaiw		flags = SMRW;
331260684Skaiw		break;
332260684Skaiw	  case SM_IO_RDONLY:
333260684Skaiw		flags = SMRD;
334260684Skaiw		break;
335260684Skaiw	  case SM_IO_WRONLY:
336260684Skaiw		flags = SMWR;
337260684Skaiw		break;
338260684Skaiw	  case SM_IO_APPEND:
339260684Skaiw		errno = EINVAL;
340260684Skaiw		return -1;
341260684Skaiw	  default:
342260684Skaiw		errno = EINVAL;
343260684Skaiw		return -1;
344260684Skaiw	}
345260684Skaiw	s->strio_flags &= ~SMMODEMASK;
346260684Skaiw	s->strio_flags |= flags;
347260684Skaiw	return 0;
348260684Skaiw}
349260684Skaiw
350260684Skaiw/*
351260684Skaiw**  SM_STRGETMODE -- get mode info for the file
352260684Skaiw**
353260684Skaiw**	Parameters:
354260684Skaiw**		fp -- the file pointer
355260684Skaiw**		mode -- location to store current mode
356260684Skaiw**
357260684Skaiw**	Results:
358260684Skaiw**		Success: 0 (zero)
359260684Skaiw**		Failure: -1 and sets errno
360260684Skaiw*/
361260684Skaiw
362260684Skaiwstatic int
363260684Skaiwsm_strgetmode(fp, mode)
364260684Skaiw	SM_FILE_T *fp;
365260684Skaiw	int *mode;
366260684Skaiw{
367260684Skaiw	register SM_STR_OBJ_T *s = fp->f_cookie;
368260684Skaiw
369260684Skaiw	switch (s->strio_flags & SMMODEMASK)
370260684Skaiw	{
371260684Skaiw	  case SMRW:
372260684Skaiw		*mode = SM_IO_RDWR;
373260684Skaiw		break;
374260684Skaiw	  case SMRD:
375260684Skaiw		*mode = SM_IO_RDONLY;
376260684Skaiw		break;
377260684Skaiw	  case SMWR:
378260684Skaiw		*mode = SM_IO_WRONLY;
379260684Skaiw		break;
380260684Skaiw	  default:
381260684Skaiw		errno = EINVAL;
382260684Skaiw		return -1;
383260684Skaiw	}
384260684Skaiw	return 0;
385260684Skaiw}
386260684Skaiw
387260684Skaiw/*
388260684Skaiw**  SM_STRSETINFO -- set info for the file
389260684Skaiw**
390260684Skaiw**	Currently only SM_IO_WHAT_MODE is supported for 'what'.
391260684Skaiw**
392260684Skaiw**	Parameters:
393260684Skaiw**		fp -- the file pointer
394260684Skaiw**		what -- type of information to set
395260684Skaiw**		valp -- location to data for doing set
396260684Skaiw**
397260684Skaiw**	Results:
398260684Skaiw**		Failure: -1 and sets errno
399260684Skaiw**		Success: sm_strsetmode() return [0 (zero)]
400260684Skaiw*/
401260684Skaiw
402260684Skaiwint
403260684Skaiwsm_strsetinfo(fp, what, valp)
404260684Skaiw	SM_FILE_T *fp;
405260684Skaiw	int what;
406260684Skaiw	void *valp;
407260684Skaiw{
408260684Skaiw	switch(what)
409260684Skaiw	{
410260684Skaiw	  case SM_IO_WHAT_MODE:
411260684Skaiw		return sm_strsetmode(fp, (int *) valp);
412260684Skaiw	  default:
413260684Skaiw		errno = EINVAL;
414260684Skaiw		return -1;
415260684Skaiw	}
416260684Skaiw}
417260684Skaiw
418260684Skaiw/*
419260684Skaiw**  SM_STRGETINFO -- get info for the file
420260684Skaiw**
421260684Skaiw**	Currently only SM_IO_WHAT_MODE is supported for 'what'.
422260684Skaiw**
423260684Skaiw**	Parameters:
424260684Skaiw**		fp -- the file pointer
425260684Skaiw**		what -- type of information requested
426260684Skaiw**		valp -- location to return information in
427260684Skaiw**
428260684Skaiw**	Results:
429260684Skaiw**		Failure: -1 and sets errno
430260684Skaiw**		Success: sm_strgetmode() return [0 (zero)]
431260684Skaiw*/
432260684Skaiw
433260684Skaiwint
434260684Skaiwsm_strgetinfo(fp, what, valp)
435260684Skaiw	SM_FILE_T *fp;
436260684Skaiw	int what;
437260684Skaiw	void *valp;
438260684Skaiw{
439260684Skaiw	switch(what)
440260684Skaiw	{
441260684Skaiw	  case SM_IO_WHAT_MODE:
442260684Skaiw		return sm_strgetmode(fp, (int *) valp);
443260684Skaiw	  default:
444260684Skaiw		errno = EINVAL;
445260684Skaiw		return -1;
446260684Skaiw	}
447260684Skaiw}
448260684Skaiw
449260684Skaiw/*
450260684Skaiw**  SM_STRIO_INIT -- initializes a write-only string type
451260684Skaiw**
452260684Skaiw**  Original comments below. This function does not appear to be used anywhere.
453260684Skaiw**  The same functionality can be done by changing the mode of the file.
454260684Skaiw**  ------------
455260684Skaiw** sm_strio_init initializes an SM_FILE_T structure as a write-only file
456260684Skaiw** that writes into the specified buffer:
457260684Skaiw** - Use sm_io_putc, sm_io_fprintf, etc, to write into the buffer.
458260684Skaiw**   Attempts to write more than size-1 characters into the buffer will fail
459260684Skaiw**   silently (no error is reported).
460260684Skaiw** - Use sm_io_fflush to nul terminate the string in the buffer
461260684Skaiw**   (the write pointer is not advanced).
462260684Skaiw** No memory is allocated either by sm_strio_init or by sm_io_{putc,write} etc.
463260684Skaiw**
464260684Skaiw**	Parameters:
465260684Skaiw**		fp -- file pointer
466260684Skaiw**		buf -- memory location for stored data
467260684Skaiw**		size -- size of 'buf'
468260684Skaiw**
469260684Skaiw**	Results:
470260684Skaiw**		none.
471260684Skaiw*/
472260684Skaiw
473260684Skaiwvoid
474260684Skaiwsm_strio_init(fp, buf, size)
475260684Skaiw	SM_FILE_T *fp;
476260684Skaiw	char *buf;
477260684Skaiw	size_t size;
478260684Skaiw{
479260684Skaiw	fp->sm_magic = SmFileMagic;
480260684Skaiw	fp->f_flags = SMWR | SMSTR;
481260684Skaiw	fp->f_file = -1;
482260684Skaiw	fp->f_bf.smb_base = fp->f_p = (unsigned char *) buf;
483260684Skaiw	fp->f_bf.smb_size = fp->f_w = (size ? size - 1 : 0);
484260684Skaiw	fp->f_lbfsize = 0;
485260684Skaiw	fp->f_r = 0;
486260684Skaiw	fp->f_read = NULL;
487260684Skaiw	fp->f_seek = NULL;
488260684Skaiw	fp->f_getinfo = NULL;
489260684Skaiw	fp->f_setinfo = NULL;
490260684Skaiw}
491260684Skaiw