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