smstdio.c revision 132943
190792Sgshapiro/*
2132943Sgshapiro * Copyright (c) 2000-2002, 2004 Sendmail, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro */
990792Sgshapiro
1090792Sgshapiro#include <sm/gen.h>
11132943SgshapiroSM_IDSTR(id, "@(#)$Id: smstdio.c,v 1.33 2004/03/03 19:14:51 ca Exp $")
1290792Sgshapiro#include <unistd.h>
1390792Sgshapiro#include <stdio.h>
1490792Sgshapiro#include <fcntl.h>
1590792Sgshapiro#include <errno.h>
1694334Sgshapiro#include <sys/stat.h>
1790792Sgshapiro#include <sm/assert.h>
1890792Sgshapiro#include <sm/io.h>
1990792Sgshapiro#include <sm/string.h>
2090792Sgshapiro#include "local.h"
2190792Sgshapiro
2290792Sgshapiro/*
2390792Sgshapiro** Overall:
2490792Sgshapiro**	This is a file type which implements a layer on top of the system
2590792Sgshapiro**	stdio. fp->f_cookie is the FILE* of stdio. The cookie may be
2690792Sgshapiro**	"bound late" because of the manner which Linux implements stdio.
2790792Sgshapiro**	When binding late  (when fp->f_cookie==NULL) then the value of
2890792Sgshapiro**	fp->f_ival is used (0, 1 or 2) to map to stdio's stdin, stdout or
2990792Sgshapiro**	stderr.
3090792Sgshapiro*/
3190792Sgshapiro
3290792Sgshapiro/*
3390792Sgshapiro**  SM_STDIOOPEN -- open a file to system stdio implementation
3490792Sgshapiro**
3590792Sgshapiro**	Parameters:
3690792Sgshapiro**		fp -- file pointer assign for this open
3790792Sgshapiro**		info -- info about file to open
3890792Sgshapiro**		flags -- indicating method of opening
3990792Sgshapiro**		rpool -- ignored
4090792Sgshapiro**
4190792Sgshapiro**	Returns:
4290792Sgshapiro**		Failure: -1
4390792Sgshapiro**		Success: 0 (zero)
4490792Sgshapiro*/
4590792Sgshapiro
4690792Sgshapiro/* ARGSUSED3 */
4790792Sgshapiroint
4890792Sgshapirosm_stdioopen(fp, info, flags, rpool)
4990792Sgshapiro	SM_FILE_T *fp;
5090792Sgshapiro	const void *info;
5190792Sgshapiro	int flags;
5290792Sgshapiro	const void *rpool;
5390792Sgshapiro{
5490792Sgshapiro	register FILE *s;
5590792Sgshapiro	char *stdiomode;
5690792Sgshapiro
5790792Sgshapiro	switch (flags)
5890792Sgshapiro	{
5990792Sgshapiro	  case SM_IO_RDONLY:
6090792Sgshapiro		stdiomode = "r";
6190792Sgshapiro		break;
6290792Sgshapiro	  case SM_IO_WRONLY:
6390792Sgshapiro		stdiomode = "w";
6490792Sgshapiro		break;
6590792Sgshapiro	  case SM_IO_APPEND:
6690792Sgshapiro		stdiomode = "a";
6790792Sgshapiro		break;
6890792Sgshapiro	  case SM_IO_APPENDRW:
6990792Sgshapiro		stdiomode = "a+";
7090792Sgshapiro		break;
71120256Sgshapiro#if SM_IO_BINARY != 0
72120256Sgshapiro	  case SM_IO_RDONLY_B:
73120256Sgshapiro		stdiomode = "rb";
74120256Sgshapiro		break;
75120256Sgshapiro	  case SM_IO_WRONLY_B:
76120256Sgshapiro		stdiomode = "wb";
77120256Sgshapiro		break;
78120256Sgshapiro	  case SM_IO_APPEND_B:
79120256Sgshapiro		stdiomode = "ab";
80120256Sgshapiro		break;
81120256Sgshapiro	  case SM_IO_APPENDRW_B:
82120256Sgshapiro		stdiomode = "a+b";
83120256Sgshapiro		break;
84120256Sgshapiro	  case SM_IO_RDWR_B:
85120256Sgshapiro		stdiomode = "r+b";
86120256Sgshapiro		break;
87120256Sgshapiro#endif /* SM_IO_BINARY != 0 */
8890792Sgshapiro	  case SM_IO_RDWR:
8990792Sgshapiro	  default:
9090792Sgshapiro		stdiomode = "r+";
9190792Sgshapiro		break;
9290792Sgshapiro	}
9390792Sgshapiro
9490792Sgshapiro	if ((s = fopen((char *)info, stdiomode)) == NULL)
9590792Sgshapiro		return -1;
9690792Sgshapiro	fp->f_cookie = s;
9790792Sgshapiro	return 0;
9890792Sgshapiro}
9990792Sgshapiro
10090792Sgshapiro/*
10190792Sgshapiro**  SETUP -- assign file type cookie when not already assigned
10290792Sgshapiro**
10390792Sgshapiro**	Parameters:
10490792Sgshapiro**		fp - the file pointer to get the cookie assigned
10590792Sgshapiro**
10690792Sgshapiro**	Return:
10790792Sgshapiro**		none.
10890792Sgshapiro*/
10990792Sgshapiro
11090792Sgshapirostatic void
11190792Sgshapirosetup(fp)
11290792Sgshapiro	SM_FILE_T *fp;
11390792Sgshapiro{
11490792Sgshapiro	if (fp->f_cookie == NULL)
11590792Sgshapiro	{
11690792Sgshapiro		switch (fp->f_ival)
11790792Sgshapiro		{
11890792Sgshapiro		  case 0:
11990792Sgshapiro			fp->f_cookie = stdin;
12090792Sgshapiro			break;
12190792Sgshapiro		  case 1:
12290792Sgshapiro			fp->f_cookie = stdout;
12390792Sgshapiro			break;
12490792Sgshapiro		  case 2:
12590792Sgshapiro			fp->f_cookie = stderr;
12690792Sgshapiro			break;
12790792Sgshapiro		  default:
12890792Sgshapiro			sm_abort("fp->f_ival=%d: out of range (0...2)", fp->f_ival);
12990792Sgshapiro			break;
13090792Sgshapiro		}
13190792Sgshapiro	}
13290792Sgshapiro}
13390792Sgshapiro
13490792Sgshapiro/*
13590792Sgshapiro**  SM_STDIOREAD -- read from the file
13690792Sgshapiro**
13790792Sgshapiro**	Parameters:
13890792Sgshapiro**		fp -- the file pointer
13990792Sgshapiro**		buf -- location to place the read data
14090792Sgshapiro**		n - number of bytes to read
14190792Sgshapiro**
14290792Sgshapiro**	Returns:
14390792Sgshapiro**		result from fread().
14490792Sgshapiro*/
14590792Sgshapiro
14690792Sgshapirossize_t
14790792Sgshapirosm_stdioread(fp, buf, n)
14890792Sgshapiro	SM_FILE_T *fp;
14990792Sgshapiro	char *buf;
15090792Sgshapiro	size_t n;
15190792Sgshapiro{
15290792Sgshapiro	register FILE *s;
15390792Sgshapiro
15490792Sgshapiro	if (fp->f_cookie == NULL)
15590792Sgshapiro		setup(fp);
15690792Sgshapiro	s = fp->f_cookie;
15790792Sgshapiro	return fread(buf, 1, n, s);
15890792Sgshapiro}
15990792Sgshapiro
16090792Sgshapiro/*
16190792Sgshapiro**  SM_STDIOWRITE -- write to the file
16290792Sgshapiro**
16390792Sgshapiro**	Parameters:
16490792Sgshapiro**		fp -- the file pointer
16590792Sgshapiro**		buf -- location of data to write
16690792Sgshapiro**		n - number of bytes to write
16790792Sgshapiro**
16890792Sgshapiro**	Returns:
16990792Sgshapiro**		result from fwrite().
17090792Sgshapiro*/
17190792Sgshapiro
17290792Sgshapirossize_t
17390792Sgshapirosm_stdiowrite(fp, buf, n)
17490792Sgshapiro	SM_FILE_T *fp;
17590792Sgshapiro	char const *buf;
17690792Sgshapiro	size_t n;
17790792Sgshapiro{
17890792Sgshapiro	register FILE *s;
17990792Sgshapiro
18090792Sgshapiro	if (fp->f_cookie == NULL)
18190792Sgshapiro		setup(fp);
18290792Sgshapiro	s = fp->f_cookie;
18390792Sgshapiro	return fwrite(buf, 1, n, s);
18490792Sgshapiro}
18590792Sgshapiro
18690792Sgshapiro/*
18790792Sgshapiro**  SM_STDIOSEEK -- set position within file
18890792Sgshapiro**
18990792Sgshapiro**	Parameters:
19090792Sgshapiro**		fp -- the file pointer
19190792Sgshapiro**		offset -- new location based on 'whence'
19290792Sgshapiro**		whence -- indicates "base" for 'offset'
19390792Sgshapiro**
19490792Sgshapiro**	Returns:
19590792Sgshapiro**		result from fseek().
19690792Sgshapiro*/
19790792Sgshapiro
19890792Sgshapirooff_t
19990792Sgshapirosm_stdioseek(fp, offset, whence)
20090792Sgshapiro	SM_FILE_T *fp;
20190792Sgshapiro	off_t offset;
20290792Sgshapiro	int whence;
20390792Sgshapiro{
20490792Sgshapiro	register FILE *s;
20590792Sgshapiro
20690792Sgshapiro	if (fp->f_cookie == NULL)
20790792Sgshapiro		setup(fp);
20890792Sgshapiro	s = fp->f_cookie;
20990792Sgshapiro	return fseek(s, offset, whence);
21090792Sgshapiro}
21190792Sgshapiro
21290792Sgshapiro/*
21390792Sgshapiro**  SM_STDIOCLOSE -- close the file
21490792Sgshapiro**
21590792Sgshapiro**	Parameters:
21690792Sgshapiro**		fp -- close file pointer
21790792Sgshapiro**
21890792Sgshapiro**	Return:
21990792Sgshapiro**		status from fclose()
22090792Sgshapiro*/
22190792Sgshapiro
22290792Sgshapiroint
22390792Sgshapirosm_stdioclose(fp)
22490792Sgshapiro	SM_FILE_T *fp;
22590792Sgshapiro{
22690792Sgshapiro	register FILE *s;
22790792Sgshapiro
22890792Sgshapiro	if (fp->f_cookie == NULL)
22990792Sgshapiro		setup(fp);
23090792Sgshapiro	s = fp->f_cookie;
23190792Sgshapiro	return fclose(s);
23290792Sgshapiro}
23390792Sgshapiro
23490792Sgshapiro/*
23590792Sgshapiro**  SM_STDIOSETINFO -- set info for this open file
23690792Sgshapiro**
23790792Sgshapiro**	Parameters:
23890792Sgshapiro**		fp -- the file pointer
23990792Sgshapiro**		what -- type of information setting
24090792Sgshapiro**		valp -- memory location of info to set
24190792Sgshapiro**
24290792Sgshapiro**	Return:
24390792Sgshapiro**		Failure: -1 and sets errno
24490792Sgshapiro**		Success: none (currently).
24590792Sgshapiro*/
24690792Sgshapiro
24790792Sgshapiro/* ARGSUSED2 */
24890792Sgshapiroint
24990792Sgshapirosm_stdiosetinfo(fp, what, valp)
25090792Sgshapiro	SM_FILE_T *fp;
25190792Sgshapiro	int what;
25290792Sgshapiro	void *valp;
25390792Sgshapiro{
25490792Sgshapiro	switch (what)
25590792Sgshapiro	{
25690792Sgshapiro	  case SM_IO_WHAT_MODE:
25790792Sgshapiro	  default:
25890792Sgshapiro		errno = EINVAL;
25990792Sgshapiro		return -1;
26090792Sgshapiro	}
26190792Sgshapiro}
26290792Sgshapiro
26390792Sgshapiro/*
26490792Sgshapiro**  SM_STDIOGETINFO -- get info for this open file
26590792Sgshapiro**
26690792Sgshapiro**	Parameters:
26790792Sgshapiro**		fp -- the file pointer
26890792Sgshapiro**		what -- type of information request
26990792Sgshapiro**		valp -- memory location to place info
27090792Sgshapiro**
27190792Sgshapiro**	Return:
27290792Sgshapiro**		Failure: -1 and sets errno
27390792Sgshapiro**		Success: none (currently).
27490792Sgshapiro*/
27590792Sgshapiro
27690792Sgshapiro/* ARGSUSED2 */
27790792Sgshapiroint
27890792Sgshapirosm_stdiogetinfo(fp, what, valp)
27990792Sgshapiro	SM_FILE_T *fp;
28090792Sgshapiro	int what;
28190792Sgshapiro	void *valp;
28290792Sgshapiro{
28390792Sgshapiro	switch (what)
28490792Sgshapiro	{
28594334Sgshapiro	  case SM_IO_WHAT_SIZE:
28694334Sgshapiro	  {
28794334Sgshapiro		  int fd;
28894334Sgshapiro		  struct stat st;
28994334Sgshapiro
29094334Sgshapiro		  if (fp->f_cookie == NULL)
29194334Sgshapiro			  setup(fp);
29294334Sgshapiro		  fd = fileno((FILE *) fp->f_cookie);
29394334Sgshapiro		  if (fd < 0)
29494334Sgshapiro			  return -1;
29594334Sgshapiro		  if (fstat(fd, &st) == 0)
29694334Sgshapiro			  return st.st_size;
29794334Sgshapiro		  else
29894334Sgshapiro			  return -1;
29994334Sgshapiro	  }
30094334Sgshapiro
30190792Sgshapiro	  case SM_IO_WHAT_MODE:
30290792Sgshapiro	  default:
30390792Sgshapiro		errno = EINVAL;
30490792Sgshapiro		return -1;
30590792Sgshapiro	}
30690792Sgshapiro}
30790792Sgshapiro
30890792Sgshapiro/*
30990792Sgshapiro**  SM_IO_STDIOOPEN -- create an SM_FILE which interfaces to a stdio FILE
31090792Sgshapiro**
31190792Sgshapiro**	Parameters:
31290792Sgshapiro**		stream -- an open stdio stream, as returned by fopen()
31390792Sgshapiro**		mode -- the mode argument to fopen() which describes stream
31490792Sgshapiro**
31590792Sgshapiro**	Return:
31690792Sgshapiro**		On success, return a pointer to an SM_FILE object which
31790792Sgshapiro**		can be used for reading and writing 'stream'.
31890792Sgshapiro**		Abort if mode is gibberish or stream is bad.
31990792Sgshapiro**		Raise an exception if we can't allocate memory.
32090792Sgshapiro*/
32190792Sgshapiro
32290792SgshapiroSM_FILE_T *
32390792Sgshapirosm_io_stdioopen(stream, mode)
32490792Sgshapiro	FILE *stream;
32590792Sgshapiro	char *mode;
32690792Sgshapiro{
32790792Sgshapiro	int fd;
32890792Sgshapiro	bool r, w;
32990792Sgshapiro	int ioflags;
33090792Sgshapiro	SM_FILE_T *fp;
33190792Sgshapiro
33290792Sgshapiro	fd = fileno(stream);
33390792Sgshapiro	SM_REQUIRE(fd >= 0);
33490792Sgshapiro
33590792Sgshapiro	r = w = false;
33690792Sgshapiro	switch (mode[0])
33790792Sgshapiro	{
33890792Sgshapiro	  case 'r':
33990792Sgshapiro		r = true;
34090792Sgshapiro		break;
34190792Sgshapiro	  case 'w':
34290792Sgshapiro	  case 'a':
34390792Sgshapiro		w = true;
34490792Sgshapiro		break;
34590792Sgshapiro	  default:
34690792Sgshapiro		sm_abort("sm_io_stdioopen: mode '%s' is bad", mode);
34790792Sgshapiro	}
34890792Sgshapiro	if (strchr(&mode[1], '+') != NULL)
34990792Sgshapiro		r = w = true;
35090792Sgshapiro	if (r && w)
35190792Sgshapiro		ioflags = SMRW;
35290792Sgshapiro	else if (r)
35390792Sgshapiro		ioflags = SMRD;
35490792Sgshapiro	else
35590792Sgshapiro		ioflags = SMWR;
35690792Sgshapiro
35790792Sgshapiro	fp = sm_fp(SmFtRealStdio, ioflags, NULL);
35890792Sgshapiro	fp->f_file = fd;
35990792Sgshapiro	fp->f_cookie = stream;
36090792Sgshapiro	return fp;
36190792Sgshapiro}
362