1 | /* |
---|
2 | * Copyright (c) 2000-2001 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. |
---|
6 | * |
---|
7 | * This code is derived from software contributed to Berkeley by |
---|
8 | * Chris Torek. |
---|
9 | * |
---|
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. |
---|
13 | */ |
---|
14 | |
---|
15 | #include <sm/gen.h> |
---|
16 | SM_RCSID("@(#)$Id: makebuf.c,v 1.1.1.1 2003-04-08 15:06:29 zacheiss Exp $") |
---|
17 | #include <stdlib.h> |
---|
18 | #include <unistd.h> |
---|
19 | #include <sys/types.h> |
---|
20 | #include <sys/stat.h> |
---|
21 | #include <sm/io.h> |
---|
22 | #include <sm/heap.h> |
---|
23 | #include <sm/conf.h> |
---|
24 | #include "local.h" |
---|
25 | |
---|
26 | /* |
---|
27 | ** SM_MAKEBUF -- make a buffer for the file |
---|
28 | ** |
---|
29 | ** Parameters: |
---|
30 | ** fp -- the file to be buffered |
---|
31 | ** |
---|
32 | ** Returns: |
---|
33 | ** nothing |
---|
34 | ** |
---|
35 | ** Allocate a file buffer, or switch to unbuffered I/O. |
---|
36 | ** By default tty devices default to line buffered. |
---|
37 | */ |
---|
38 | |
---|
39 | void |
---|
40 | sm_makebuf(fp) |
---|
41 | register SM_FILE_T *fp; |
---|
42 | { |
---|
43 | register void *p; |
---|
44 | register int flags; |
---|
45 | size_t size; |
---|
46 | int couldbetty; |
---|
47 | |
---|
48 | if (fp->f_flags & SMNBF) |
---|
49 | { |
---|
50 | fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; |
---|
51 | fp->f_bf.smb_size = 1; |
---|
52 | return; |
---|
53 | } |
---|
54 | flags = sm_whatbuf(fp, &size, &couldbetty); |
---|
55 | if ((p = sm_malloc(size)) == NULL) |
---|
56 | { |
---|
57 | fp->f_flags |= SMNBF; |
---|
58 | fp->f_bf.smb_base = fp->f_p = fp->f_nbuf; |
---|
59 | fp->f_bf.smb_size = 1; |
---|
60 | return; |
---|
61 | } |
---|
62 | if (!Sm_IO_DidInit) |
---|
63 | sm_init(); |
---|
64 | flags |= SMMBF; |
---|
65 | fp->f_bf.smb_base = fp->f_p = p; |
---|
66 | fp->f_bf.smb_size = size; |
---|
67 | if (couldbetty && isatty(fp->f_file)) |
---|
68 | flags |= SMLBF; |
---|
69 | fp->f_flags |= flags; |
---|
70 | } |
---|
71 | |
---|
72 | /* |
---|
73 | ** SM_WHATBUF -- determine proper buffer for a file (internal) |
---|
74 | ** |
---|
75 | ** Plus it fills in 'bufsize' for recommended buffer size and |
---|
76 | ** fills in flag to indicate if 'fp' could be a tty (nothing |
---|
77 | ** to do with "betty" :-) ). |
---|
78 | ** |
---|
79 | ** Parameters: |
---|
80 | ** fp -- file pointer to be buffered |
---|
81 | ** bufsize -- new buffer size (a return) |
---|
82 | ** couldbetty -- could be a tty (returns) |
---|
83 | ** |
---|
84 | ** Returns: |
---|
85 | ** Success: |
---|
86 | ** on error: |
---|
87 | ** SMNPT -- not seek opimized |
---|
88 | ** SMOPT -- seek opimized |
---|
89 | */ |
---|
90 | |
---|
91 | int |
---|
92 | sm_whatbuf(fp, bufsize, couldbetty) |
---|
93 | register SM_FILE_T *fp; |
---|
94 | size_t *bufsize; |
---|
95 | int *couldbetty; |
---|
96 | { |
---|
97 | struct stat st; |
---|
98 | |
---|
99 | if (fp->f_file < 0 || fstat(fp->f_file, &st) < 0) |
---|
100 | { |
---|
101 | *couldbetty = 0; |
---|
102 | *bufsize = SM_IO_BUFSIZ; |
---|
103 | return SMNPT; |
---|
104 | } |
---|
105 | |
---|
106 | /* could be a tty iff it is a character device */ |
---|
107 | *couldbetty = S_ISCHR(st.st_mode); |
---|
108 | if (st.st_blksize == 0) |
---|
109 | { |
---|
110 | *bufsize = SM_IO_BUFSIZ; |
---|
111 | return SMNPT; |
---|
112 | } |
---|
113 | |
---|
114 | #if SM_IO_MAX_BUF_FILE > 0 |
---|
115 | if (S_ISREG(st.st_mode) && st.st_blksize > SM_IO_MAX_BUF_FILE) |
---|
116 | st.st_blksize = SM_IO_MAX_BUF_FILE; |
---|
117 | #endif /* SM_IO_MAX_BUF_FILE > 0 */ |
---|
118 | |
---|
119 | #if SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 |
---|
120 | if (!S_ISREG(st.st_mode)) |
---|
121 | { |
---|
122 | # if SM_IO_MAX_BUF > 0 |
---|
123 | if (st.st_blksize > SM_IO_MAX_BUF) |
---|
124 | st.st_blksize = SM_IO_MAX_BUF; |
---|
125 | # if SM_IO_MIN_BUF > 0 |
---|
126 | else |
---|
127 | # endif /* SM_IO_MIN_BUF > 0 */ |
---|
128 | # endif /* SM_IO_MAX_BUF > 0 */ |
---|
129 | # if SM_IO_MIN_BUF > 0 |
---|
130 | if (st.st_blksize < SM_IO_MIN_BUF) |
---|
131 | st.st_blksize = SM_IO_MIN_BUF; |
---|
132 | # endif /* SM_IO_MIN_BUF > 0 */ |
---|
133 | } |
---|
134 | #endif /* SM_IO_MAX_BUF > 0 || SM_IO_MIN_BUF > 0 */ |
---|
135 | |
---|
136 | /* |
---|
137 | ** Optimise fseek() only if it is a regular file. (The test for |
---|
138 | ** sm_std_seek is mainly paranoia.) It is safe to set _blksize |
---|
139 | ** unconditionally; it will only be used if SMOPT is also set. |
---|
140 | */ |
---|
141 | |
---|
142 | if ((fp->f_flags & SMSTR) == 0) |
---|
143 | { |
---|
144 | *bufsize = st.st_blksize; |
---|
145 | fp->f_blksize = st.st_blksize; |
---|
146 | } |
---|
147 | else |
---|
148 | *bufsize = SM_IO_BUFSIZ; |
---|
149 | if ((st.st_mode & S_IFMT) == S_IFREG && |
---|
150 | fp->f_seek == sm_stdseek) |
---|
151 | return SMOPT; |
---|
152 | else |
---|
153 | return SMNPT; |
---|
154 | } |
---|