xref: /titanic_50/usr/src/cmd/sendmail/libsm/stdio.c (revision 49218d4f8e4d84d1c08aeb267bcf6e451f2056dc)
17c478bd9Sstevel@tonic-gate /*
2*49218d4fSjbeck  * Copyright (c) 2000-2005 Sendmail, Inc. and its suppliers.
37c478bd9Sstevel@tonic-gate  *      All rights reserved.
47c478bd9Sstevel@tonic-gate  * Copyright (c) 1990, 1993
57c478bd9Sstevel@tonic-gate  *	The Regents of the University of California.  All rights reserved.
67c478bd9Sstevel@tonic-gate  *
77c478bd9Sstevel@tonic-gate  * This code is derived from software contributed to Berkeley by
87c478bd9Sstevel@tonic-gate  * Chris Torek.
97c478bd9Sstevel@tonic-gate  *
107c478bd9Sstevel@tonic-gate  * By using this file, you agree to the terms and conditions set
117c478bd9Sstevel@tonic-gate  * forth in the LICENSE file which can be found at the top level of
127c478bd9Sstevel@tonic-gate  * the sendmail distribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
167c478bd9Sstevel@tonic-gate 
177c478bd9Sstevel@tonic-gate #include <sm/gen.h>
18*49218d4fSjbeck SM_RCSID("@(#)$Id: stdio.c,v 1.71 2005/06/14 23:07:20 ca Exp $")
197c478bd9Sstevel@tonic-gate #include <unistd.h>
207c478bd9Sstevel@tonic-gate #include <errno.h>
217c478bd9Sstevel@tonic-gate #include <fcntl.h>
227c478bd9Sstevel@tonic-gate #include <string.h>	/* FreeBSD: FD_ZERO needs <string.h> */
237c478bd9Sstevel@tonic-gate #include <sys/stat.h>
24*49218d4fSjbeck #include <sm/time.h>
257c478bd9Sstevel@tonic-gate #include <sm/heap.h>
267c478bd9Sstevel@tonic-gate #include <sm/assert.h>
277c478bd9Sstevel@tonic-gate #include <sm/varargs.h>
287c478bd9Sstevel@tonic-gate #include <sm/io.h>
297c478bd9Sstevel@tonic-gate #include <sm/setjmp.h>
307c478bd9Sstevel@tonic-gate #include <sm/conf.h>
317c478bd9Sstevel@tonic-gate #include <sm/fdset.h>
327c478bd9Sstevel@tonic-gate #include "local.h"
337c478bd9Sstevel@tonic-gate 
347c478bd9Sstevel@tonic-gate static int	sm_stdsetmode __P((SM_FILE_T *, const int *));
357c478bd9Sstevel@tonic-gate static int	sm_stdgetmode __P((SM_FILE_T *, int *));
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate **  Overall:
397c478bd9Sstevel@tonic-gate **  Small standard I/O/seek/close functions.
407c478bd9Sstevel@tonic-gate **  These maintain the `known seek offset' for seek optimization.
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate 
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate **  SM_STDOPEN -- open a file with stdio behavior
457c478bd9Sstevel@tonic-gate **
467c478bd9Sstevel@tonic-gate **  Not associated with the system's stdio in libc.
477c478bd9Sstevel@tonic-gate **
487c478bd9Sstevel@tonic-gate **	Parameters:
497c478bd9Sstevel@tonic-gate **		fp -- file pointer to be associated with the open
507c478bd9Sstevel@tonic-gate **		info -- pathname of the file to be opened
517c478bd9Sstevel@tonic-gate **		flags -- indicates type of access methods
527c478bd9Sstevel@tonic-gate **		rpool -- ignored
537c478bd9Sstevel@tonic-gate **
547c478bd9Sstevel@tonic-gate **	Returns:
557c478bd9Sstevel@tonic-gate **		Failure: -1 and set errno
567c478bd9Sstevel@tonic-gate **		Success: 0 or greater (fd of file from open(2)).
577c478bd9Sstevel@tonic-gate **
587c478bd9Sstevel@tonic-gate */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
617c478bd9Sstevel@tonic-gate int
sm_stdopen(fp,info,flags,rpool)627c478bd9Sstevel@tonic-gate sm_stdopen(fp, info, flags, rpool)
637c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
647c478bd9Sstevel@tonic-gate 	const void *info;
657c478bd9Sstevel@tonic-gate 	int flags;
667c478bd9Sstevel@tonic-gate 	const void *rpool;
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate 	char *path = (char *) info;
697c478bd9Sstevel@tonic-gate 	int oflags;
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(flags))
727c478bd9Sstevel@tonic-gate 	{
737c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
747c478bd9Sstevel@tonic-gate 		oflags = O_RDWR;
757c478bd9Sstevel@tonic-gate 		break;
767c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWRTR:
777c478bd9Sstevel@tonic-gate 		oflags = O_RDWR | O_CREAT | O_TRUNC;
787c478bd9Sstevel@tonic-gate 		break;
797c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
807c478bd9Sstevel@tonic-gate 		oflags = O_RDONLY;
817c478bd9Sstevel@tonic-gate 		break;
827c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
837c478bd9Sstevel@tonic-gate 		oflags = O_WRONLY | O_CREAT | O_TRUNC;
847c478bd9Sstevel@tonic-gate 		break;
857c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
867c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_WRONLY | O_CREAT;
877c478bd9Sstevel@tonic-gate 		break;
887c478bd9Sstevel@tonic-gate 	  case SM_IO_APPENDRW:
897c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_RDWR | O_CREAT;
907c478bd9Sstevel@tonic-gate 		break;
917c478bd9Sstevel@tonic-gate 	  default:
927c478bd9Sstevel@tonic-gate 		errno = EINVAL;
937c478bd9Sstevel@tonic-gate 		return -1;
947c478bd9Sstevel@tonic-gate 	}
957c478bd9Sstevel@tonic-gate #ifdef O_BINARY
967c478bd9Sstevel@tonic-gate 	if (SM_IS_BINARY(flags))
977c478bd9Sstevel@tonic-gate 		oflags |= O_BINARY;
987c478bd9Sstevel@tonic-gate #endif /* O_BINARY */
997c478bd9Sstevel@tonic-gate 	fp->f_file = open(path, oflags,
1007c478bd9Sstevel@tonic-gate 			  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
1017c478bd9Sstevel@tonic-gate 	if (fp->f_file < 0)
1027c478bd9Sstevel@tonic-gate 		return -1; /* errno set by open() */
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (oflags & O_APPEND)
1057c478bd9Sstevel@tonic-gate 		(void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 	return fp->f_file;
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate **  SM_STDREAD -- read from the file
1127c478bd9Sstevel@tonic-gate **
1137c478bd9Sstevel@tonic-gate **	Parameters:
1147c478bd9Sstevel@tonic-gate **		fp -- file pointer to read from
1157c478bd9Sstevel@tonic-gate **		buf -- location to place read data
1167c478bd9Sstevel@tonic-gate **		n -- number of bytes to read
1177c478bd9Sstevel@tonic-gate **
1187c478bd9Sstevel@tonic-gate **	Returns:
1197c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
1207c478bd9Sstevel@tonic-gate **		Success: number of bytes read
1217c478bd9Sstevel@tonic-gate **
1227c478bd9Sstevel@tonic-gate **	Side Effects:
1237c478bd9Sstevel@tonic-gate **		Updates internal offset into file.
1247c478bd9Sstevel@tonic-gate */
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate ssize_t
sm_stdread(fp,buf,n)1277c478bd9Sstevel@tonic-gate sm_stdread(fp, buf, n)
1287c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
1297c478bd9Sstevel@tonic-gate 	char *buf;
1307c478bd9Sstevel@tonic-gate 	size_t n;
1317c478bd9Sstevel@tonic-gate {
1327c478bd9Sstevel@tonic-gate 	register int ret;
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate 	ret = read(fp->f_file, buf, n);
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate 	/* if the read succeeded, update the current offset */
1377c478bd9Sstevel@tonic-gate 	if (ret > 0)
1387c478bd9Sstevel@tonic-gate 		fp->f_lseekoff += ret;
1397c478bd9Sstevel@tonic-gate 	return ret;
1407c478bd9Sstevel@tonic-gate }
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate /*
1437c478bd9Sstevel@tonic-gate **  SM_STDWRITE -- write to the file
1447c478bd9Sstevel@tonic-gate **
1457c478bd9Sstevel@tonic-gate **	Parameters:
1467c478bd9Sstevel@tonic-gate **		fp -- file pointer ro write to
1477c478bd9Sstevel@tonic-gate **		buf -- location of data to be written
1487c478bd9Sstevel@tonic-gate **		n - number of bytes to write
1497c478bd9Sstevel@tonic-gate **
1507c478bd9Sstevel@tonic-gate **	Returns:
1517c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
1527c478bd9Sstevel@tonic-gate **		Success: number of bytes written
1537c478bd9Sstevel@tonic-gate */
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate ssize_t
sm_stdwrite(fp,buf,n)1567c478bd9Sstevel@tonic-gate sm_stdwrite(fp, buf, n)
1577c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
1587c478bd9Sstevel@tonic-gate 	char const *buf;
1597c478bd9Sstevel@tonic-gate 	size_t n;
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	return write(fp->f_file, buf, n);
1627c478bd9Sstevel@tonic-gate }
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate /*
1657c478bd9Sstevel@tonic-gate **  SM_STDSEEK -- set the file offset position
1667c478bd9Sstevel@tonic-gate **
1677c478bd9Sstevel@tonic-gate **	Parmeters:
1687c478bd9Sstevel@tonic-gate **		fp -- file pointer to position
1697c478bd9Sstevel@tonic-gate **		offset -- how far to position from "base" (set by 'whence')
1707c478bd9Sstevel@tonic-gate **		whence -- indicates where the "base" of the 'offset' to start
1717c478bd9Sstevel@tonic-gate **
1727c478bd9Sstevel@tonic-gate **	Results:
1737c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
1747c478bd9Sstevel@tonic-gate **		Success: the current offset
1757c478bd9Sstevel@tonic-gate **
1767c478bd9Sstevel@tonic-gate **	Side Effects:
1777c478bd9Sstevel@tonic-gate **		Updates the internal value of the offset.
1787c478bd9Sstevel@tonic-gate */
1797c478bd9Sstevel@tonic-gate 
1807c478bd9Sstevel@tonic-gate off_t
sm_stdseek(fp,offset,whence)1817c478bd9Sstevel@tonic-gate sm_stdseek(fp, offset, whence)
1827c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
1837c478bd9Sstevel@tonic-gate 	off_t offset;
1847c478bd9Sstevel@tonic-gate 	int whence;
1857c478bd9Sstevel@tonic-gate {
1867c478bd9Sstevel@tonic-gate 	register off_t ret;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	ret = lseek(fp->f_file, (off_t) offset, whence);
1897c478bd9Sstevel@tonic-gate 	if (ret != (off_t) -1)
1907c478bd9Sstevel@tonic-gate 		fp->f_lseekoff = ret;
1917c478bd9Sstevel@tonic-gate 	return ret;
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate 
1947c478bd9Sstevel@tonic-gate /*
1957c478bd9Sstevel@tonic-gate **  SM_STDCLOSE -- close the file
1967c478bd9Sstevel@tonic-gate **
1977c478bd9Sstevel@tonic-gate **	Parameters:
1987c478bd9Sstevel@tonic-gate **		fp -- the file pointer to close
1997c478bd9Sstevel@tonic-gate **
2007c478bd9Sstevel@tonic-gate **	Returns:
2017c478bd9Sstevel@tonic-gate **		Success: 0 (zero)
2027c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
2037c478bd9Sstevel@tonic-gate */
2047c478bd9Sstevel@tonic-gate 
2057c478bd9Sstevel@tonic-gate int
sm_stdclose(fp)2067c478bd9Sstevel@tonic-gate sm_stdclose(fp)
2077c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
2087c478bd9Sstevel@tonic-gate {
2097c478bd9Sstevel@tonic-gate 	return close(fp->f_file);
2107c478bd9Sstevel@tonic-gate }
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate **  SM_STDSETMODE -- set the access mode for the file
2147c478bd9Sstevel@tonic-gate **
2157c478bd9Sstevel@tonic-gate **  Called by sm_stdsetinfo().
2167c478bd9Sstevel@tonic-gate **
2177c478bd9Sstevel@tonic-gate **	Parameters:
2187c478bd9Sstevel@tonic-gate **		fp -- file pointer
2197c478bd9Sstevel@tonic-gate **		mode -- new mode to set the file access to
2207c478bd9Sstevel@tonic-gate **
2217c478bd9Sstevel@tonic-gate **	Results:
2227c478bd9Sstevel@tonic-gate **		Success: 0 (zero);
2237c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
2247c478bd9Sstevel@tonic-gate */
2257c478bd9Sstevel@tonic-gate 
226*49218d4fSjbeck static int
sm_stdsetmode(fp,mode)2277c478bd9Sstevel@tonic-gate sm_stdsetmode(fp, mode)
2287c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
2297c478bd9Sstevel@tonic-gate 	const int *mode;
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 	int flags = 0;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(*mode))
2347c478bd9Sstevel@tonic-gate 	{
2357c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
2367c478bd9Sstevel@tonic-gate 		flags |= SMRW;
2377c478bd9Sstevel@tonic-gate 		break;
2387c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
2397c478bd9Sstevel@tonic-gate 		flags |= SMRD;
2407c478bd9Sstevel@tonic-gate 		break;
2417c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
2427c478bd9Sstevel@tonic-gate 		flags |= SMWR;
2437c478bd9Sstevel@tonic-gate 		break;
2447c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
2457c478bd9Sstevel@tonic-gate 	  default:
2467c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2477c478bd9Sstevel@tonic-gate 		return -1;
2487c478bd9Sstevel@tonic-gate 	}
2497c478bd9Sstevel@tonic-gate 	fp->f_flags = fp->f_flags & ~SMMODEMASK;
2507c478bd9Sstevel@tonic-gate 	fp->f_flags |= flags;
2517c478bd9Sstevel@tonic-gate 	return 0;
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate /*
2557c478bd9Sstevel@tonic-gate **  SM_STDGETMODE -- for getinfo determine open mode
2567c478bd9Sstevel@tonic-gate **
2577c478bd9Sstevel@tonic-gate **  Called by sm_stdgetinfo().
2587c478bd9Sstevel@tonic-gate **
2597c478bd9Sstevel@tonic-gate **	Parameters:
2607c478bd9Sstevel@tonic-gate **		fp -- the file mode being determined
2617c478bd9Sstevel@tonic-gate **		mode -- internal mode to map to external value
2627c478bd9Sstevel@tonic-gate **
2637c478bd9Sstevel@tonic-gate **	Results:
2647c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
2657c478bd9Sstevel@tonic-gate **		Success: external mode value
2667c478bd9Sstevel@tonic-gate */
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate static int
sm_stdgetmode(fp,mode)2697c478bd9Sstevel@tonic-gate sm_stdgetmode(fp, mode)
2707c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
2717c478bd9Sstevel@tonic-gate 	int *mode;
2727c478bd9Sstevel@tonic-gate {
2737c478bd9Sstevel@tonic-gate 	switch (fp->f_flags & SMMODEMASK)
2747c478bd9Sstevel@tonic-gate 	{
2757c478bd9Sstevel@tonic-gate 	  case SMRW:
2767c478bd9Sstevel@tonic-gate 		*mode = SM_IO_RDWR;
2777c478bd9Sstevel@tonic-gate 		break;
2787c478bd9Sstevel@tonic-gate 	  case SMRD:
2797c478bd9Sstevel@tonic-gate 		*mode = SM_IO_RDONLY;
2807c478bd9Sstevel@tonic-gate 		break;
2817c478bd9Sstevel@tonic-gate 	  case SMWR:
2827c478bd9Sstevel@tonic-gate 		*mode = SM_IO_WRONLY;
2837c478bd9Sstevel@tonic-gate 		break;
2847c478bd9Sstevel@tonic-gate 	  default:
2857c478bd9Sstevel@tonic-gate 		errno = EINVAL;
2867c478bd9Sstevel@tonic-gate 		return -1;
2877c478bd9Sstevel@tonic-gate 	}
2887c478bd9Sstevel@tonic-gate 	return 0;
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate 
2917c478bd9Sstevel@tonic-gate /*
2927c478bd9Sstevel@tonic-gate **  SM_STDSETINFO -- set/modify information for a file
2937c478bd9Sstevel@tonic-gate **
2947c478bd9Sstevel@tonic-gate **	Parameters:
2957c478bd9Sstevel@tonic-gate **		fp -- file to set info for
2967c478bd9Sstevel@tonic-gate **		what -- type of info to set
2977c478bd9Sstevel@tonic-gate **		valp -- location of data used for setting
2987c478bd9Sstevel@tonic-gate **
2997c478bd9Sstevel@tonic-gate **	Returns:
3007c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
3017c478bd9Sstevel@tonic-gate **		Success: >=0
3027c478bd9Sstevel@tonic-gate */
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate int
sm_stdsetinfo(fp,what,valp)3057c478bd9Sstevel@tonic-gate sm_stdsetinfo(fp, what, valp)
3067c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
3077c478bd9Sstevel@tonic-gate 	int what;
3087c478bd9Sstevel@tonic-gate 	void *valp;
3097c478bd9Sstevel@tonic-gate {
3107c478bd9Sstevel@tonic-gate 	switch (what)
3117c478bd9Sstevel@tonic-gate 	{
3127c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_MODE:
3137c478bd9Sstevel@tonic-gate 		return sm_stdsetmode(fp, (const int *)valp);
3147c478bd9Sstevel@tonic-gate 
3157c478bd9Sstevel@tonic-gate 	  default:
3167c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3177c478bd9Sstevel@tonic-gate 		return -1;
3187c478bd9Sstevel@tonic-gate 	}
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate **  SM_GETINFO -- get information about the open file
3237c478bd9Sstevel@tonic-gate **
3247c478bd9Sstevel@tonic-gate **	Parameters:
3257c478bd9Sstevel@tonic-gate **		fp -- file to get info for
3267c478bd9Sstevel@tonic-gate **		what -- type of info to get
3277c478bd9Sstevel@tonic-gate **		valp -- location to place found info
3287c478bd9Sstevel@tonic-gate **
3297c478bd9Sstevel@tonic-gate **	Returns:
3307c478bd9Sstevel@tonic-gate **		Success: may or may not place info in 'valp' depending
3317c478bd9Sstevel@tonic-gate **			on 'what' value, and returns values >=0. Return
3327c478bd9Sstevel@tonic-gate **			value may be the obtained info
3337c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate int
sm_stdgetinfo(fp,what,valp)3377c478bd9Sstevel@tonic-gate sm_stdgetinfo(fp, what, valp)
3387c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
3397c478bd9Sstevel@tonic-gate 	int what;
3407c478bd9Sstevel@tonic-gate 	void *valp;
3417c478bd9Sstevel@tonic-gate {
3427c478bd9Sstevel@tonic-gate 	switch (what)
3437c478bd9Sstevel@tonic-gate 	{
3447c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_MODE:
3457c478bd9Sstevel@tonic-gate 		return sm_stdgetmode(fp, (int *)valp);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_FD:
3487c478bd9Sstevel@tonic-gate 		return fp->f_file;
3497c478bd9Sstevel@tonic-gate 
3507c478bd9Sstevel@tonic-gate 	  case SM_IO_WHAT_SIZE:
3517c478bd9Sstevel@tonic-gate 	  {
3527c478bd9Sstevel@tonic-gate 		  struct stat st;
3537c478bd9Sstevel@tonic-gate 
3547c478bd9Sstevel@tonic-gate 		  if (fstat(fp->f_file, &st) == 0)
3557c478bd9Sstevel@tonic-gate 			  return st.st_size;
3567c478bd9Sstevel@tonic-gate 		  else
3577c478bd9Sstevel@tonic-gate 			  return -1;
3587c478bd9Sstevel@tonic-gate 	  }
3597c478bd9Sstevel@tonic-gate 
3607c478bd9Sstevel@tonic-gate 	  case SM_IO_IS_READABLE:
3617c478bd9Sstevel@tonic-gate 	  {
3627c478bd9Sstevel@tonic-gate 		  fd_set readfds;
3637c478bd9Sstevel@tonic-gate 		  struct timeval timeout;
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 		  if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
3667c478bd9Sstevel@tonic-gate 		  {
3677c478bd9Sstevel@tonic-gate 			  errno = EINVAL;
3687c478bd9Sstevel@tonic-gate 			  return -1;
3697c478bd9Sstevel@tonic-gate 		  }
3707c478bd9Sstevel@tonic-gate 		  FD_ZERO(&readfds);
3717c478bd9Sstevel@tonic-gate 		  SM_FD_SET(fp->f_file, &readfds);
3727c478bd9Sstevel@tonic-gate 		  timeout.tv_sec = 0;
3737c478bd9Sstevel@tonic-gate 		  timeout.tv_usec = 0;
3747c478bd9Sstevel@tonic-gate 		  if (select(fp->f_file + 1, FDSET_CAST &readfds,
3757c478bd9Sstevel@tonic-gate 			     NULL, NULL, &timeout) > 0 &&
3767c478bd9Sstevel@tonic-gate 		      SM_FD_ISSET(fp->f_file, &readfds))
3777c478bd9Sstevel@tonic-gate 			  return 1;
3787c478bd9Sstevel@tonic-gate 		  return 0;
3797c478bd9Sstevel@tonic-gate 	  }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 	  default:
3827c478bd9Sstevel@tonic-gate 		errno = EINVAL;
3837c478bd9Sstevel@tonic-gate 		return -1;
3847c478bd9Sstevel@tonic-gate 	}
3857c478bd9Sstevel@tonic-gate }
3867c478bd9Sstevel@tonic-gate 
3877c478bd9Sstevel@tonic-gate /*
3887c478bd9Sstevel@tonic-gate **  SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
3897c478bd9Sstevel@tonic-gate **
3907c478bd9Sstevel@tonic-gate **	I/O function to handle fdopen() stdio equivalence. The rest of
3917c478bd9Sstevel@tonic-gate **	the functions are the same as the sm_stdopen() above.
3927c478bd9Sstevel@tonic-gate **
3937c478bd9Sstevel@tonic-gate **	Parameters:
3947c478bd9Sstevel@tonic-gate **		fp -- the file pointer to be associated with the open
3957c478bd9Sstevel@tonic-gate **		name -- the primitive file descriptor for association
3967c478bd9Sstevel@tonic-gate **		flags -- indicates type of access methods
3977c478bd9Sstevel@tonic-gate **		rpool -- ignored
3987c478bd9Sstevel@tonic-gate **
3997c478bd9Sstevel@tonic-gate **	Results:
4007c478bd9Sstevel@tonic-gate **		Success: primitive file descriptor value
4017c478bd9Sstevel@tonic-gate **		Failure: -1 and sets errno
4027c478bd9Sstevel@tonic-gate */
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate /* ARGSUSED3 */
4057c478bd9Sstevel@tonic-gate int
sm_stdfdopen(fp,info,flags,rpool)4067c478bd9Sstevel@tonic-gate sm_stdfdopen(fp, info, flags, rpool)
4077c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
4087c478bd9Sstevel@tonic-gate 	const void *info;
4097c478bd9Sstevel@tonic-gate 	int flags;
4107c478bd9Sstevel@tonic-gate 	const void *rpool;
4117c478bd9Sstevel@tonic-gate {
4127c478bd9Sstevel@tonic-gate 	int oflags, tmp, fdflags, fd = *((int *) info);
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	switch (SM_IO_MODE(flags))
4157c478bd9Sstevel@tonic-gate 	{
4167c478bd9Sstevel@tonic-gate 	  case SM_IO_RDWR:
4177c478bd9Sstevel@tonic-gate 		oflags = O_RDWR | O_CREAT;
4187c478bd9Sstevel@tonic-gate 		break;
4197c478bd9Sstevel@tonic-gate 	  case SM_IO_RDONLY:
4207c478bd9Sstevel@tonic-gate 		oflags = O_RDONLY;
4217c478bd9Sstevel@tonic-gate 		break;
4227c478bd9Sstevel@tonic-gate 	  case SM_IO_WRONLY:
4237c478bd9Sstevel@tonic-gate 		oflags = O_WRONLY | O_CREAT | O_TRUNC;
4247c478bd9Sstevel@tonic-gate 		break;
4257c478bd9Sstevel@tonic-gate 	  case SM_IO_APPEND:
4267c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_WRONLY | O_CREAT;
4277c478bd9Sstevel@tonic-gate 		break;
4287c478bd9Sstevel@tonic-gate 	  case SM_IO_APPENDRW:
4297c478bd9Sstevel@tonic-gate 		oflags = O_APPEND | O_RDWR | O_CREAT;
4307c478bd9Sstevel@tonic-gate 		break;
4317c478bd9Sstevel@tonic-gate 	  default:
4327c478bd9Sstevel@tonic-gate 		errno = EINVAL;
4337c478bd9Sstevel@tonic-gate 		return -1;
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate #ifdef O_BINARY
4367c478bd9Sstevel@tonic-gate 	if (SM_IS_BINARY(flags))
4377c478bd9Sstevel@tonic-gate 		oflags |= O_BINARY;
4387c478bd9Sstevel@tonic-gate #endif /* O_BINARY */
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate 	/* Make sure the mode the user wants is a subset of the actual mode. */
4417c478bd9Sstevel@tonic-gate 	if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
4427c478bd9Sstevel@tonic-gate 		return -1;
4437c478bd9Sstevel@tonic-gate 	tmp = fdflags & O_ACCMODE;
4447c478bd9Sstevel@tonic-gate 	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
4457c478bd9Sstevel@tonic-gate 	{
4467c478bd9Sstevel@tonic-gate 		errno = EINVAL;
4477c478bd9Sstevel@tonic-gate 		return -1;
4487c478bd9Sstevel@tonic-gate 	}
4497c478bd9Sstevel@tonic-gate 	fp->f_file = fd;
4507c478bd9Sstevel@tonic-gate 	if (oflags & O_APPEND)
4517c478bd9Sstevel@tonic-gate 		(void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
4527c478bd9Sstevel@tonic-gate 	return fp->f_file;
4537c478bd9Sstevel@tonic-gate }
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate **  SM_IO_FOPEN -- open a file
4577c478bd9Sstevel@tonic-gate **
4587c478bd9Sstevel@tonic-gate **	Same interface and semantics as the open() system call,
4597c478bd9Sstevel@tonic-gate **	except that it returns SM_FILE_T* instead of a file descriptor.
4607c478bd9Sstevel@tonic-gate **
4617c478bd9Sstevel@tonic-gate **	Parameters:
4627c478bd9Sstevel@tonic-gate **		pathname -- path of file to open
4637c478bd9Sstevel@tonic-gate **		flags -- flags controlling the open
4647c478bd9Sstevel@tonic-gate **		...  -- option "mode" for opening the file
4657c478bd9Sstevel@tonic-gate **
4667c478bd9Sstevel@tonic-gate **	Returns:
4677c478bd9Sstevel@tonic-gate **		Raises an exception on heap exhaustion.
4687c478bd9Sstevel@tonic-gate **		Returns NULL and sets errno if open() fails.
4697c478bd9Sstevel@tonic-gate **		Returns an SM_FILE_T pointer on success.
4707c478bd9Sstevel@tonic-gate */
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate SM_FILE_T *
4737c478bd9Sstevel@tonic-gate #if SM_VA_STD
sm_io_fopen(char * pathname,int flags,...)4747c478bd9Sstevel@tonic-gate sm_io_fopen(char *pathname, int flags, ...)
4757c478bd9Sstevel@tonic-gate #else /* SM_VA_STD */
4767c478bd9Sstevel@tonic-gate sm_io_fopen(pathname, flags, va_alist)
4777c478bd9Sstevel@tonic-gate 	char *pathname;
4787c478bd9Sstevel@tonic-gate 	int flags;
4797c478bd9Sstevel@tonic-gate 	va_dcl
4807c478bd9Sstevel@tonic-gate #endif /* SM_VA_STD */
4817c478bd9Sstevel@tonic-gate {
4827c478bd9Sstevel@tonic-gate 	MODE_T mode;
4837c478bd9Sstevel@tonic-gate 	SM_FILE_T *fp;
4847c478bd9Sstevel@tonic-gate 	int ioflags;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 	if (flags & O_CREAT)
4877c478bd9Sstevel@tonic-gate 	{
4887c478bd9Sstevel@tonic-gate 		SM_VA_LOCAL_DECL
4897c478bd9Sstevel@tonic-gate 
4907c478bd9Sstevel@tonic-gate 		SM_VA_START(ap, flags);
4917c478bd9Sstevel@tonic-gate 		mode = (MODE_T) SM_VA_ARG(ap, int);
4927c478bd9Sstevel@tonic-gate 		SM_VA_END(ap);
4937c478bd9Sstevel@tonic-gate 	}
4947c478bd9Sstevel@tonic-gate 	else
4957c478bd9Sstevel@tonic-gate 		mode = 0;
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	switch (flags & O_ACCMODE)
4987c478bd9Sstevel@tonic-gate 	{
4997c478bd9Sstevel@tonic-gate 	  case O_RDONLY:
5007c478bd9Sstevel@tonic-gate 		ioflags = SMRD;
5017c478bd9Sstevel@tonic-gate 		break;
5027c478bd9Sstevel@tonic-gate 	  case O_WRONLY:
5037c478bd9Sstevel@tonic-gate 		ioflags = SMWR;
5047c478bd9Sstevel@tonic-gate 		break;
5057c478bd9Sstevel@tonic-gate 	  case O_RDWR:
5067c478bd9Sstevel@tonic-gate 		ioflags = SMRW;
5077c478bd9Sstevel@tonic-gate 		break;
5087c478bd9Sstevel@tonic-gate 	  default:
5097c478bd9Sstevel@tonic-gate 		sm_abort("sm_io_fopen: bad flags 0%o", flags);
5107c478bd9Sstevel@tonic-gate 	}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	fp = sm_fp(SmFtStdio, ioflags, NULL);
5137c478bd9Sstevel@tonic-gate 	fp->f_file = open(pathname, flags, mode);
5147c478bd9Sstevel@tonic-gate 	if (fp->f_file == -1)
5157c478bd9Sstevel@tonic-gate 	{
5167c478bd9Sstevel@tonic-gate 		fp->f_flags = 0;
5177c478bd9Sstevel@tonic-gate 		fp->sm_magic = NULL;
5187c478bd9Sstevel@tonic-gate 		return NULL;
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 	return fp;
5217c478bd9Sstevel@tonic-gate }
522