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