190792Sgshapiro/*
2261363Sgshapiro * Copyright (c) 2000-2005 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro * Copyright (c) 1990, 1993
590792Sgshapiro *	The Regents of the University of California.  All rights reserved.
690792Sgshapiro *
790792Sgshapiro * This code is derived from software contributed to Berkeley by
890792Sgshapiro * Chris Torek.
990792Sgshapiro *
1090792Sgshapiro * By using this file, you agree to the terms and conditions set
1190792Sgshapiro * forth in the LICENSE file which can be found at the top level of
1290792Sgshapiro * the sendmail distribution.
1390792Sgshapiro */
1490792Sgshapiro
1590792Sgshapiro#include <sm/gen.h>
16266692SgshapiroSM_RCSID("@(#)$Id: stdio.c,v 1.72 2013-11-22 20:51:43 ca Exp $")
1790792Sgshapiro#include <unistd.h>
1890792Sgshapiro#include <errno.h>
1990792Sgshapiro#include <fcntl.h>
2090792Sgshapiro#include <string.h>	/* FreeBSD: FD_ZERO needs <string.h> */
2190792Sgshapiro#include <sys/stat.h>
22157001Sgshapiro#include <sm/time.h>
2390792Sgshapiro#include <sm/heap.h>
2490792Sgshapiro#include <sm/assert.h>
2590792Sgshapiro#include <sm/varargs.h>
2690792Sgshapiro#include <sm/io.h>
2790792Sgshapiro#include <sm/setjmp.h>
2890792Sgshapiro#include <sm/conf.h>
29110560Sgshapiro#include <sm/fdset.h>
3090792Sgshapiro#include "local.h"
3190792Sgshapiro
32141858Sgshapirostatic int	sm_stdsetmode __P((SM_FILE_T *, const int *));
33141858Sgshapirostatic int	sm_stdgetmode __P((SM_FILE_T *, int *));
34141858Sgshapiro
3590792Sgshapiro/*
3690792Sgshapiro**  Overall:
3790792Sgshapiro**  Small standard I/O/seek/close functions.
3890792Sgshapiro**  These maintain the `known seek offset' for seek optimization.
3990792Sgshapiro*/
4090792Sgshapiro
4190792Sgshapiro/*
4290792Sgshapiro**  SM_STDOPEN -- open a file with stdio behavior
4390792Sgshapiro**
4490792Sgshapiro**  Not associated with the system's stdio in libc.
4590792Sgshapiro**
4690792Sgshapiro**	Parameters:
4790792Sgshapiro**		fp -- file pointer to be associated with the open
4890792Sgshapiro**		info -- pathname of the file to be opened
4990792Sgshapiro**		flags -- indicates type of access methods
5090792Sgshapiro**		rpool -- ignored
5190792Sgshapiro**
5290792Sgshapiro**	Returns:
5390792Sgshapiro**		Failure: -1 and set errno
5490792Sgshapiro**		Success: 0 or greater (fd of file from open(2)).
5590792Sgshapiro**
5690792Sgshapiro*/
5790792Sgshapiro
5890792Sgshapiro/* ARGSUSED3 */
5990792Sgshapiroint
6090792Sgshapirosm_stdopen(fp, info, flags, rpool)
6190792Sgshapiro	SM_FILE_T *fp;
6290792Sgshapiro	const void *info;
6390792Sgshapiro	int flags;
6490792Sgshapiro	const void *rpool;
6590792Sgshapiro{
6690792Sgshapiro	char *path = (char *) info;
6790792Sgshapiro	int oflags;
6890792Sgshapiro
69120256Sgshapiro	switch (SM_IO_MODE(flags))
7090792Sgshapiro	{
7190792Sgshapiro	  case SM_IO_RDWR:
7290792Sgshapiro		oflags = O_RDWR;
7390792Sgshapiro		break;
7490792Sgshapiro	  case SM_IO_RDWRTR:
7590792Sgshapiro		oflags = O_RDWR | O_CREAT | O_TRUNC;
7690792Sgshapiro		break;
7790792Sgshapiro	  case SM_IO_RDONLY:
7890792Sgshapiro		oflags = O_RDONLY;
7990792Sgshapiro		break;
8090792Sgshapiro	  case SM_IO_WRONLY:
8190792Sgshapiro		oflags = O_WRONLY | O_CREAT | O_TRUNC;
8290792Sgshapiro		break;
8390792Sgshapiro	  case SM_IO_APPEND:
8490792Sgshapiro		oflags = O_APPEND | O_WRONLY | O_CREAT;
8590792Sgshapiro		break;
8690792Sgshapiro	  case SM_IO_APPENDRW:
8790792Sgshapiro		oflags = O_APPEND | O_RDWR | O_CREAT;
8890792Sgshapiro		break;
8990792Sgshapiro	  default:
9090792Sgshapiro		errno = EINVAL;
9190792Sgshapiro		return -1;
9290792Sgshapiro	}
93120256Sgshapiro#ifdef O_BINARY
94120256Sgshapiro	if (SM_IS_BINARY(flags))
95120256Sgshapiro		oflags |= O_BINARY;
96120256Sgshapiro#endif /* O_BINARY */
9790792Sgshapiro	fp->f_file = open(path, oflags,
9890792Sgshapiro			  S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
9990792Sgshapiro	if (fp->f_file < 0)
10090792Sgshapiro		return -1; /* errno set by open() */
10190792Sgshapiro
10290792Sgshapiro	if (oflags & O_APPEND)
10390792Sgshapiro		(void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
10490792Sgshapiro
10590792Sgshapiro	return fp->f_file;
10690792Sgshapiro}
10790792Sgshapiro
10890792Sgshapiro/*
10990792Sgshapiro**  SM_STDREAD -- read from the file
11090792Sgshapiro**
11190792Sgshapiro**	Parameters:
11290792Sgshapiro**		fp -- file pointer to read from
11390792Sgshapiro**		buf -- location to place read data
11490792Sgshapiro**		n -- number of bytes to read
11590792Sgshapiro**
11690792Sgshapiro**	Returns:
11790792Sgshapiro**		Failure: -1 and sets errno
11890792Sgshapiro**		Success: number of bytes read
11990792Sgshapiro**
12090792Sgshapiro**	Side Effects:
12190792Sgshapiro**		Updates internal offset into file.
12290792Sgshapiro*/
12390792Sgshapiro
12490792Sgshapirossize_t
12590792Sgshapirosm_stdread(fp, buf, n)
12690792Sgshapiro	SM_FILE_T *fp;
12790792Sgshapiro	char *buf;
12890792Sgshapiro	size_t n;
12990792Sgshapiro{
13090792Sgshapiro	register int ret;
13190792Sgshapiro
13290792Sgshapiro	ret = read(fp->f_file, buf, n);
13390792Sgshapiro
13490792Sgshapiro	/* if the read succeeded, update the current offset */
13590792Sgshapiro	if (ret > 0)
13690792Sgshapiro		fp->f_lseekoff += ret;
13790792Sgshapiro	return ret;
13890792Sgshapiro}
13990792Sgshapiro
14090792Sgshapiro/*
14190792Sgshapiro**  SM_STDWRITE -- write to the file
14290792Sgshapiro**
14390792Sgshapiro**	Parameters:
14490792Sgshapiro**		fp -- file pointer ro write to
14590792Sgshapiro**		buf -- location of data to be written
14690792Sgshapiro**		n - number of bytes to write
14790792Sgshapiro**
14890792Sgshapiro**	Returns:
14990792Sgshapiro**		Failure: -1 and sets errno
15090792Sgshapiro**		Success: number of bytes written
15190792Sgshapiro*/
15290792Sgshapiro
15390792Sgshapirossize_t
15490792Sgshapirosm_stdwrite(fp, buf, n)
15590792Sgshapiro	SM_FILE_T *fp;
15690792Sgshapiro	char const *buf;
15790792Sgshapiro	size_t n;
15890792Sgshapiro{
15990792Sgshapiro	return write(fp->f_file, buf, n);
16090792Sgshapiro}
16190792Sgshapiro
16290792Sgshapiro/*
16390792Sgshapiro**  SM_STDSEEK -- set the file offset position
16490792Sgshapiro**
16590792Sgshapiro**	Parmeters:
16690792Sgshapiro**		fp -- file pointer to position
16790792Sgshapiro**		offset -- how far to position from "base" (set by 'whence')
16890792Sgshapiro**		whence -- indicates where the "base" of the 'offset' to start
16990792Sgshapiro**
17090792Sgshapiro**	Results:
17190792Sgshapiro**		Failure: -1 and sets errno
17290792Sgshapiro**		Success: the current offset
17390792Sgshapiro**
17490792Sgshapiro**	Side Effects:
17590792Sgshapiro**		Updates the internal value of the offset.
17690792Sgshapiro*/
17790792Sgshapiro
17890792Sgshapirooff_t
17990792Sgshapirosm_stdseek(fp, offset, whence)
18090792Sgshapiro	SM_FILE_T *fp;
18190792Sgshapiro	off_t offset;
18290792Sgshapiro	int whence;
18390792Sgshapiro{
18490792Sgshapiro	register off_t ret;
18590792Sgshapiro
18690792Sgshapiro	ret = lseek(fp->f_file, (off_t) offset, whence);
18790792Sgshapiro	if (ret != (off_t) -1)
18890792Sgshapiro		fp->f_lseekoff = ret;
18990792Sgshapiro	return ret;
19090792Sgshapiro}
19190792Sgshapiro
19290792Sgshapiro/*
19390792Sgshapiro**  SM_STDCLOSE -- close the file
19490792Sgshapiro**
19590792Sgshapiro**	Parameters:
19690792Sgshapiro**		fp -- the file pointer to close
19790792Sgshapiro**
19890792Sgshapiro**	Returns:
19990792Sgshapiro**		Success: 0 (zero)
20090792Sgshapiro**		Failure: -1 and sets errno
20190792Sgshapiro*/
20290792Sgshapiro
20390792Sgshapiroint
20490792Sgshapirosm_stdclose(fp)
20590792Sgshapiro	SM_FILE_T *fp;
20690792Sgshapiro{
20790792Sgshapiro	return close(fp->f_file);
20890792Sgshapiro}
20990792Sgshapiro
21090792Sgshapiro/*
21190792Sgshapiro**  SM_STDSETMODE -- set the access mode for the file
21290792Sgshapiro**
21390792Sgshapiro**  Called by sm_stdsetinfo().
21490792Sgshapiro**
21590792Sgshapiro**	Parameters:
21690792Sgshapiro**		fp -- file pointer
21790792Sgshapiro**		mode -- new mode to set the file access to
21890792Sgshapiro**
21990792Sgshapiro**	Results:
22090792Sgshapiro**		Success: 0 (zero);
22190792Sgshapiro**		Failure: -1 and sets errno
22290792Sgshapiro*/
22390792Sgshapiro
224157001Sgshapirostatic int
22590792Sgshapirosm_stdsetmode(fp, mode)
22690792Sgshapiro	SM_FILE_T *fp;
22790792Sgshapiro	const int *mode;
22890792Sgshapiro{
22990792Sgshapiro	int flags = 0;
23090792Sgshapiro
231120256Sgshapiro	switch (SM_IO_MODE(*mode))
23290792Sgshapiro	{
23390792Sgshapiro	  case SM_IO_RDWR:
23490792Sgshapiro		flags |= SMRW;
23590792Sgshapiro		break;
23690792Sgshapiro	  case SM_IO_RDONLY:
23790792Sgshapiro		flags |= SMRD;
23890792Sgshapiro		break;
23990792Sgshapiro	  case SM_IO_WRONLY:
24090792Sgshapiro		flags |= SMWR;
24190792Sgshapiro		break;
24290792Sgshapiro	  case SM_IO_APPEND:
24390792Sgshapiro	  default:
24490792Sgshapiro		errno = EINVAL;
24590792Sgshapiro		return -1;
24690792Sgshapiro	}
24790792Sgshapiro	fp->f_flags = fp->f_flags & ~SMMODEMASK;
24890792Sgshapiro	fp->f_flags |= flags;
24990792Sgshapiro	return 0;
25090792Sgshapiro}
25190792Sgshapiro
25290792Sgshapiro/*
25390792Sgshapiro**  SM_STDGETMODE -- for getinfo determine open mode
25490792Sgshapiro**
25590792Sgshapiro**  Called by sm_stdgetinfo().
25690792Sgshapiro**
25790792Sgshapiro**	Parameters:
25890792Sgshapiro**		fp -- the file mode being determined
25990792Sgshapiro**		mode -- internal mode to map to external value
26090792Sgshapiro**
26190792Sgshapiro**	Results:
26290792Sgshapiro**		Failure: -1 and sets errno
26390792Sgshapiro**		Success: external mode value
26490792Sgshapiro*/
26590792Sgshapiro
266141858Sgshapirostatic int
26790792Sgshapirosm_stdgetmode(fp, mode)
26890792Sgshapiro	SM_FILE_T *fp;
26990792Sgshapiro	int *mode;
27090792Sgshapiro{
27190792Sgshapiro	switch (fp->f_flags & SMMODEMASK)
27290792Sgshapiro	{
27390792Sgshapiro	  case SMRW:
27490792Sgshapiro		*mode = SM_IO_RDWR;
27590792Sgshapiro		break;
27690792Sgshapiro	  case SMRD:
27790792Sgshapiro		*mode = SM_IO_RDONLY;
27890792Sgshapiro		break;
27990792Sgshapiro	  case SMWR:
28090792Sgshapiro		*mode = SM_IO_WRONLY;
28190792Sgshapiro		break;
28290792Sgshapiro	  default:
28390792Sgshapiro		errno = EINVAL;
28490792Sgshapiro		return -1;
28590792Sgshapiro	}
28690792Sgshapiro	return 0;
28790792Sgshapiro}
28890792Sgshapiro
28990792Sgshapiro/*
29090792Sgshapiro**  SM_STDSETINFO -- set/modify information for a file
29190792Sgshapiro**
29290792Sgshapiro**	Parameters:
29390792Sgshapiro**		fp -- file to set info for
29490792Sgshapiro**		what -- type of info to set
29590792Sgshapiro**		valp -- location of data used for setting
29690792Sgshapiro**
29790792Sgshapiro**	Returns:
29890792Sgshapiro**		Failure: -1 and sets errno
29990792Sgshapiro**		Success: >=0
30090792Sgshapiro*/
30190792Sgshapiro
30290792Sgshapiroint
30390792Sgshapirosm_stdsetinfo(fp, what, valp)
30490792Sgshapiro	SM_FILE_T *fp;
30590792Sgshapiro	int what;
30690792Sgshapiro	void *valp;
30790792Sgshapiro{
30890792Sgshapiro	switch (what)
30990792Sgshapiro	{
31090792Sgshapiro	  case SM_IO_WHAT_MODE:
31190792Sgshapiro		return sm_stdsetmode(fp, (const int *)valp);
31290792Sgshapiro
31390792Sgshapiro	  default:
31490792Sgshapiro		errno = EINVAL;
31590792Sgshapiro		return -1;
31690792Sgshapiro	}
31790792Sgshapiro}
31890792Sgshapiro
31990792Sgshapiro/*
32090792Sgshapiro**  SM_GETINFO -- get information about the open file
32190792Sgshapiro**
32290792Sgshapiro**	Parameters:
32390792Sgshapiro**		fp -- file to get info for
32490792Sgshapiro**		what -- type of info to get
32590792Sgshapiro**		valp -- location to place found info
32690792Sgshapiro**
32790792Sgshapiro**	Returns:
32890792Sgshapiro**		Success: may or may not place info in 'valp' depending
32990792Sgshapiro**			on 'what' value, and returns values >=0. Return
33090792Sgshapiro**			value may be the obtained info
33190792Sgshapiro**		Failure: -1 and sets errno
33290792Sgshapiro*/
33390792Sgshapiro
33490792Sgshapiroint
33590792Sgshapirosm_stdgetinfo(fp, what, valp)
33690792Sgshapiro	SM_FILE_T *fp;
33790792Sgshapiro	int what;
33890792Sgshapiro	void *valp;
33990792Sgshapiro{
34090792Sgshapiro	switch (what)
34190792Sgshapiro	{
34290792Sgshapiro	  case SM_IO_WHAT_MODE:
34390792Sgshapiro		return sm_stdgetmode(fp, (int *)valp);
34490792Sgshapiro
34590792Sgshapiro	  case SM_IO_WHAT_FD:
34690792Sgshapiro		return fp->f_file;
34790792Sgshapiro
34894334Sgshapiro	  case SM_IO_WHAT_SIZE:
34994334Sgshapiro	  {
35094334Sgshapiro		  struct stat st;
35194334Sgshapiro
35294334Sgshapiro		  if (fstat(fp->f_file, &st) == 0)
35394334Sgshapiro			  return st.st_size;
35494334Sgshapiro		  else
35594334Sgshapiro			  return -1;
35694334Sgshapiro	  }
35794334Sgshapiro
35890792Sgshapiro	  case SM_IO_IS_READABLE:
35994334Sgshapiro	  {
36094334Sgshapiro		  fd_set readfds;
36194334Sgshapiro		  struct timeval timeout;
36290792Sgshapiro
363110560Sgshapiro		  if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
364110560Sgshapiro		  {
365110560Sgshapiro			  errno = EINVAL;
366110560Sgshapiro			  return -1;
367110560Sgshapiro		  }
36894334Sgshapiro		  FD_ZERO(&readfds);
36994334Sgshapiro		  SM_FD_SET(fp->f_file, &readfds);
37094334Sgshapiro		  timeout.tv_sec = 0;
37194334Sgshapiro		  timeout.tv_usec = 0;
37294334Sgshapiro		  if (select(fp->f_file + 1, FDSET_CAST &readfds,
37394334Sgshapiro			     NULL, NULL, &timeout) > 0 &&
37494334Sgshapiro		      SM_FD_ISSET(fp->f_file, &readfds))
37594334Sgshapiro			  return 1;
37694334Sgshapiro		  return 0;
37794334Sgshapiro	  }
37890792Sgshapiro
37990792Sgshapiro	  default:
38090792Sgshapiro		errno = EINVAL;
38190792Sgshapiro		return -1;
38290792Sgshapiro	}
38390792Sgshapiro}
38490792Sgshapiro
38590792Sgshapiro/*
38694334Sgshapiro**  SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
38790792Sgshapiro**
38890792Sgshapiro**	I/O function to handle fdopen() stdio equivalence. The rest of
38990792Sgshapiro**	the functions are the same as the sm_stdopen() above.
39090792Sgshapiro**
39190792Sgshapiro**	Parameters:
39290792Sgshapiro**		fp -- the file pointer to be associated with the open
39394334Sgshapiro**		name -- the primitive file descriptor for association
39490792Sgshapiro**		flags -- indicates type of access methods
39590792Sgshapiro**		rpool -- ignored
39690792Sgshapiro**
39790792Sgshapiro**	Results:
39894334Sgshapiro**		Success: primitive file descriptor value
39990792Sgshapiro**		Failure: -1 and sets errno
40090792Sgshapiro*/
40190792Sgshapiro
40290792Sgshapiro/* ARGSUSED3 */
40390792Sgshapiroint
40490792Sgshapirosm_stdfdopen(fp, info, flags, rpool)
40590792Sgshapiro	SM_FILE_T *fp;
40690792Sgshapiro	const void *info;
40790792Sgshapiro	int flags;
40890792Sgshapiro	const void *rpool;
40990792Sgshapiro{
41090792Sgshapiro	int oflags, tmp, fdflags, fd = *((int *) info);
41190792Sgshapiro
412120256Sgshapiro	switch (SM_IO_MODE(flags))
41390792Sgshapiro	{
41490792Sgshapiro	  case SM_IO_RDWR:
41590792Sgshapiro		oflags = O_RDWR | O_CREAT;
41690792Sgshapiro		break;
41790792Sgshapiro	  case SM_IO_RDONLY:
41890792Sgshapiro		oflags = O_RDONLY;
41990792Sgshapiro		break;
42090792Sgshapiro	  case SM_IO_WRONLY:
42190792Sgshapiro		oflags = O_WRONLY | O_CREAT | O_TRUNC;
42290792Sgshapiro		break;
42390792Sgshapiro	  case SM_IO_APPEND:
42490792Sgshapiro		oflags = O_APPEND | O_WRONLY | O_CREAT;
42590792Sgshapiro		break;
42690792Sgshapiro	  case SM_IO_APPENDRW:
42790792Sgshapiro		oflags = O_APPEND | O_RDWR | O_CREAT;
42890792Sgshapiro		break;
42990792Sgshapiro	  default:
43090792Sgshapiro		errno = EINVAL;
43190792Sgshapiro		return -1;
43290792Sgshapiro	}
433120256Sgshapiro#ifdef O_BINARY
434120256Sgshapiro	if (SM_IS_BINARY(flags))
435120256Sgshapiro		oflags |= O_BINARY;
436120256Sgshapiro#endif /* O_BINARY */
43790792Sgshapiro
43890792Sgshapiro	/* Make sure the mode the user wants is a subset of the actual mode. */
43990792Sgshapiro	if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
44090792Sgshapiro		return -1;
44190792Sgshapiro	tmp = fdflags & O_ACCMODE;
44290792Sgshapiro	if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
44390792Sgshapiro	{
44490792Sgshapiro		errno = EINVAL;
44590792Sgshapiro		return -1;
44690792Sgshapiro	}
44790792Sgshapiro	fp->f_file = fd;
44890792Sgshapiro	if (oflags & O_APPEND)
44990792Sgshapiro		(void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
45090792Sgshapiro	return fp->f_file;
45190792Sgshapiro}
45290792Sgshapiro
45390792Sgshapiro/*
45490792Sgshapiro**  SM_IO_FOPEN -- open a file
45590792Sgshapiro**
45690792Sgshapiro**	Same interface and semantics as the open() system call,
45790792Sgshapiro**	except that it returns SM_FILE_T* instead of a file descriptor.
45890792Sgshapiro**
45990792Sgshapiro**	Parameters:
46090792Sgshapiro**		pathname -- path of file to open
46190792Sgshapiro**		flags -- flags controlling the open
46290792Sgshapiro**		...  -- option "mode" for opening the file
46390792Sgshapiro**
46490792Sgshapiro**	Returns:
46590792Sgshapiro**		Raises an exception on heap exhaustion.
46690792Sgshapiro**		Returns NULL and sets errno if open() fails.
46790792Sgshapiro**		Returns an SM_FILE_T pointer on success.
46890792Sgshapiro*/
46990792Sgshapiro
47090792SgshapiroSM_FILE_T *
47190792Sgshapiro#if SM_VA_STD
47290792Sgshapirosm_io_fopen(char *pathname, int flags, ...)
47390792Sgshapiro#else /* SM_VA_STD */
47490792Sgshapirosm_io_fopen(pathname, flags, va_alist)
47590792Sgshapiro	char *pathname;
47690792Sgshapiro	int flags;
47790792Sgshapiro	va_dcl
47890792Sgshapiro#endif /* SM_VA_STD */
47990792Sgshapiro{
48090792Sgshapiro	MODE_T mode;
48190792Sgshapiro	SM_FILE_T *fp;
48290792Sgshapiro	int ioflags;
48390792Sgshapiro
48490792Sgshapiro	if (flags & O_CREAT)
48590792Sgshapiro	{
48690792Sgshapiro		SM_VA_LOCAL_DECL
48790792Sgshapiro
48890792Sgshapiro		SM_VA_START(ap, flags);
48990792Sgshapiro		mode = (MODE_T) SM_VA_ARG(ap, int);
49090792Sgshapiro		SM_VA_END(ap);
49190792Sgshapiro	}
49290792Sgshapiro	else
49390792Sgshapiro		mode = 0;
49490792Sgshapiro
49590792Sgshapiro	switch (flags & O_ACCMODE)
49690792Sgshapiro	{
49790792Sgshapiro	  case O_RDONLY:
49890792Sgshapiro		ioflags = SMRD;
49990792Sgshapiro		break;
50090792Sgshapiro	  case O_WRONLY:
50190792Sgshapiro		ioflags = SMWR;
50290792Sgshapiro		break;
50390792Sgshapiro	  case O_RDWR:
50490792Sgshapiro		ioflags = SMRW;
50590792Sgshapiro		break;
50690792Sgshapiro	  default:
50790792Sgshapiro		sm_abort("sm_io_fopen: bad flags 0%o", flags);
50890792Sgshapiro	}
50990792Sgshapiro
51090792Sgshapiro	fp = sm_fp(SmFtStdio, ioflags, NULL);
51190792Sgshapiro	fp->f_file = open(pathname, flags, mode);
51290792Sgshapiro	if (fp->f_file == -1)
51390792Sgshapiro	{
51490792Sgshapiro		fp->f_flags = 0;
51590792Sgshapiro		fp->sm_magic = NULL;
51690792Sgshapiro		return NULL;
51790792Sgshapiro	}
51890792Sgshapiro	return fp;
51990792Sgshapiro}
520