8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / sendmail / libsm / stdio.c
blob8c5cae77bd1924f682e30325ced7d3ec608c4a02
1 /*
2 * Copyright (c) 2000-2005 Sendmail, Inc. and its suppliers.
3 * All rights reserved.
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
8 * Chris Torek.
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.
15 #pragma ident "%Z%%M% %I% %E% SMI"
17 #include <sm/gen.h>
18 SM_RCSID("@(#)$Id: stdio.c,v 1.71 2005/06/14 23:07:20 ca Exp $")
19 #include <unistd.h>
20 #include <errno.h>
21 #include <fcntl.h>
22 #include <string.h> /* FreeBSD: FD_ZERO needs <string.h> */
23 #include <sys/stat.h>
24 #include <sm/time.h>
25 #include <sm/heap.h>
26 #include <sm/assert.h>
27 #include <sm/varargs.h>
28 #include <sm/io.h>
29 #include <sm/setjmp.h>
30 #include <sm/conf.h>
31 #include <sm/fdset.h>
32 #include "local.h"
34 static int sm_stdsetmode __P((SM_FILE_T *, const int *));
35 static int sm_stdgetmode __P((SM_FILE_T *, int *));
38 ** Overall:
39 ** Small standard I/O/seek/close functions.
40 ** These maintain the `known seek offset' for seek optimization.
44 ** SM_STDOPEN -- open a file with stdio behavior
46 ** Not associated with the system's stdio in libc.
48 ** Parameters:
49 ** fp -- file pointer to be associated with the open
50 ** info -- pathname of the file to be opened
51 ** flags -- indicates type of access methods
52 ** rpool -- ignored
54 ** Returns:
55 ** Failure: -1 and set errno
56 ** Success: 0 or greater (fd of file from open(2)).
60 /* ARGSUSED3 */
61 int
62 sm_stdopen(fp, info, flags, rpool)
63 SM_FILE_T *fp;
64 const void *info;
65 int flags;
66 const void *rpool;
68 char *path = (char *) info;
69 int oflags;
71 switch (SM_IO_MODE(flags))
73 case SM_IO_RDWR:
74 oflags = O_RDWR;
75 break;
76 case SM_IO_RDWRTR:
77 oflags = O_RDWR | O_CREAT | O_TRUNC;
78 break;
79 case SM_IO_RDONLY:
80 oflags = O_RDONLY;
81 break;
82 case SM_IO_WRONLY:
83 oflags = O_WRONLY | O_CREAT | O_TRUNC;
84 break;
85 case SM_IO_APPEND:
86 oflags = O_APPEND | O_WRONLY | O_CREAT;
87 break;
88 case SM_IO_APPENDRW:
89 oflags = O_APPEND | O_RDWR | O_CREAT;
90 break;
91 default:
92 errno = EINVAL;
93 return -1;
95 #ifdef O_BINARY
96 if (SM_IS_BINARY(flags))
97 oflags |= O_BINARY;
98 #endif /* O_BINARY */
99 fp->f_file = open(path, oflags,
100 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
101 if (fp->f_file < 0)
102 return -1; /* errno set by open() */
104 if (oflags & O_APPEND)
105 (void) (*fp->f_seek)((void *)fp, (off_t)0, SEEK_END);
107 return fp->f_file;
111 ** SM_STDREAD -- read from the file
113 ** Parameters:
114 ** fp -- file pointer to read from
115 ** buf -- location to place read data
116 ** n -- number of bytes to read
118 ** Returns:
119 ** Failure: -1 and sets errno
120 ** Success: number of bytes read
122 ** Side Effects:
123 ** Updates internal offset into file.
126 ssize_t
127 sm_stdread(fp, buf, n)
128 SM_FILE_T *fp;
129 char *buf;
130 size_t n;
132 register int ret;
134 ret = read(fp->f_file, buf, n);
136 /* if the read succeeded, update the current offset */
137 if (ret > 0)
138 fp->f_lseekoff += ret;
139 return ret;
143 ** SM_STDWRITE -- write to the file
145 ** Parameters:
146 ** fp -- file pointer ro write to
147 ** buf -- location of data to be written
148 ** n - number of bytes to write
150 ** Returns:
151 ** Failure: -1 and sets errno
152 ** Success: number of bytes written
155 ssize_t
156 sm_stdwrite(fp, buf, n)
157 SM_FILE_T *fp;
158 char const *buf;
159 size_t n;
161 return write(fp->f_file, buf, n);
165 ** SM_STDSEEK -- set the file offset position
167 ** Parmeters:
168 ** fp -- file pointer to position
169 ** offset -- how far to position from "base" (set by 'whence')
170 ** whence -- indicates where the "base" of the 'offset' to start
172 ** Results:
173 ** Failure: -1 and sets errno
174 ** Success: the current offset
176 ** Side Effects:
177 ** Updates the internal value of the offset.
180 off_t
181 sm_stdseek(fp, offset, whence)
182 SM_FILE_T *fp;
183 off_t offset;
184 int whence;
186 register off_t ret;
188 ret = lseek(fp->f_file, (off_t) offset, whence);
189 if (ret != (off_t) -1)
190 fp->f_lseekoff = ret;
191 return ret;
195 ** SM_STDCLOSE -- close the file
197 ** Parameters:
198 ** fp -- the file pointer to close
200 ** Returns:
201 ** Success: 0 (zero)
202 ** Failure: -1 and sets errno
206 sm_stdclose(fp)
207 SM_FILE_T *fp;
209 return close(fp->f_file);
213 ** SM_STDSETMODE -- set the access mode for the file
215 ** Called by sm_stdsetinfo().
217 ** Parameters:
218 ** fp -- file pointer
219 ** mode -- new mode to set the file access to
221 ** Results:
222 ** Success: 0 (zero);
223 ** Failure: -1 and sets errno
226 static int
227 sm_stdsetmode(fp, mode)
228 SM_FILE_T *fp;
229 const int *mode;
231 int flags = 0;
233 switch (SM_IO_MODE(*mode))
235 case SM_IO_RDWR:
236 flags |= SMRW;
237 break;
238 case SM_IO_RDONLY:
239 flags |= SMRD;
240 break;
241 case SM_IO_WRONLY:
242 flags |= SMWR;
243 break;
244 case SM_IO_APPEND:
245 default:
246 errno = EINVAL;
247 return -1;
249 fp->f_flags = fp->f_flags & ~SMMODEMASK;
250 fp->f_flags |= flags;
251 return 0;
255 ** SM_STDGETMODE -- for getinfo determine open mode
257 ** Called by sm_stdgetinfo().
259 ** Parameters:
260 ** fp -- the file mode being determined
261 ** mode -- internal mode to map to external value
263 ** Results:
264 ** Failure: -1 and sets errno
265 ** Success: external mode value
268 static int
269 sm_stdgetmode(fp, mode)
270 SM_FILE_T *fp;
271 int *mode;
273 switch (fp->f_flags & SMMODEMASK)
275 case SMRW:
276 *mode = SM_IO_RDWR;
277 break;
278 case SMRD:
279 *mode = SM_IO_RDONLY;
280 break;
281 case SMWR:
282 *mode = SM_IO_WRONLY;
283 break;
284 default:
285 errno = EINVAL;
286 return -1;
288 return 0;
292 ** SM_STDSETINFO -- set/modify information for a file
294 ** Parameters:
295 ** fp -- file to set info for
296 ** what -- type of info to set
297 ** valp -- location of data used for setting
299 ** Returns:
300 ** Failure: -1 and sets errno
301 ** Success: >=0
305 sm_stdsetinfo(fp, what, valp)
306 SM_FILE_T *fp;
307 int what;
308 void *valp;
310 switch (what)
312 case SM_IO_WHAT_MODE:
313 return sm_stdsetmode(fp, (const int *)valp);
315 default:
316 errno = EINVAL;
317 return -1;
322 ** SM_GETINFO -- get information about the open file
324 ** Parameters:
325 ** fp -- file to get info for
326 ** what -- type of info to get
327 ** valp -- location to place found info
329 ** Returns:
330 ** Success: may or may not place info in 'valp' depending
331 ** on 'what' value, and returns values >=0. Return
332 ** value may be the obtained info
333 ** Failure: -1 and sets errno
337 sm_stdgetinfo(fp, what, valp)
338 SM_FILE_T *fp;
339 int what;
340 void *valp;
342 switch (what)
344 case SM_IO_WHAT_MODE:
345 return sm_stdgetmode(fp, (int *)valp);
347 case SM_IO_WHAT_FD:
348 return fp->f_file;
350 case SM_IO_WHAT_SIZE:
352 struct stat st;
354 if (fstat(fp->f_file, &st) == 0)
355 return st.st_size;
356 else
357 return -1;
360 case SM_IO_IS_READABLE:
362 fd_set readfds;
363 struct timeval timeout;
365 if (SM_FD_SETSIZE > 0 && fp->f_file >= SM_FD_SETSIZE)
367 errno = EINVAL;
368 return -1;
370 FD_ZERO(&readfds);
371 SM_FD_SET(fp->f_file, &readfds);
372 timeout.tv_sec = 0;
373 timeout.tv_usec = 0;
374 if (select(fp->f_file + 1, FDSET_CAST &readfds,
375 NULL, NULL, &timeout) > 0 &&
376 SM_FD_ISSET(fp->f_file, &readfds))
377 return 1;
378 return 0;
381 default:
382 errno = EINVAL;
383 return -1;
388 ** SM_STDFDOPEN -- open file by primitive 'fd' rather than pathname
390 ** I/O function to handle fdopen() stdio equivalence. The rest of
391 ** the functions are the same as the sm_stdopen() above.
393 ** Parameters:
394 ** fp -- the file pointer to be associated with the open
395 ** name -- the primitive file descriptor for association
396 ** flags -- indicates type of access methods
397 ** rpool -- ignored
399 ** Results:
400 ** Success: primitive file descriptor value
401 ** Failure: -1 and sets errno
404 /* ARGSUSED3 */
406 sm_stdfdopen(fp, info, flags, rpool)
407 SM_FILE_T *fp;
408 const void *info;
409 int flags;
410 const void *rpool;
412 int oflags, tmp, fdflags, fd = *((int *) info);
414 switch (SM_IO_MODE(flags))
416 case SM_IO_RDWR:
417 oflags = O_RDWR | O_CREAT;
418 break;
419 case SM_IO_RDONLY:
420 oflags = O_RDONLY;
421 break;
422 case SM_IO_WRONLY:
423 oflags = O_WRONLY | O_CREAT | O_TRUNC;
424 break;
425 case SM_IO_APPEND:
426 oflags = O_APPEND | O_WRONLY | O_CREAT;
427 break;
428 case SM_IO_APPENDRW:
429 oflags = O_APPEND | O_RDWR | O_CREAT;
430 break;
431 default:
432 errno = EINVAL;
433 return -1;
435 #ifdef O_BINARY
436 if (SM_IS_BINARY(flags))
437 oflags |= O_BINARY;
438 #endif /* O_BINARY */
440 /* Make sure the mode the user wants is a subset of the actual mode. */
441 if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
442 return -1;
443 tmp = fdflags & O_ACCMODE;
444 if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE)))
446 errno = EINVAL;
447 return -1;
449 fp->f_file = fd;
450 if (oflags & O_APPEND)
451 (void) (*fp->f_seek)(fp, (off_t)0, SEEK_END);
452 return fp->f_file;
456 ** SM_IO_FOPEN -- open a file
458 ** Same interface and semantics as the open() system call,
459 ** except that it returns SM_FILE_T* instead of a file descriptor.
461 ** Parameters:
462 ** pathname -- path of file to open
463 ** flags -- flags controlling the open
464 ** ... -- option "mode" for opening the file
466 ** Returns:
467 ** Raises an exception on heap exhaustion.
468 ** Returns NULL and sets errno if open() fails.
469 ** Returns an SM_FILE_T pointer on success.
472 SM_FILE_T *
473 #if SM_VA_STD
474 sm_io_fopen(char *pathname, int flags, ...)
475 #else /* SM_VA_STD */
476 sm_io_fopen(pathname, flags, va_alist)
477 char *pathname;
478 int flags;
479 va_dcl
480 #endif /* SM_VA_STD */
482 MODE_T mode;
483 SM_FILE_T *fp;
484 int ioflags;
486 if (flags & O_CREAT)
488 SM_VA_LOCAL_DECL
490 SM_VA_START(ap, flags);
491 mode = (MODE_T) SM_VA_ARG(ap, int);
492 SM_VA_END(ap);
494 else
495 mode = 0;
497 switch (flags & O_ACCMODE)
499 case O_RDONLY:
500 ioflags = SMRD;
501 break;
502 case O_WRONLY:
503 ioflags = SMWR;
504 break;
505 case O_RDWR:
506 ioflags = SMRW;
507 break;
508 default:
509 sm_abort("sm_io_fopen: bad flags 0%o", flags);
512 fp = sm_fp(SmFtStdio, ioflags, NULL);
513 fp->f_file = open(pathname, flags, mode);
514 if (fp->f_file == -1)
516 fp->f_flags = 0;
517 fp->sm_magic = NULL;
518 return NULL;
520 return fp;