xref: /freebsd/contrib/sendmail/libsm/smstdio.c (revision ee7b0571c2c18bdec848ed2044223cc88db29bd8)
140266059SGregory Neil Shapiro /*
25dd76dd0SGregory Neil Shapiro  * Copyright (c) 2000-2002, 2004 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro  *      All rights reserved.
440266059SGregory Neil Shapiro  *
540266059SGregory Neil Shapiro  * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro  * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro  * the sendmail distribution.
840266059SGregory Neil Shapiro  */
940266059SGregory Neil Shapiro 
1040266059SGregory Neil Shapiro #include <sm/gen.h>
11*4313cc83SGregory Neil Shapiro SM_IDSTR(id, "@(#)$Id: smstdio.c,v 1.35 2013-11-22 20:51:43 ca Exp $")
1240266059SGregory Neil Shapiro #include <unistd.h>
1340266059SGregory Neil Shapiro #include <stdio.h>
1440266059SGregory Neil Shapiro #include <fcntl.h>
1540266059SGregory Neil Shapiro #include <errno.h>
16605302a5SGregory Neil Shapiro #include <sys/stat.h>
1740266059SGregory Neil Shapiro #include <sm/assert.h>
1840266059SGregory Neil Shapiro #include <sm/io.h>
1940266059SGregory Neil Shapiro #include <sm/string.h>
2040266059SGregory Neil Shapiro #include "local.h"
2140266059SGregory Neil Shapiro 
22b6bacd31SGregory Neil Shapiro static void	setup __P((SM_FILE_T *));
23b6bacd31SGregory Neil Shapiro 
2440266059SGregory Neil Shapiro /*
2540266059SGregory Neil Shapiro ** Overall:
2640266059SGregory Neil Shapiro **	This is a file type which implements a layer on top of the system
2740266059SGregory Neil Shapiro **	stdio. fp->f_cookie is the FILE* of stdio. The cookie may be
2840266059SGregory Neil Shapiro **	"bound late" because of the manner which Linux implements stdio.
2940266059SGregory Neil Shapiro **	When binding late  (when fp->f_cookie==NULL) then the value of
3040266059SGregory Neil Shapiro **	fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or
3140266059SGregory Neil Shapiro **	stderr.
3240266059SGregory Neil Shapiro */
3340266059SGregory Neil Shapiro 
3440266059SGregory Neil Shapiro /*
3540266059SGregory Neil Shapiro **  SM_STDIOOPEN -- open a file to system stdio implementation
3640266059SGregory Neil Shapiro **
3740266059SGregory Neil Shapiro **	Parameters:
3840266059SGregory Neil Shapiro **		fp -- file pointer assign for this open
3940266059SGregory Neil Shapiro **		info -- info about file to open
4040266059SGregory Neil Shapiro **		flags -- indicating method of opening
4140266059SGregory Neil Shapiro **		rpool -- ignored
4240266059SGregory Neil Shapiro **
4340266059SGregory Neil Shapiro **	Returns:
4440266059SGregory Neil Shapiro **		Failure: -1
4540266059SGregory Neil Shapiro **		Success: 0 (zero)
4640266059SGregory Neil Shapiro */
4740266059SGregory Neil Shapiro 
4840266059SGregory Neil Shapiro /* ARGSUSED3 */
4940266059SGregory Neil Shapiro int
sm_stdioopen(fp,info,flags,rpool)5040266059SGregory Neil Shapiro sm_stdioopen(fp, info, flags, rpool)
5140266059SGregory Neil Shapiro 	SM_FILE_T *fp;
5240266059SGregory Neil Shapiro 	const void *info;
5340266059SGregory Neil Shapiro 	int flags;
5440266059SGregory Neil Shapiro 	const void *rpool;
5540266059SGregory Neil Shapiro {
5640266059SGregory Neil Shapiro 	register FILE *s;
5740266059SGregory Neil Shapiro 	char *stdiomode;
5840266059SGregory Neil Shapiro 
5940266059SGregory Neil Shapiro 	switch (flags)
6040266059SGregory Neil Shapiro 	{
6140266059SGregory Neil Shapiro 	  case SM_IO_RDONLY:
6240266059SGregory Neil Shapiro 		stdiomode = "r";
6340266059SGregory Neil Shapiro 		break;
6440266059SGregory Neil Shapiro 	  case SM_IO_WRONLY:
6540266059SGregory Neil Shapiro 		stdiomode = "w";
6640266059SGregory Neil Shapiro 		break;
6740266059SGregory Neil Shapiro 	  case SM_IO_APPEND:
6840266059SGregory Neil Shapiro 		stdiomode = "a";
6940266059SGregory Neil Shapiro 		break;
7040266059SGregory Neil Shapiro 	  case SM_IO_APPENDRW:
7140266059SGregory Neil Shapiro 		stdiomode = "a+";
7240266059SGregory Neil Shapiro 		break;
73a7ec597cSGregory Neil Shapiro #if SM_IO_BINARY != 0
74a7ec597cSGregory Neil Shapiro 	  case SM_IO_RDONLY_B:
75a7ec597cSGregory Neil Shapiro 		stdiomode = "rb";
76a7ec597cSGregory Neil Shapiro 		break;
77a7ec597cSGregory Neil Shapiro 	  case SM_IO_WRONLY_B:
78a7ec597cSGregory Neil Shapiro 		stdiomode = "wb";
79a7ec597cSGregory Neil Shapiro 		break;
80a7ec597cSGregory Neil Shapiro 	  case SM_IO_APPEND_B:
81a7ec597cSGregory Neil Shapiro 		stdiomode = "ab";
82a7ec597cSGregory Neil Shapiro 		break;
83a7ec597cSGregory Neil Shapiro 	  case SM_IO_APPENDRW_B:
84a7ec597cSGregory Neil Shapiro 		stdiomode = "a+b";
85a7ec597cSGregory Neil Shapiro 		break;
86a7ec597cSGregory Neil Shapiro 	  case SM_IO_RDWR_B:
87a7ec597cSGregory Neil Shapiro 		stdiomode = "r+b";
88a7ec597cSGregory Neil Shapiro 		break;
89a7ec597cSGregory Neil Shapiro #endif /* SM_IO_BINARY != 0 */
9040266059SGregory Neil Shapiro 	  case SM_IO_RDWR:
9140266059SGregory Neil Shapiro 	  default:
9240266059SGregory Neil Shapiro 		stdiomode = "r+";
9340266059SGregory Neil Shapiro 		break;
9440266059SGregory Neil Shapiro 	}
9540266059SGregory Neil Shapiro 
9640266059SGregory Neil Shapiro 	if ((s = fopen((char *)info, stdiomode)) == NULL)
9740266059SGregory Neil Shapiro 		return -1;
9840266059SGregory Neil Shapiro 	fp->f_cookie = s;
9940266059SGregory Neil Shapiro 	return 0;
10040266059SGregory Neil Shapiro }
10140266059SGregory Neil Shapiro 
10240266059SGregory Neil Shapiro /*
10340266059SGregory Neil Shapiro **  SETUP -- assign file type cookie when not already assigned
10440266059SGregory Neil Shapiro **
10540266059SGregory Neil Shapiro **	Parameters:
10640266059SGregory Neil Shapiro **		fp - the file pointer to get the cookie assigned
10740266059SGregory Neil Shapiro **
10840266059SGregory Neil Shapiro **	Return:
10940266059SGregory Neil Shapiro **		none.
11040266059SGregory Neil Shapiro */
11140266059SGregory Neil Shapiro 
11240266059SGregory Neil Shapiro static void
setup(fp)11340266059SGregory Neil Shapiro setup(fp)
11440266059SGregory Neil Shapiro 	SM_FILE_T *fp;
11540266059SGregory Neil Shapiro {
11640266059SGregory Neil Shapiro 	if (fp->f_cookie == NULL)
11740266059SGregory Neil Shapiro 	{
11840266059SGregory Neil Shapiro 		switch (fp->f_ival)
11940266059SGregory Neil Shapiro 		{
12040266059SGregory Neil Shapiro 		  case 0:
12140266059SGregory Neil Shapiro 			fp->f_cookie = stdin;
12240266059SGregory Neil Shapiro 			break;
12340266059SGregory Neil Shapiro 		  case 1:
12440266059SGregory Neil Shapiro 			fp->f_cookie = stdout;
12540266059SGregory Neil Shapiro 			break;
12640266059SGregory Neil Shapiro 		  case 2:
12740266059SGregory Neil Shapiro 			fp->f_cookie = stderr;
12840266059SGregory Neil Shapiro 			break;
12940266059SGregory Neil Shapiro 		  default:
13040266059SGregory Neil Shapiro 			sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival);
13140266059SGregory Neil Shapiro 			break;
13240266059SGregory Neil Shapiro 		}
13340266059SGregory Neil Shapiro 	}
13440266059SGregory Neil Shapiro }
13540266059SGregory Neil Shapiro 
13640266059SGregory Neil Shapiro /*
13740266059SGregory Neil Shapiro **  SM_STDIOREAD -- read from the file
13840266059SGregory Neil Shapiro **
13940266059SGregory Neil Shapiro **	Parameters:
14040266059SGregory Neil Shapiro **		fp -- the file pointer
14140266059SGregory Neil Shapiro **		buf -- location to place the read data
14240266059SGregory Neil Shapiro **		n - number of bytes to read
14340266059SGregory Neil Shapiro **
14440266059SGregory Neil Shapiro **	Returns:
14540266059SGregory Neil Shapiro **		result from fread().
14640266059SGregory Neil Shapiro */
14740266059SGregory Neil Shapiro 
14840266059SGregory Neil Shapiro ssize_t
sm_stdioread(fp,buf,n)14940266059SGregory Neil Shapiro sm_stdioread(fp, buf, n)
15040266059SGregory Neil Shapiro 	SM_FILE_T *fp;
15140266059SGregory Neil Shapiro 	char *buf;
15240266059SGregory Neil Shapiro 	size_t n;
15340266059SGregory Neil Shapiro {
15440266059SGregory Neil Shapiro 	register FILE *s;
15540266059SGregory Neil Shapiro 
15640266059SGregory Neil Shapiro 	if (fp->f_cookie == NULL)
15740266059SGregory Neil Shapiro 		setup(fp);
15840266059SGregory Neil Shapiro 	s = fp->f_cookie;
15940266059SGregory Neil Shapiro 	return fread(buf, 1, n, s);
16040266059SGregory Neil Shapiro }
16140266059SGregory Neil Shapiro 
16240266059SGregory Neil Shapiro /*
16340266059SGregory Neil Shapiro **  SM_STDIOWRITE -- write to the file
16440266059SGregory Neil Shapiro **
16540266059SGregory Neil Shapiro **	Parameters:
16640266059SGregory Neil Shapiro **		fp -- the file pointer
16740266059SGregory Neil Shapiro **		buf -- location of data to write
16840266059SGregory Neil Shapiro **		n - number of bytes to write
16940266059SGregory Neil Shapiro **
17040266059SGregory Neil Shapiro **	Returns:
17140266059SGregory Neil Shapiro **		result from fwrite().
17240266059SGregory Neil Shapiro */
17340266059SGregory Neil Shapiro 
17440266059SGregory Neil Shapiro ssize_t
sm_stdiowrite(fp,buf,n)17540266059SGregory Neil Shapiro sm_stdiowrite(fp, buf, n)
17640266059SGregory Neil Shapiro 	SM_FILE_T *fp;
17740266059SGregory Neil Shapiro 	char const *buf;
17840266059SGregory Neil Shapiro 	size_t n;
17940266059SGregory Neil Shapiro {
18040266059SGregory Neil Shapiro 	register FILE *s;
18140266059SGregory Neil Shapiro 
18240266059SGregory Neil Shapiro 	if (fp->f_cookie == NULL)
18340266059SGregory Neil Shapiro 		setup(fp);
18440266059SGregory Neil Shapiro 	s = fp->f_cookie;
18540266059SGregory Neil Shapiro 	return fwrite(buf, 1, n, s);
18640266059SGregory Neil Shapiro }
18740266059SGregory Neil Shapiro 
18840266059SGregory Neil Shapiro /*
18940266059SGregory Neil Shapiro **  SM_STDIOSEEK -- set position within file
19040266059SGregory Neil Shapiro **
19140266059SGregory Neil Shapiro **	Parameters:
19240266059SGregory Neil Shapiro **		fp -- the file pointer
19340266059SGregory Neil Shapiro **		offset -- new location based on 'whence'
19440266059SGregory Neil Shapiro **		whence -- indicates "base" for 'offset'
19540266059SGregory Neil Shapiro **
19640266059SGregory Neil Shapiro **	Returns:
19740266059SGregory Neil Shapiro **		result from fseek().
19840266059SGregory Neil Shapiro */
19940266059SGregory Neil Shapiro 
20040266059SGregory Neil Shapiro off_t
sm_stdioseek(fp,offset,whence)20140266059SGregory Neil Shapiro sm_stdioseek(fp, offset, whence)
20240266059SGregory Neil Shapiro 	SM_FILE_T *fp;
20340266059SGregory Neil Shapiro 	off_t offset;
20440266059SGregory Neil Shapiro 	int whence;
20540266059SGregory Neil Shapiro {
20640266059SGregory Neil Shapiro 	register FILE *s;
20740266059SGregory Neil Shapiro 
20840266059SGregory Neil Shapiro 	if (fp->f_cookie == NULL)
20940266059SGregory Neil Shapiro 		setup(fp);
21040266059SGregory Neil Shapiro 	s = fp->f_cookie;
21140266059SGregory Neil Shapiro 	return fseek(s, offset, whence);
21240266059SGregory Neil Shapiro }
21340266059SGregory Neil Shapiro 
21440266059SGregory Neil Shapiro /*
21540266059SGregory Neil Shapiro **  SM_STDIOCLOSE -- close the file
21640266059SGregory Neil Shapiro **
21740266059SGregory Neil Shapiro **	Parameters:
21840266059SGregory Neil Shapiro **		fp -- close file pointer
21940266059SGregory Neil Shapiro **
22040266059SGregory Neil Shapiro **	Return:
22140266059SGregory Neil Shapiro **		status from fclose()
22240266059SGregory Neil Shapiro */
22340266059SGregory Neil Shapiro 
22440266059SGregory Neil Shapiro int
sm_stdioclose(fp)22540266059SGregory Neil Shapiro sm_stdioclose(fp)
22640266059SGregory Neil Shapiro 	SM_FILE_T *fp;
22740266059SGregory Neil Shapiro {
22840266059SGregory Neil Shapiro 	register FILE *s;
22940266059SGregory Neil Shapiro 
23040266059SGregory Neil Shapiro 	if (fp->f_cookie == NULL)
23140266059SGregory Neil Shapiro 		setup(fp);
23240266059SGregory Neil Shapiro 	s = fp->f_cookie;
23340266059SGregory Neil Shapiro 	return fclose(s);
23440266059SGregory Neil Shapiro }
23540266059SGregory Neil Shapiro 
23640266059SGregory Neil Shapiro /*
23740266059SGregory Neil Shapiro **  SM_STDIOSETINFO -- set info for this open file
23840266059SGregory Neil Shapiro **
23940266059SGregory Neil Shapiro **	Parameters:
24040266059SGregory Neil Shapiro **		fp -- the file pointer
24140266059SGregory Neil Shapiro **		what -- type of information setting
24240266059SGregory Neil Shapiro **		valp -- memory location of info to set
24340266059SGregory Neil Shapiro **
24440266059SGregory Neil Shapiro **	Return:
24540266059SGregory Neil Shapiro **		Failure: -1 and sets errno
24640266059SGregory Neil Shapiro **		Success: none (currently).
24740266059SGregory Neil Shapiro */
24840266059SGregory Neil Shapiro 
24940266059SGregory Neil Shapiro /* ARGSUSED2 */
25040266059SGregory Neil Shapiro int
sm_stdiosetinfo(fp,what,valp)25140266059SGregory Neil Shapiro sm_stdiosetinfo(fp, what, valp)
25240266059SGregory Neil Shapiro 	SM_FILE_T *fp;
25340266059SGregory Neil Shapiro 	int what;
25440266059SGregory Neil Shapiro 	void *valp;
25540266059SGregory Neil Shapiro {
25640266059SGregory Neil Shapiro 	switch (what)
25740266059SGregory Neil Shapiro 	{
25840266059SGregory Neil Shapiro 	  case SM_IO_WHAT_MODE:
25940266059SGregory Neil Shapiro 	  default:
26040266059SGregory Neil Shapiro 		errno = EINVAL;
26140266059SGregory Neil Shapiro 		return -1;
26240266059SGregory Neil Shapiro 	}
26340266059SGregory Neil Shapiro }
26440266059SGregory Neil Shapiro 
26540266059SGregory Neil Shapiro /*
26640266059SGregory Neil Shapiro **  SM_STDIOGETINFO -- get info for this open file
26740266059SGregory Neil Shapiro **
26840266059SGregory Neil Shapiro **	Parameters:
26940266059SGregory Neil Shapiro **		fp -- the file pointer
27040266059SGregory Neil Shapiro **		what -- type of information request
27140266059SGregory Neil Shapiro **		valp -- memory location to place info
27240266059SGregory Neil Shapiro **
27340266059SGregory Neil Shapiro **	Return:
27440266059SGregory Neil Shapiro **		Failure: -1 and sets errno
27540266059SGregory Neil Shapiro **		Success: none (currently).
27640266059SGregory Neil Shapiro */
27740266059SGregory Neil Shapiro 
27840266059SGregory Neil Shapiro /* ARGSUSED2 */
27940266059SGregory Neil Shapiro int
sm_stdiogetinfo(fp,what,valp)28040266059SGregory Neil Shapiro sm_stdiogetinfo(fp, what, valp)
28140266059SGregory Neil Shapiro 	SM_FILE_T *fp;
28240266059SGregory Neil Shapiro 	int what;
28340266059SGregory Neil Shapiro 	void *valp;
28440266059SGregory Neil Shapiro {
28540266059SGregory Neil Shapiro 	switch (what)
28640266059SGregory Neil Shapiro 	{
287605302a5SGregory Neil Shapiro 	  case SM_IO_WHAT_SIZE:
288605302a5SGregory Neil Shapiro 	  {
289605302a5SGregory Neil Shapiro 		  int fd;
290605302a5SGregory Neil Shapiro 		  struct stat st;
291605302a5SGregory Neil Shapiro 
292605302a5SGregory Neil Shapiro 		  if (fp->f_cookie == NULL)
293605302a5SGregory Neil Shapiro 			  setup(fp);
294605302a5SGregory Neil Shapiro 		  fd = fileno((FILE *) fp->f_cookie);
295605302a5SGregory Neil Shapiro 		  if (fd < 0)
296605302a5SGregory Neil Shapiro 			  return -1;
297605302a5SGregory Neil Shapiro 		  if (fstat(fd, &st) == 0)
298605302a5SGregory Neil Shapiro 			  return st.st_size;
299605302a5SGregory Neil Shapiro 		  else
300605302a5SGregory Neil Shapiro 			  return -1;
301605302a5SGregory Neil Shapiro 	  }
302605302a5SGregory Neil Shapiro 
30340266059SGregory Neil Shapiro 	  case SM_IO_WHAT_MODE:
30440266059SGregory Neil Shapiro 	  default:
30540266059SGregory Neil Shapiro 		errno = EINVAL;
30640266059SGregory Neil Shapiro 		return -1;
30740266059SGregory Neil Shapiro 	}
30840266059SGregory Neil Shapiro }
30940266059SGregory Neil Shapiro 
31040266059SGregory Neil Shapiro /*
31140266059SGregory Neil Shapiro **  SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE
31240266059SGregory Neil Shapiro **
31340266059SGregory Neil Shapiro **	Parameters:
31440266059SGregory Neil Shapiro **		stream -- an open stdio stream, as returned by fopen()
31540266059SGregory Neil Shapiro **		mode -- the mode argument to fopen() which describes stream
31640266059SGregory Neil Shapiro **
31740266059SGregory Neil Shapiro **	Return:
31840266059SGregory Neil Shapiro **		On success, return a pointer to an SM_FILE object which
31940266059SGregory Neil Shapiro **		can be used for reading and writing 'stream'.
32040266059SGregory Neil Shapiro **		Abort if mode is gibberish or stream is bad.
32140266059SGregory Neil Shapiro **		Raise an exception if we can't allocate memory.
32240266059SGregory Neil Shapiro */
32340266059SGregory Neil Shapiro 
32440266059SGregory Neil Shapiro SM_FILE_T *
sm_io_stdioopen(stream,mode)32540266059SGregory Neil Shapiro sm_io_stdioopen(stream, mode)
32640266059SGregory Neil Shapiro 	FILE *stream;
32740266059SGregory Neil Shapiro 	char *mode;
32840266059SGregory Neil Shapiro {
32940266059SGregory Neil Shapiro 	int fd;
33040266059SGregory Neil Shapiro 	bool r, w;
33140266059SGregory Neil Shapiro 	int ioflags;
33240266059SGregory Neil Shapiro 	SM_FILE_T *fp;
33340266059SGregory Neil Shapiro 
33440266059SGregory Neil Shapiro 	fd = fileno(stream);
33540266059SGregory Neil Shapiro 	SM_REQUIRE(fd >= 0);
33640266059SGregory Neil Shapiro 
33740266059SGregory Neil Shapiro 	r = w = false;
33840266059SGregory Neil Shapiro 	switch (mode[0])
33940266059SGregory Neil Shapiro 	{
34040266059SGregory Neil Shapiro 	  case 'r':
34140266059SGregory Neil Shapiro 		r = true;
34240266059SGregory Neil Shapiro 		break;
34340266059SGregory Neil Shapiro 	  case 'w':
34440266059SGregory Neil Shapiro 	  case 'a':
34540266059SGregory Neil Shapiro 		w = true;
34640266059SGregory Neil Shapiro 		break;
34740266059SGregory Neil Shapiro 	  default:
34840266059SGregory Neil Shapiro 		sm_abort("sm_io_stdioopen: mode '%s' is bad", mode);
34940266059SGregory Neil Shapiro 	}
35040266059SGregory Neil Shapiro 	if (strchr(&mode[1], '+') != NULL)
35140266059SGregory Neil Shapiro 		r = w = true;
35240266059SGregory Neil Shapiro 	if (r && w)
35340266059SGregory Neil Shapiro 		ioflags = SMRW;
35440266059SGregory Neil Shapiro 	else if (r)
35540266059SGregory Neil Shapiro 		ioflags = SMRD;
35640266059SGregory Neil Shapiro 	else
35740266059SGregory Neil Shapiro 		ioflags = SMWR;
35840266059SGregory Neil Shapiro 
35940266059SGregory Neil Shapiro 	fp = sm_fp(SmFtRealStdio, ioflags, NULL);
36040266059SGregory Neil Shapiro 	fp->f_file = fd;
36140266059SGregory Neil Shapiro 	fp->f_cookie = stream;
36240266059SGregory Neil Shapiro 	return fp;
36340266059SGregory Neil Shapiro }
364