2 * Copyright (c) 2000-2003 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
10 * By using this file, you agree to the terms and conditions set
11 * forth in the LICENSE file which can be found at the top level of
12 * the sendmail distribution.
16 SM_RCSID("@(#)$Id: stdio.c,v 1.56.2.13 2003/09/04 01:18:08 ca Exp $")
20 #include <string.h> /* FreeBSD: FD_ZERO needs <string.h> */
24 #include <sm/assert.h>
25 #include <sm/varargs.h>
27 #include <sm/setjmp.h>
34 ** Small standard I/O/seek/close functions.
35 ** These maintain the `known seek offset' for seek optimization.
39 ** SM_STDOPEN -- open a file with stdio behavior
41 ** Not associated with the system's stdio in libc.
44 ** fp -- file pointer to be associated with the open
45 ** info -- pathname of the file to be opened
46 ** flags -- indicates type of access methods
50 ** Failure: -1 and set errno
51 ** Success: 0 or greater (fd of file from open(2)).
57 sm_stdopen(fp, info, flags, rpool)
63 char *path = (char *) info;
66 switch (SM_IO_MODE(flags))
72 oflags = O_RDWR | O_CREAT | O_TRUNC;
78 oflags = O_WRONLY | O_CREAT | O_TRUNC;
81 oflags = O_APPEND | O_WRONLY | O_CREAT;
84 oflags = O_APPEND | O_RDWR | O_CREAT;
91 if (SM_IS_BINARY(flags))
94 fp->f_file = open(path, oflags,
95 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
97 return -1; /* errno set by open() */
99 if (oflags & O_APPEND)
100 (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
106 ** SM_STDREAD -- read from the file
109 ** fp -- file pointer to read from
110 ** buf -- location to place read data
111 ** n -- number of bytes to read
114 ** Failure: -1 and sets errno
115 ** Success: number of bytes read
118 ** Updates internal offset into file.
122 sm_stdread(fp, buf, n)
129 ret = read(fp->f_file, buf, n);
131 /* if the read succeeded, update the current offset */
133 fp->f_lseekoff += ret;
138 ** SM_STDWRITE -- write to the file
141 ** fp -- file pointer ro write to
142 ** buf -- location of data to be written
143 ** n - number of bytes to write
146 ** Failure: -1 and sets errno
147 ** Success: number of bytes written
151 sm_stdwrite(fp, buf, n)
156 return write(fp->f_file, buf, n);
160 ** SM_STDSEEK -- set the file offset position
163 ** fp -- file pointer to position
164 ** offset -- how far to position from "base" (set by 'whence')
165 ** whence -- indicates where the "base" of the 'offset' to start
168 ** Failure: -1 and sets errno
169 ** Success: the current offset
172 ** Updates the internal value of the offset.
176 sm_stdseek(fp, offset, whence)
183 ret = lseek(fp->f_file, (off_t) offset, whence);
184 if (ret != (off_t) -1)
185 fp->f_lseekoff = ret;
190 ** SM_STDCLOSE -- close the file
193 ** fp -- the file pointer to close
197 ** Failure: -1 and sets errno
204 return close(fp->f_file);
208 ** SM_STDSETMODE -- set the access mode for the file
210 ** Called by sm_stdsetinfo().
213 ** fp -- file pointer
214 ** mode -- new mode to set the file access to
217 ** Success: 0 (zero);
218 ** Failure: -1 and sets errno
222 sm_stdsetmode(fp, mode)
228 switch (SM_IO_MODE(*mode))
244 fp->f_flags = fp->f_flags & ~SMMODEMASK;
245 fp->f_flags |= flags;
250 ** SM_STDGETMODE -- for getinfo determine open mode
252 ** Called by sm_stdgetinfo().
255 ** fp -- the file mode being determined
256 ** mode -- internal mode to map to external value
259 ** Failure: -1 and sets errno
260 ** Success: external mode value
264 sm_stdgetmode(fp, mode)
268 switch (fp->f_flags & SMMODEMASK)
274 *mode = SM_IO_RDONLY;
277 *mode = SM_IO_WRONLY;
287 ** SM_STDSETINFO -- set/modify information for a file
290 ** fp -- file to set info for
291 ** what -- type of info to set
292 ** valp -- location of data used for setting
295 ** Failure: -1 and sets errno
300 sm_stdsetinfo(fp, what, valp)
307 case SM_IO_WHAT_MODE:
308 return sm_stdsetmode(fp, (const int *)valp);
317 ** SM_GETINFO -- get information about the open file
320 ** fp -- file to get info for
321 ** what -- type of info to get
322 ** valp -- location to place found info
325 ** Success: may or may not place info in 'valp' depending
326 ** on 'what' value, and returns values >=0. Return
327 ** value may be the obtained info
328 ** Failure: -1 and sets errno
332 sm_stdgetinfo(fp, what, valp)
339 case SM_IO_WHAT_MODE:
340 return sm_stdgetmode(fp, (int *)valp);
345 case SM_IO_WHAT_SIZE:
349 if (fstat(fp->f_file, &st) == 0)
355 case SM_IO_IS_READABLE:
358 struct timeval timeout;
360 if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
366 SM_FD_SET(fp->f_file, &readfds);
369 if (select(fp->f_file + 1, FDSET_CAST &readfds,
370 NULL, NULL, &timeout) > 0 &&
371 SM_FD_ISSET(fp->f_file, &readfds))
383 ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
385 ** I/O function to handle fdopen() stdio equivalence. The rest of
386 ** the functions are the same as the sm_stdopen() above.
389 ** fp -- the file pointer to be associated with the open
390 ** name -- the primitive file descriptor for association
391 ** flags -- indicates type of access methods
395 ** Success: primitive file descriptor value
396 ** Failure: -1 and sets errno
401 sm_stdfdopen(fp, info, flags, rpool)
407 int oflags, tmp, fdflags, fd = *((int *) info);
409 switch (SM_IO_MODE(flags))
412 oflags = O_RDWR | O_CREAT;
418 oflags = O_WRONLY | O_CREAT | O_TRUNC;
421 oflags = O_APPEND | O_WRONLY | O_CREAT;
424 oflags = O_APPEND | O_RDWR | O_CREAT;
431 if (SM_IS_BINARY(flags))
433 #endif /* O_BINARY */
435 /* Make sure the mode the user wants is a subset of the actual mode. */
436 if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
438 tmp = fdflags & O_ACCMODE;
439 if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
445 if (oflags & O_APPEND)
446 (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
451 ** SM_IO_FOPEN -- open a file
453 ** Same interface and semantics as the open() system call,
454 ** except that it returns SM_FILE_T* instead of a file descriptor.
457 ** pathname -- path of file to open
458 ** flags -- flags controlling the open
459 ** ... -- option "mode" for opening the file
462 ** Raises an exception on heap exhaustion.
463 ** Returns NULL and sets errno if open() fails.
464 ** Returns an SM_FILE_T pointer on success.
469 sm_io_fopen(char *pathname, int flags, ...)
470 #else /* SM_VA_STD */
471 sm_io_fopen(pathname, flags, va_alist)
475 #endif /* SM_VA_STD */
485 SM_VA_START(ap, flags);
486 mode = (MODE_T) SM_VA_ARG(ap, int);
492 switch (flags & O_ACCMODE)
504 sm_abort("sm_io_fopen: bad flags 0%o", flags);
507 fp = sm_fp(SmFtStdio, ioflags, NULL);
508 fp->f_file = open(pathname, flags, mode);
509 if (fp->f_file == -1)