xref: /titanic_53/usr/src/cmd/sendmail/libsm/stdio.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * Copyright (c) 2000-2004 Sendmail, Inc. and its suppliers.
3*7c478bd9Sstevel@tonic-gate  *      All rights reserved.
4*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
5*7c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
6*7c478bd9Sstevel@tonic-gate  *
7*7c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
8*7c478bd9Sstevel@tonic-gate  * Chris Torek.
9*7c478bd9Sstevel@tonic-gate  *
10*7c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
11*7c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
12*7c478bd9Sstevel@tonic-gate  * the sendmail distribution.
13*7c478bd9Sstevel@tonic-gate  */
14*7c478bd9Sstevel@tonic-gate 
15*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
16*7c478bd9Sstevel@tonic-gate 
17*7c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*7c478bd9Sstevel@tonic-gate SM_RCSID("@(#)$Id: stdio.c,v 1.69 2004/08/03 20:46:34 ca Exp $")
19*7c478bd9Sstevel@tonic-gate #include <unistd.h>
20*7c478bd9Sstevel@tonic-gate #include <errno.h>
21*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
22*7c478bd9Sstevel@tonic-gate #include <string.h>	/* FreeBSD: FD_ZERO needs <string.h> */
23*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
24*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
25*7c478bd9Sstevel@tonic-gate #include <sm/heap.h>
26*7c478bd9Sstevel@tonic-gate #include <sm/assert.h>
27*7c478bd9Sstevel@tonic-gate #include <sm/varargs.h>
28*7c478bd9Sstevel@tonic-gate #include <sm/io.h>
29*7c478bd9Sstevel@tonic-gate #include <sm/setjmp.h>
30*7c478bd9Sstevel@tonic-gate #include <sm/conf.h>
31*7c478bd9Sstevel@tonic-gate #include <sm/fdset.h>
32*7c478bd9Sstevel@tonic-gate #include "local.h"
33*7c478bd9Sstevel@tonic-gate 
34*7c478bd9Sstevel@tonic-gate static int	sm_stdsetmode __P((SM_FILE_T *, const int *));
35*7c478bd9Sstevel@tonic-gate static int	sm_stdgetmode __P((SM_FILE_T *, int *));
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate /*
38*7c478bd9Sstevel@tonic-gate **  Overall:
39*7c478bd9Sstevel@tonic-gate **  Small standard I/O/seek/close functions.
40*7c478bd9Sstevel@tonic-gate **  These maintain the `known seek offset' for seek optimization.
41*7c478bd9Sstevel@tonic-gate */
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /*
44*7c478bd9Sstevel@tonic-gate **  SM_STDOPEN -- open a file with stdio behavior
45*7c478bd9Sstevel@tonic-gate **
46*7c478bd9Sstevel@tonic-gate **  Not associated with the system's stdio in libc.
47*7c478bd9Sstevel@tonic-gate **
48*7c478bd9Sstevel@tonic-gate **	Parameters:
49*7c478bd9Sstevel@tonic-gate **		fp -- file pointer to be associated with the open
50*7c478bd9Sstevel@tonic-gate **		info -- pathname of the file to be opened
51*7c478bd9Sstevel@tonic-gate **		flags -- indicates type of access methods
52*7c478bd9Sstevel@tonic-gate **		rpool -- ignored
53*7c478bd9Sstevel@tonic-gate **
54*7c478bd9Sstevel@tonic-gate **	Returns:
55*7c478bd9Sstevel@tonic-gate **		Failure: -1 and set errno
56*7c478bd9Sstevel@tonic-gate **		Success: 0 or greater (fd of file from open(2)).
57*7c478bd9Sstevel@tonic-gate **
58*7c478bd9Sstevel@tonic-gate */
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
61*7c478bd9Sstevel@tonic-gate int
62*7c478bd9Sstevel@tonic-gate sm_stdopen(fp, info, flags, rpool)
63*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
64*7c478bd9Sstevel@tonic-gate 	const void *info;
65*7c478bd9Sstevel@tonic-gate 	int flags;
66*7c478bd9Sstevel@tonic-gate 	const void *rpool;
67*7c478bd9Sstevel@tonic-gate {
68*7c478bd9Sstevel@tonic-gate 	char *path = (char *) info;
69*7c478bd9Sstevel@tonic-gate 	int oflags;
70*7c478bd9Sstevel@tonic-gate 
71*7c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(flags))
72*7c478bd9Sstevel@tonic-gate 	{
73*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
74*7c478bd9Sstevel@tonic-gate 		oflags = O_RDWR;
75*7c478bd9Sstevel@tonic-gate 		break;
76*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWRTR:
77*7c478bd9Sstevel@tonic-gate 		oflags = O_RDWR | O_CREAT | O_TRUNC;
78*7c478bd9Sstevel@tonic-gate 		break;
79*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
80*7c478bd9Sstevel@tonic-gate 		oflags = O_RDONLY;
81*7c478bd9Sstevel@tonic-gate 		break;
82*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
83*7c478bd9Sstevel@tonic-gate 		oflags = O_WRONLY | O_CREAT | O_TRUNC;
84*7c478bd9Sstevel@tonic-gate 		break;
85*7c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
86*7c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_WRONLY | O_CREAT;
87*7c478bd9Sstevel@tonic-gate 		break;
88*7c478bd9Sstevel@tonic-gate 	  case SM_IO_APPENDRW:
89*7c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_RDWR | O_CREAT;
90*7c478bd9Sstevel@tonic-gate 		break;
91*7c478bd9Sstevel@tonic-gate 	  default:
92*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
93*7c478bd9Sstevel@tonic-gate 		return -1;
94*7c478bd9Sstevel@tonic-gate 	}
95*7c478bd9Sstevel@tonic-gate #ifdef O_BINARY
96*7c478bd9Sstevel@tonic-gate 	if (SM_IS_BINARY(flags))
97*7c478bd9Sstevel@tonic-gate 		oflags |= O_BINARY;
98*7c478bd9Sstevel@tonic-gate #endif /* O_BINARY */
99*7c478bd9Sstevel@tonic-gate 	fp->f_file = open(path, oflags,
100*7c478bd9Sstevel@tonic-gate 			  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
101*7c478bd9Sstevel@tonic-gate 	if (fp->f_file < 0)
102*7c478bd9Sstevel@tonic-gate 		return -1; /* errno set by open() */
103*7c478bd9Sstevel@tonic-gate 
104*7c478bd9Sstevel@tonic-gate 	if (oflags & O_APPEND)
105*7c478bd9Sstevel@tonic-gate 		(void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate 	return fp->f_file;
108*7c478bd9Sstevel@tonic-gate }
109*7c478bd9Sstevel@tonic-gate 
110*7c478bd9Sstevel@tonic-gate /*
111*7c478bd9Sstevel@tonic-gate **  SM_STDREAD -- read from the file
112*7c478bd9Sstevel@tonic-gate **
113*7c478bd9Sstevel@tonic-gate **	Parameters:
114*7c478bd9Sstevel@tonic-gate **		fp -- file pointer to read from
115*7c478bd9Sstevel@tonic-gate **		buf -- location to place read data
116*7c478bd9Sstevel@tonic-gate **		n -- number of bytes to read
117*7c478bd9Sstevel@tonic-gate **
118*7c478bd9Sstevel@tonic-gate **	Returns:
119*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
120*7c478bd9Sstevel@tonic-gate **		Success: number of bytes read
121*7c478bd9Sstevel@tonic-gate **
122*7c478bd9Sstevel@tonic-gate **	Side Effects:
123*7c478bd9Sstevel@tonic-gate **		Updates internal offset into file.
124*7c478bd9Sstevel@tonic-gate */
125*7c478bd9Sstevel@tonic-gate 
126*7c478bd9Sstevel@tonic-gate ssize_t
127*7c478bd9Sstevel@tonic-gate sm_stdread(fp, buf, n)
128*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
129*7c478bd9Sstevel@tonic-gate 	char *buf;
130*7c478bd9Sstevel@tonic-gate 	size_t n;
131*7c478bd9Sstevel@tonic-gate {
132*7c478bd9Sstevel@tonic-gate 	register int ret;
133*7c478bd9Sstevel@tonic-gate 
134*7c478bd9Sstevel@tonic-gate 	ret = read(fp->f_file, buf, n);
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate 	/* if the read succeeded, update the current offset */
137*7c478bd9Sstevel@tonic-gate 	if (ret > 0)
138*7c478bd9Sstevel@tonic-gate 		fp->f_lseekoff += ret;
139*7c478bd9Sstevel@tonic-gate 	return ret;
140*7c478bd9Sstevel@tonic-gate }
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate /*
143*7c478bd9Sstevel@tonic-gate **  SM_STDWRITE -- write to the file
144*7c478bd9Sstevel@tonic-gate **
145*7c478bd9Sstevel@tonic-gate **	Parameters:
146*7c478bd9Sstevel@tonic-gate **		fp -- file pointer ro write to
147*7c478bd9Sstevel@tonic-gate **		buf -- location of data to be written
148*7c478bd9Sstevel@tonic-gate **		n - number of bytes to write
149*7c478bd9Sstevel@tonic-gate **
150*7c478bd9Sstevel@tonic-gate **	Returns:
151*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
152*7c478bd9Sstevel@tonic-gate **		Success: number of bytes written
153*7c478bd9Sstevel@tonic-gate */
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate ssize_t
156*7c478bd9Sstevel@tonic-gate sm_stdwrite(fp, buf, n)
157*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
158*7c478bd9Sstevel@tonic-gate 	char const *buf;
159*7c478bd9Sstevel@tonic-gate 	size_t n;
160*7c478bd9Sstevel@tonic-gate {
161*7c478bd9Sstevel@tonic-gate 	return write(fp->f_file, buf, n);
162*7c478bd9Sstevel@tonic-gate }
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate /*
165*7c478bd9Sstevel@tonic-gate **  SM_STDSEEK -- set the file offset position
166*7c478bd9Sstevel@tonic-gate **
167*7c478bd9Sstevel@tonic-gate **	Parmeters:
168*7c478bd9Sstevel@tonic-gate **		fp -- file pointer to position
169*7c478bd9Sstevel@tonic-gate **		offset -- how far to position from "base" (set by 'whence')
170*7c478bd9Sstevel@tonic-gate **		whence -- indicates where the "base" of the 'offset' to start
171*7c478bd9Sstevel@tonic-gate **
172*7c478bd9Sstevel@tonic-gate **	Results:
173*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
174*7c478bd9Sstevel@tonic-gate **		Success: the current offset
175*7c478bd9Sstevel@tonic-gate **
176*7c478bd9Sstevel@tonic-gate **	Side Effects:
177*7c478bd9Sstevel@tonic-gate **		Updates the internal value of the offset.
178*7c478bd9Sstevel@tonic-gate */
179*7c478bd9Sstevel@tonic-gate 
180*7c478bd9Sstevel@tonic-gate off_t
181*7c478bd9Sstevel@tonic-gate sm_stdseek(fp, offset, whence)
182*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
183*7c478bd9Sstevel@tonic-gate 	off_t offset;
184*7c478bd9Sstevel@tonic-gate 	int whence;
185*7c478bd9Sstevel@tonic-gate {
186*7c478bd9Sstevel@tonic-gate 	register off_t ret;
187*7c478bd9Sstevel@tonic-gate 
188*7c478bd9Sstevel@tonic-gate 	ret = lseek(fp->f_file, (off_t) offset, whence);
189*7c478bd9Sstevel@tonic-gate 	if (ret != (off_t) -1)
190*7c478bd9Sstevel@tonic-gate 		fp->f_lseekoff = ret;
191*7c478bd9Sstevel@tonic-gate 	return ret;
192*7c478bd9Sstevel@tonic-gate }
193*7c478bd9Sstevel@tonic-gate 
194*7c478bd9Sstevel@tonic-gate /*
195*7c478bd9Sstevel@tonic-gate **  SM_STDCLOSE -- close the file
196*7c478bd9Sstevel@tonic-gate **
197*7c478bd9Sstevel@tonic-gate **	Parameters:
198*7c478bd9Sstevel@tonic-gate **		fp -- the file pointer to close
199*7c478bd9Sstevel@tonic-gate **
200*7c478bd9Sstevel@tonic-gate **	Returns:
201*7c478bd9Sstevel@tonic-gate **		Success: 0 (zero)
202*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
203*7c478bd9Sstevel@tonic-gate */
204*7c478bd9Sstevel@tonic-gate 
205*7c478bd9Sstevel@tonic-gate int
206*7c478bd9Sstevel@tonic-gate sm_stdclose(fp)
207*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
208*7c478bd9Sstevel@tonic-gate {
209*7c478bd9Sstevel@tonic-gate 	return close(fp->f_file);
210*7c478bd9Sstevel@tonic-gate }
211*7c478bd9Sstevel@tonic-gate 
212*7c478bd9Sstevel@tonic-gate /*
213*7c478bd9Sstevel@tonic-gate **  SM_STDSETMODE -- set the access mode for the file
214*7c478bd9Sstevel@tonic-gate **
215*7c478bd9Sstevel@tonic-gate **  Called by sm_stdsetinfo().
216*7c478bd9Sstevel@tonic-gate **
217*7c478bd9Sstevel@tonic-gate **	Parameters:
218*7c478bd9Sstevel@tonic-gate **		fp -- file pointer
219*7c478bd9Sstevel@tonic-gate **		mode -- new mode to set the file access to
220*7c478bd9Sstevel@tonic-gate **
221*7c478bd9Sstevel@tonic-gate **	Results:
222*7c478bd9Sstevel@tonic-gate **		Success: 0 (zero);
223*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
224*7c478bd9Sstevel@tonic-gate */
225*7c478bd9Sstevel@tonic-gate 
226*7c478bd9Sstevel@tonic-gate int
227*7c478bd9Sstevel@tonic-gate sm_stdsetmode(fp, mode)
228*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
229*7c478bd9Sstevel@tonic-gate 	const int *mode;
230*7c478bd9Sstevel@tonic-gate {
231*7c478bd9Sstevel@tonic-gate 	int flags = 0;
232*7c478bd9Sstevel@tonic-gate 
233*7c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(*mode))
234*7c478bd9Sstevel@tonic-gate 	{
235*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
236*7c478bd9Sstevel@tonic-gate 		flags |= SMRW;
237*7c478bd9Sstevel@tonic-gate 		break;
238*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
239*7c478bd9Sstevel@tonic-gate 		flags |= SMRD;
240*7c478bd9Sstevel@tonic-gate 		break;
241*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
242*7c478bd9Sstevel@tonic-gate 		flags |= SMWR;
243*7c478bd9Sstevel@tonic-gate 		break;
244*7c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
245*7c478bd9Sstevel@tonic-gate 	  default:
246*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
247*7c478bd9Sstevel@tonic-gate 		return -1;
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 	fp->f_flags = fp->f_flags & ~SMMODEMASK;
250*7c478bd9Sstevel@tonic-gate 	fp->f_flags |= flags;
251*7c478bd9Sstevel@tonic-gate 	return 0;
252*7c478bd9Sstevel@tonic-gate }
253*7c478bd9Sstevel@tonic-gate 
254*7c478bd9Sstevel@tonic-gate /*
255*7c478bd9Sstevel@tonic-gate **  SM_STDGETMODE -- for getinfo determine open mode
256*7c478bd9Sstevel@tonic-gate **
257*7c478bd9Sstevel@tonic-gate **  Called by sm_stdgetinfo().
258*7c478bd9Sstevel@tonic-gate **
259*7c478bd9Sstevel@tonic-gate **	Parameters:
260*7c478bd9Sstevel@tonic-gate **		fp -- the file mode being determined
261*7c478bd9Sstevel@tonic-gate **		mode -- internal mode to map to external value
262*7c478bd9Sstevel@tonic-gate **
263*7c478bd9Sstevel@tonic-gate **	Results:
264*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
265*7c478bd9Sstevel@tonic-gate **		Success: external mode value
266*7c478bd9Sstevel@tonic-gate */
267*7c478bd9Sstevel@tonic-gate 
268*7c478bd9Sstevel@tonic-gate static int
269*7c478bd9Sstevel@tonic-gate sm_stdgetmode(fp, mode)
270*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
271*7c478bd9Sstevel@tonic-gate 	int *mode;
272*7c478bd9Sstevel@tonic-gate {
273*7c478bd9Sstevel@tonic-gate 	switch (fp->f_flags & SMMODEMASK)
274*7c478bd9Sstevel@tonic-gate 	{
275*7c478bd9Sstevel@tonic-gate 	  case SMRW:
276*7c478bd9Sstevel@tonic-gate 		*mode = SM_IO_RDWR;
277*7c478bd9Sstevel@tonic-gate 		break;
278*7c478bd9Sstevel@tonic-gate 	  case SMRD:
279*7c478bd9Sstevel@tonic-gate 		*mode = SM_IO_RDONLY;
280*7c478bd9Sstevel@tonic-gate 		break;
281*7c478bd9Sstevel@tonic-gate 	  case SMWR:
282*7c478bd9Sstevel@tonic-gate 		*mode = SM_IO_WRONLY;
283*7c478bd9Sstevel@tonic-gate 		break;
284*7c478bd9Sstevel@tonic-gate 	  default:
285*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
286*7c478bd9Sstevel@tonic-gate 		return -1;
287*7c478bd9Sstevel@tonic-gate 	}
288*7c478bd9Sstevel@tonic-gate 	return 0;
289*7c478bd9Sstevel@tonic-gate }
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate /*
292*7c478bd9Sstevel@tonic-gate **  SM_STDSETINFO -- set/modify information for a file
293*7c478bd9Sstevel@tonic-gate **
294*7c478bd9Sstevel@tonic-gate **	Parameters:
295*7c478bd9Sstevel@tonic-gate **		fp -- file to set info for
296*7c478bd9Sstevel@tonic-gate **		what -- type of info to set
297*7c478bd9Sstevel@tonic-gate **		valp -- location of data used for setting
298*7c478bd9Sstevel@tonic-gate **
299*7c478bd9Sstevel@tonic-gate **	Returns:
300*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
301*7c478bd9Sstevel@tonic-gate **		Success: >=0
302*7c478bd9Sstevel@tonic-gate */
303*7c478bd9Sstevel@tonic-gate 
304*7c478bd9Sstevel@tonic-gate int
305*7c478bd9Sstevel@tonic-gate sm_stdsetinfo(fp, what, valp)
306*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
307*7c478bd9Sstevel@tonic-gate 	int what;
308*7c478bd9Sstevel@tonic-gate 	void *valp;
309*7c478bd9Sstevel@tonic-gate {
310*7c478bd9Sstevel@tonic-gate 	switch (what)
311*7c478bd9Sstevel@tonic-gate 	{
312*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_MODE:
313*7c478bd9Sstevel@tonic-gate 		return sm_stdsetmode(fp, (const int *)valp);
314*7c478bd9Sstevel@tonic-gate 
315*7c478bd9Sstevel@tonic-gate 	  default:
316*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
317*7c478bd9Sstevel@tonic-gate 		return -1;
318*7c478bd9Sstevel@tonic-gate 	}
319*7c478bd9Sstevel@tonic-gate }
320*7c478bd9Sstevel@tonic-gate 
321*7c478bd9Sstevel@tonic-gate /*
322*7c478bd9Sstevel@tonic-gate **  SM_GETINFO -- get information about the open file
323*7c478bd9Sstevel@tonic-gate **
324*7c478bd9Sstevel@tonic-gate **	Parameters:
325*7c478bd9Sstevel@tonic-gate **		fp -- file to get info for
326*7c478bd9Sstevel@tonic-gate **		what -- type of info to get
327*7c478bd9Sstevel@tonic-gate **		valp -- location to place found info
328*7c478bd9Sstevel@tonic-gate **
329*7c478bd9Sstevel@tonic-gate **	Returns:
330*7c478bd9Sstevel@tonic-gate **		Success: may or may not place info in 'valp' depending
331*7c478bd9Sstevel@tonic-gate **			on 'what' value, and returns values >=0. Return
332*7c478bd9Sstevel@tonic-gate **			value may be the obtained info
333*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
334*7c478bd9Sstevel@tonic-gate */
335*7c478bd9Sstevel@tonic-gate 
336*7c478bd9Sstevel@tonic-gate int
337*7c478bd9Sstevel@tonic-gate sm_stdgetinfo(fp, what, valp)
338*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
339*7c478bd9Sstevel@tonic-gate 	int what;
340*7c478bd9Sstevel@tonic-gate 	void *valp;
341*7c478bd9Sstevel@tonic-gate {
342*7c478bd9Sstevel@tonic-gate 	switch (what)
343*7c478bd9Sstevel@tonic-gate 	{
344*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_MODE:
345*7c478bd9Sstevel@tonic-gate 		return sm_stdgetmode(fp, (int *)valp);
346*7c478bd9Sstevel@tonic-gate 
347*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_FD:
348*7c478bd9Sstevel@tonic-gate 		return fp->f_file;
349*7c478bd9Sstevel@tonic-gate 
350*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_SIZE:
351*7c478bd9Sstevel@tonic-gate 	  {
352*7c478bd9Sstevel@tonic-gate 		  struct stat st;
353*7c478bd9Sstevel@tonic-gate 
354*7c478bd9Sstevel@tonic-gate 		  if (fstat(fp->f_file, &st) == 0)
355*7c478bd9Sstevel@tonic-gate 			  return st.st_size;
356*7c478bd9Sstevel@tonic-gate 		  else
357*7c478bd9Sstevel@tonic-gate 			  return -1;
358*7c478bd9Sstevel@tonic-gate 	  }
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	  case SM_IO_IS_READABLE:
361*7c478bd9Sstevel@tonic-gate 	  {
362*7c478bd9Sstevel@tonic-gate 		  fd_set readfds;
363*7c478bd9Sstevel@tonic-gate 		  struct timeval timeout;
364*7c478bd9Sstevel@tonic-gate 
365*7c478bd9Sstevel@tonic-gate 		  if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
366*7c478bd9Sstevel@tonic-gate 		  {
367*7c478bd9Sstevel@tonic-gate 			  errno = EINVAL;
368*7c478bd9Sstevel@tonic-gate 			  return -1;
369*7c478bd9Sstevel@tonic-gate 		  }
370*7c478bd9Sstevel@tonic-gate 		  FD_ZERO(&readfds);
371*7c478bd9Sstevel@tonic-gate 		  SM_FD_SET(fp->f_file, &readfds);
372*7c478bd9Sstevel@tonic-gate 		  timeout.tv_sec = 0;
373*7c478bd9Sstevel@tonic-gate 		  timeout.tv_usec = 0;
374*7c478bd9Sstevel@tonic-gate 		  if (select(fp->f_file + 1, FDSET_CAST &readfds,
375*7c478bd9Sstevel@tonic-gate 			     NULL, NULL, &timeout) > 0 &&
376*7c478bd9Sstevel@tonic-gate 		      SM_FD_ISSET(fp->f_file, &readfds))
377*7c478bd9Sstevel@tonic-gate 			  return 1;
378*7c478bd9Sstevel@tonic-gate 		  return 0;
379*7c478bd9Sstevel@tonic-gate 	  }
380*7c478bd9Sstevel@tonic-gate 
381*7c478bd9Sstevel@tonic-gate 	  default:
382*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
383*7c478bd9Sstevel@tonic-gate 		return -1;
384*7c478bd9Sstevel@tonic-gate 	}
385*7c478bd9Sstevel@tonic-gate }
386*7c478bd9Sstevel@tonic-gate 
387*7c478bd9Sstevel@tonic-gate /*
388*7c478bd9Sstevel@tonic-gate **  SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
389*7c478bd9Sstevel@tonic-gate **
390*7c478bd9Sstevel@tonic-gate **	I/O function to handle fdopen() stdio equivalence. The rest of
391*7c478bd9Sstevel@tonic-gate **	the functions are the same as the sm_stdopen() above.
392*7c478bd9Sstevel@tonic-gate **
393*7c478bd9Sstevel@tonic-gate **	Parameters:
394*7c478bd9Sstevel@tonic-gate **		fp -- the file pointer to be associated with the open
395*7c478bd9Sstevel@tonic-gate **		name -- the primitive file descriptor for association
396*7c478bd9Sstevel@tonic-gate **		flags -- indicates type of access methods
397*7c478bd9Sstevel@tonic-gate **		rpool -- ignored
398*7c478bd9Sstevel@tonic-gate **
399*7c478bd9Sstevel@tonic-gate **	Results:
400*7c478bd9Sstevel@tonic-gate **		Success: primitive file descriptor value
401*7c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
402*7c478bd9Sstevel@tonic-gate */
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
405*7c478bd9Sstevel@tonic-gate int
406*7c478bd9Sstevel@tonic-gate sm_stdfdopen(fp, info, flags, rpool)
407*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
408*7c478bd9Sstevel@tonic-gate 	const void *info;
409*7c478bd9Sstevel@tonic-gate 	int flags;
410*7c478bd9Sstevel@tonic-gate 	const void *rpool;
411*7c478bd9Sstevel@tonic-gate {
412*7c478bd9Sstevel@tonic-gate 	int oflags, tmp, fdflags, fd = *((int *) info);
413*7c478bd9Sstevel@tonic-gate 
414*7c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(flags))
415*7c478bd9Sstevel@tonic-gate 	{
416*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
417*7c478bd9Sstevel@tonic-gate 		oflags = O_RDWR | O_CREAT;
418*7c478bd9Sstevel@tonic-gate 		break;
419*7c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
420*7c478bd9Sstevel@tonic-gate 		oflags = O_RDONLY;
421*7c478bd9Sstevel@tonic-gate 		break;
422*7c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
423*7c478bd9Sstevel@tonic-gate 		oflags = O_WRONLY | O_CREAT | O_TRUNC;
424*7c478bd9Sstevel@tonic-gate 		break;
425*7c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
426*7c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_WRONLY | O_CREAT;
427*7c478bd9Sstevel@tonic-gate 		break;
428*7c478bd9Sstevel@tonic-gate 	  case SM_IO_APPENDRW:
429*7c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_RDWR | O_CREAT;
430*7c478bd9Sstevel@tonic-gate 		break;
431*7c478bd9Sstevel@tonic-gate 	  default:
432*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
433*7c478bd9Sstevel@tonic-gate 		return -1;
434*7c478bd9Sstevel@tonic-gate 	}
435*7c478bd9Sstevel@tonic-gate #ifdef O_BINARY
436*7c478bd9Sstevel@tonic-gate 	if (SM_IS_BINARY(flags))
437*7c478bd9Sstevel@tonic-gate 		oflags |= O_BINARY;
438*7c478bd9Sstevel@tonic-gate #endif /* O_BINARY */
439*7c478bd9Sstevel@tonic-gate 
440*7c478bd9Sstevel@tonic-gate 	/* Make sure the mode the user wants is a subset of the actual mode. */
441*7c478bd9Sstevel@tonic-gate 	if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
442*7c478bd9Sstevel@tonic-gate 		return -1;
443*7c478bd9Sstevel@tonic-gate 	tmp = fdflags & O_ACCMODE;
444*7c478bd9Sstevel@tonic-gate 	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
445*7c478bd9Sstevel@tonic-gate 	{
446*7c478bd9Sstevel@tonic-gate 		errno = EINVAL;
447*7c478bd9Sstevel@tonic-gate 		return -1;
448*7c478bd9Sstevel@tonic-gate 	}
449*7c478bd9Sstevel@tonic-gate 	fp->f_file = fd;
450*7c478bd9Sstevel@tonic-gate 	if (oflags & O_APPEND)
451*7c478bd9Sstevel@tonic-gate 		(void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
452*7c478bd9Sstevel@tonic-gate 	return fp->f_file;
453*7c478bd9Sstevel@tonic-gate }
454*7c478bd9Sstevel@tonic-gate 
455*7c478bd9Sstevel@tonic-gate /*
456*7c478bd9Sstevel@tonic-gate **  SM_IO_FOPEN -- open a file
457*7c478bd9Sstevel@tonic-gate **
458*7c478bd9Sstevel@tonic-gate **	Same interface and semantics as the open() system call,
459*7c478bd9Sstevel@tonic-gate **	except that it returns SM_FILE_T* instead of a file descriptor.
460*7c478bd9Sstevel@tonic-gate **
461*7c478bd9Sstevel@tonic-gate **	Parameters:
462*7c478bd9Sstevel@tonic-gate **		pathname -- path of file to open
463*7c478bd9Sstevel@tonic-gate **		flags -- flags controlling the open
464*7c478bd9Sstevel@tonic-gate **		...  -- option "mode" for opening the file
465*7c478bd9Sstevel@tonic-gate **
466*7c478bd9Sstevel@tonic-gate **	Returns:
467*7c478bd9Sstevel@tonic-gate **		Raises an exception on heap exhaustion.
468*7c478bd9Sstevel@tonic-gate **		Returns NULL and sets errno if open() fails.
469*7c478bd9Sstevel@tonic-gate **		Returns an SM_FILE_T pointer on success.
470*7c478bd9Sstevel@tonic-gate */
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate SM_FILE_T *
473*7c478bd9Sstevel@tonic-gate #if SM_VA_STD
474*7c478bd9Sstevel@tonic-gate sm_io_fopen(char *pathname, int flags, ...)
475*7c478bd9Sstevel@tonic-gate #else /* SM_VA_STD */
476*7c478bd9Sstevel@tonic-gate sm_io_fopen(pathname, flags, va_alist)
477*7c478bd9Sstevel@tonic-gate 	char *pathname;
478*7c478bd9Sstevel@tonic-gate 	int flags;
479*7c478bd9Sstevel@tonic-gate 	va_dcl
480*7c478bd9Sstevel@tonic-gate #endif /* SM_VA_STD */
481*7c478bd9Sstevel@tonic-gate {
482*7c478bd9Sstevel@tonic-gate 	MODE_T mode;
483*7c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
484*7c478bd9Sstevel@tonic-gate 	int ioflags;
485*7c478bd9Sstevel@tonic-gate 
486*7c478bd9Sstevel@tonic-gate 	if (flags & O_CREAT)
487*7c478bd9Sstevel@tonic-gate 	{
488*7c478bd9Sstevel@tonic-gate 		SM_VA_LOCAL_DECL
489*7c478bd9Sstevel@tonic-gate 
490*7c478bd9Sstevel@tonic-gate 		SM_VA_START(ap, flags);
491*7c478bd9Sstevel@tonic-gate 		mode = (MODE_T) SM_VA_ARG(ap, int);
492*7c478bd9Sstevel@tonic-gate 		SM_VA_END(ap);
493*7c478bd9Sstevel@tonic-gate 	}
494*7c478bd9Sstevel@tonic-gate 	else
495*7c478bd9Sstevel@tonic-gate 		mode = 0;
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 	switch (flags & O_ACCMODE)
498*7c478bd9Sstevel@tonic-gate 	{
499*7c478bd9Sstevel@tonic-gate 	  case O_RDONLY:
500*7c478bd9Sstevel@tonic-gate 		ioflags = SMRD;
501*7c478bd9Sstevel@tonic-gate 		break;
502*7c478bd9Sstevel@tonic-gate 	  case O_WRONLY:
503*7c478bd9Sstevel@tonic-gate 		ioflags = SMWR;
504*7c478bd9Sstevel@tonic-gate 		break;
505*7c478bd9Sstevel@tonic-gate 	  case O_RDWR:
506*7c478bd9Sstevel@tonic-gate 		ioflags = SMRW;
507*7c478bd9Sstevel@tonic-gate 		break;
508*7c478bd9Sstevel@tonic-gate 	  default:
509*7c478bd9Sstevel@tonic-gate 		sm_abort("sm_io_fopen: bad flags 0%o", flags);
510*7c478bd9Sstevel@tonic-gate 	}
511*7c478bd9Sstevel@tonic-gate 
512*7c478bd9Sstevel@tonic-gate 	fp = sm_fp(SmFtStdio, ioflags, NULL);
513*7c478bd9Sstevel@tonic-gate 	fp->f_file = open(pathname, flags, mode);
514*7c478bd9Sstevel@tonic-gate 	if (fp->f_file == -1)
515*7c478bd9Sstevel@tonic-gate 	{
516*7c478bd9Sstevel@tonic-gate 		fp->f_flags = 0;
517*7c478bd9Sstevel@tonic-gate 		fp->sm_magic = NULL;
518*7c478bd9Sstevel@tonic-gate 		return NULL;
519*7c478bd9Sstevel@tonic-gate 	}
520*7c478bd9Sstevel@tonic-gate 	return fp;
521*7c478bd9Sstevel@tonic-gate }
522