Bug Summary

File:include/stdio.h
Warning:line 392, column 6
Access to field '_w' results in a dereference of a null pointer (loaded from variable '_p')

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name mail.local.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/libexec/mail.local/obj -resource-dir /usr/local/lib/clang/13.0.0 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/libexec/mail.local/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c /usr/src/libexec/mail.local/mail.local.c

/usr/src/libexec/mail.local/mail.local.c

1/* $OpenBSD: mail.local.c,v 1.39 2020/02/09 14:59:20 millert Exp $ */
2
3/*-
4 * Copyright (c) 1996-1998 Theo de Raadt <deraadt@theos.com>
5 * Copyright (c) 1996-1998 David Mazieres <dm@lcs.mit.edu>
6 * Copyright (c) 1990 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <sys/socket.h>
37#include <sys/wait.h>
38#include <netinet/in.h>
39#include <sysexits.h>
40#include <syslog.h>
41#include <fcntl.h>
42#include <netdb.h>
43#include <pwd.h>
44#include <time.h>
45#include <unistd.h>
46#include <limits.h>
47#include <errno(*__errno()).h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <signal.h>
52#include "pathnames.h"
53#include "mail.local.h"
54
55int
56main(int argc, char *argv[])
57{
58 struct passwd *pw;
59 int ch, fd, eval, lockfile=1;
60 uid_t uid;
61 char *from;
62
63 openlog("mail.local", LOG_PERROR0x20, LOG_MAIL(2<<3));
64
65 from = NULL((void *)0);
66 while ((ch = getopt(argc, argv, "lLdf:r:")) != -1)
1
Assuming the condition is false
2
Loop condition is false. Execution continues on line 85
67 switch (ch) {
68 case 'd': /* backward compatible */
69 break;
70 case 'f':
71 case 'r': /* backward compatible */
72 if (from)
73 merr(EX_USAGE64, "multiple -f options");
74 from = optarg;
75 break;
76 case 'l':
77 lockfile=1;
78 break;
79 case 'L':
80 lockfile=0;
81 break;
82 default:
83 usage();
84 }
85 argc -= optind;
86 argv += optind;
87
88 if (!*argv)
3
Assuming the condition is false
4
Taking false branch
89 usage();
90
91 /*
92 * If from not specified, use the name from getlogin() if the
93 * uid matches, otherwise, use the name from the password file
94 * corresponding to the uid.
95 */
96 uid = getuid();
97 if (!from
4.1
'from' is null
4.1
'from' is null
&& (!(from = getlogin()) ||
5
Assuming 'from' is non-null
8
Taking false branch
98 !(pw = getpwnam(from)) || pw->pw_uid != uid))
6
Assuming 'pw' is non-null
7
Assuming 'uid' is equal to field 'pw_uid'
99 from = (pw = getpwuid(uid)) ? pw->pw_name : "???";
100
101 fd = storemail(from);
9
Calling 'storemail'
102 for (eval = 0; *argv; ++argv) {
103 if ((ch = deliver(fd, *argv, lockfile)) != 0)
104 eval = ch;
105 }
106 exit(eval);
107}
108
109int
110storemail(char *from)
111{
112 FILE *fp = NULL((void *)0);
10
'fp' initialized to a null pointer value
113 time_t tval;
114 int fd, eline;
115 size_t len;
116 char *line, *tbuf;
117
118 if ((tbuf = strdup(_PATH_LOCTMP"/tmp/local.XXXXXXXXXX")) == NULL((void *)0))
11
Assuming the condition is false
12
Taking false branch
119 merr(EX_OSERR71, "unable to allocate memory");
120 if ((fd = mkstemp(tbuf)) == -1 || !(fp = fdopen(fd, "w+")))
13
Assuming the condition is true
121 merr(EX_OSERR71, "unable to open temporary file");
122 (void)unlink(tbuf);
123 free(tbuf);
124
125 (void)time(&tval);
126 (void)fprintf(fp, "From %s %s", from, ctime(&tval));
127
128 for (eline = 1, tbuf = NULL((void *)0); (line = fgetln(stdin(&__sF[0]), &len));) {
14
Loop condition is false. Execution continues on line 152
129 /* We have to NUL-terminate the line since fgetln does not */
130 if (line[len - 1] == '\n')
131 line[len - 1] = '\0';
132 else {
133 /* No trailing newline, so alloc space and copy */
134 if ((tbuf = malloc(len + 1)) == NULL((void *)0))
135 merr(EX_OSERR71, "unable to allocate memory");
136 memcpy(tbuf, line, len);
137 tbuf[len] = '\0';
138 line = tbuf;
139 }
140 if (line[0] == '\0')
141 eline = 1;
142 else {
143 if (eline && line[0] == 'F' && len > 5 &&
144 !memcmp(line, "From ", 5))
145 (void)putc('>', fp)(!__isthreaded ? __sputc('>', fp) : (putc)('>', fp));
146 eline = 0;
147 }
148 (void)fprintf(fp, "%s\n", line);
149 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
150 break;
151 }
152 free(tbuf);
153
154 /* Output a newline; note, empty messages are allowed. */
155 (void)putc('\n', fp)(!__isthreaded ? __sputc('\n', fp) : (putc)('\n', fp));
15
Assuming '__isthreaded' is 0
16
'?' condition is true
17
Passing null pointer value via 2nd parameter '_p'
18
Calling '__sputc'
156 (void)fflush(fp);
157 if (ferror(fp)(!__isthreaded ? (((fp)->_flags & 0x0040) != 0) : (ferror
)(fp))
)
158 merr(EX_OSERR71, "temporary file write error");
159 return(fd);
160}
161
162int
163deliver(int fd, char *name, int lockfile)
164{
165 struct stat sb, fsb;
166 struct passwd *pw;
167 int mbfd=-1, lfd=-1, rval=EX_OSERR71;
168 char biffmsg[100], buf[8*1024], path[PATH_MAX1024];
169 off_t curoff;
170 size_t off;
171 ssize_t nr, nw;
172
173 /*
174 * Disallow delivery to unknown names -- special mailboxes can be
175 * handled in the sendmail aliases file.
176 */
177 if (!(pw = getpwnam(name))) {
178 mwarn("unknown name: %s", name);
179 return(EX_NOUSER67);
180 }
181
182 (void)snprintf(path, sizeof path, "%s/%s", _PATH_MAILDIR"/var/mail", name);
183
184 if (lockfile) {
185 lfd = lockspool(name, pw);
186 if (lfd == -1)
187 return(EX_OSERR71);
188 }
189
190 /* after this point, always exit via bad to remove lockfile */
191retry:
192 if (lstat(path, &sb)) {
193 if (errno(*__errno()) != ENOENT2) {
194 mwarn("%s: %s", path, strerror(errno(*__errno())));
195 goto bad;
196 }
197 if ((mbfd = open(path, O_APPEND0x0008|O_CREAT0x0200|O_EXCL0x0800|O_WRONLY0x0001|O_EXLOCK0x0020,
198 S_IRUSR0000400|S_IWUSR0000200)) == -1) {
199 if (errno(*__errno()) == EEXIST17) {
200 /* file appeared since lstat */
201 goto retry;
202 } else {
203 mwarn("%s: %s", path, strerror(errno(*__errno())));
204 rval = EX_CANTCREAT73;
205 goto bad;
206 }
207 }
208 /*
209 * Set the owner and group. Historically, binmail repeated
210 * this at each mail delivery. We no longer do this, assuming
211 * that if the ownership or permissions were changed there
212 * was a reason for doing so.
213 */
214 if (fchown(mbfd, pw->pw_uid, pw->pw_gid) == -1) {
215 mwarn("chown %u:%u: %s", pw->pw_uid, pw->pw_gid, name);
216 goto bad;
217 }
218 } else {
219 if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode)((sb.st_mode & 0170000) == 0100000)) {
220 mwarn("%s: linked or special file", path);
221 goto bad;
222 }
223 if ((mbfd = open(path, O_APPEND0x0008|O_WRONLY0x0001|O_EXLOCK0x0020,
224 S_IRUSR0000400|S_IWUSR0000200)) == -1) {
225 mwarn("%s: %s", path, strerror(errno(*__errno())));
226 goto bad;
227 }
228 if (fstat(mbfd, &fsb) == -1) {
229 /* relating error to path may be bad style */
230 mwarn("%s: %s", path, strerror(errno(*__errno())));
231 goto bad;
232 }
233 if (sb.st_dev != fsb.st_dev || sb.st_ino != fsb.st_ino) {
234 mwarn("%s: changed after open", path);
235 goto bad;
236 }
237 /* paranoia? */
238 if (fsb.st_nlink != 1 || !S_ISREG(fsb.st_mode)((fsb.st_mode & 0170000) == 0100000)) {
239 mwarn("%s: linked or special file", path);
240 rval = EX_CANTCREAT73;
241 goto bad;
242 }
243 }
244
245 curoff = lseek(mbfd, 0, SEEK_END2);
246 (void)snprintf(biffmsg, sizeof biffmsg, "%s@%lld\n", name, curoff);
247 if (lseek(fd, 0, SEEK_SET0) == (off_t)-1) {
248 mwarn("temporary file: %s", strerror(errno(*__errno())));
249 goto bad;
250 }
251
252 while ((nr = read(fd, buf, sizeof(buf))) > 0)
253 for (off = 0; off < nr; off += nw)
254 if ((nw = write(mbfd, buf + off, nr - off)) == -1) {
255 mwarn("%s: %s", path, strerror(errno(*__errno())));
256 (void)ftruncate(mbfd, curoff);
257 goto bad;
258 }
259
260 if (nr == 0) {
261 rval = 0;
262 } else {
263 (void)ftruncate(mbfd, curoff);
264 mwarn("temporary file: %s", strerror(errno(*__errno())));
265 }
266
267bad:
268 if (lfd != -1)
269 unlockspool();
270
271 if (mbfd != -1) {
272 (void)fsync(mbfd); /* Don't wait for update. */
273 (void)close(mbfd); /* Implicit unlock. */
274 }
275
276 if (!rval)
277 notifybiff(biffmsg);
278 return(rval);
279}
280
281void
282notifybiff(char *msg)
283{
284 static struct addrinfo *res0;
285 struct addrinfo hints, *res;
286 static int f = -1;
287 size_t len;
288 int error;
289
290 if (res0 == NULL((void *)0)) {
291 memset(&hints, 0, sizeof(hints));
292 hints.ai_family = PF_UNSPEC0;
293 hints.ai_socktype = SOCK_DGRAM2;
294
295 error = getaddrinfo("localhost", "biff", &hints, &res0);
296 if (error) {
297 /* Be silent if biff service not available. */
298 if (error != EAI_SERVICE-8) {
299 mwarn("localhost: %s", gai_strerror(error));
300 }
301 return;
302 }
303 }
304
305 if (f == -1) {
306 for (res = res0; res != NULL((void *)0); res = res->ai_next) {
307 f = socket(res->ai_family, res->ai_socktype,
308 res->ai_protocol);
309 if (f != -1)
310 break;
311 }
312 }
313 if (f == -1) {
314 mwarn("socket: %s", strerror(errno(*__errno())));
315 return;
316 }
317
318 len = strlen(msg) + 1; /* XXX */
319 if (sendto(f, msg, len, 0, res->ai_addr, res->ai_addrlen) != len)
320 mwarn("sendto biff: %s", strerror(errno(*__errno())));
321}
322
323static int lockfd = -1;
324static pid_t lockpid = -1;
325
326int
327lockspool(const char *name, struct passwd *pw)
328{
329 int pfd[2];
330 char ch;
331
332 if (geteuid() == 0)
333 return getlock(name, pw);
334
335 /* If not privileged, open pipe to lockspool(1) instead */
336 if (pipe2(pfd, O_CLOEXEC0x10000) == -1) {
337 merr(EX_OSERR71, "pipe: %s", strerror(errno(*__errno())));
338 return -1;
339 }
340
341 signal(SIGPIPE13, SIG_IGN(void (*)(int))1);
342 switch ((lockpid = fork())) {
343 case -1:
344 merr(EX_OSERR71, "fork: %s", strerror(errno(*__errno())));
345 return -1;
346 case 0:
347 /* child */
348 close(pfd[0]);
349 dup2(pfd[1], STDOUT_FILENO1);
350 execl(_PATH_LOCKSPOOL"/usr/libexec/lockspool", "lockspool", (char *)NULL((void *)0));
351 merr(EX_OSERR71, "execl: lockspool: %s", strerror(errno(*__errno())));
352 /* NOTREACHED */
353 break;
354 default:
355 /* parent */
356 close(pfd[1]);
357 lockfd = pfd[0];
358 break;
359 }
360
361 if (read(lockfd, &ch, 1) != 1 || ch != '1') {
362 unlockspool();
363 merr(EX_OSERR71, "lockspool: unable to get lock");
364 }
365
366 return lockfd;
367}
368
369void
370unlockspool(void)
371{
372 if (lockpid != -1) {
373 waitpid(lockpid, NULL((void *)0), 0);
374 lockpid = -1;
375 } else {
376 rellock();
377 }
378 close(lockfd);
379 lockfd = -1;
380}
381
382void
383usage(void)
384{
385 merr(EX_USAGE64, "usage: mail.local [-Ll] [-f from] user ...");
386}

/usr/include/stdio.h

1/* $OpenBSD: stdio.h,v 1.54 2020/09/11 17:56:41 naddy Exp $ */
2/* $NetBSD: stdio.h,v 1.18 1996/04/25 18:29:21 jtc Exp $ */
3
4/*-
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Chris Torek.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * @(#)stdio.h 5.17 (Berkeley) 6/3/91
36 */
37
38#ifndef _STDIO_H_
39#define _STDIO_H_
40
41#include <sys/cdefs.h>
42#include <sys/_null.h>
43#include <sys/_types.h>
44
45#if __BSD_VISIBLE1 || __POSIX_VISIBLE200809 || __XPG_VISIBLE700
46#include <sys/types.h> /* XXX should be removed */
47#endif
48
49#ifndef _SIZE_T_DEFINED_
50#define _SIZE_T_DEFINED_
51typedef __size_t size_t;
52#endif
53
54#ifndef _OFF_T_DEFINED_
55#define _OFF_T_DEFINED_
56typedef __off_t off_t;
57#endif
58
59#define _FSTDIO /* Define for new stdio with functions. */
60
61typedef off_t fpos_t; /* stdio file position type */
62
63/*
64 * NB: to fit things in six character monocase externals, the stdio
65 * code uses the prefix `__s' for stdio objects, typically followed
66 * by a three-character attempt at a mnemonic.
67 */
68
69/* stdio buffers */
70struct __sbuf {
71 unsigned char *_base;
72 int _size;
73};
74
75/*
76 * stdio state variables.
77 *
78 * The following always hold:
79 *
80 * if (_flags&(__SLBF|__SWR)) == (__SLBF|__SWR),
81 * _lbfsize is -_bf._size, else _lbfsize is 0
82 * if _flags&__SRD, _w is 0
83 * if _flags&__SWR, _r is 0
84 *
85 * This ensures that the getc and putc macros (or inline functions) never
86 * try to write or read from a file that is in `read' or `write' mode.
87 * (Moreover, they can, and do, automatically switch from read mode to
88 * write mode, and back, on "r+" and "w+" files.)
89 *
90 * _lbfsize is used only to make the inline line-buffered output stream
91 * code as compact as possible.
92 *
93 * _ub, _up, and _ur are used when ungetc() pushes back more characters
94 * than fit in the current _bf, or when ungetc() pushes back a character
95 * that does not match the previous one in _bf. When this happens,
96 * _ub._base becomes non-nil (i.e., a stream has ungetc() data iff
97 * _ub._base!=NULL) and _up and _ur save the current values of _p and _r.
98 */
99typedef struct __sFILE {
100 unsigned char *_p; /* current position in (some) buffer */
101 int _r; /* read space left for getc() */
102 int _w; /* write space left for putc() */
103 short _flags; /* flags, below; this FILE is free if 0 */
104 short _file; /* fileno, if Unix descriptor, else -1 */
105 struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */
106 int _lbfsize; /* 0 or -_bf._size, for inline putc */
107
108 /* operations */
109 void *_cookie; /* cookie passed to io functions */
110 int (*_close)(void *);
111 int (*_read)(void *, char *, int);
112 fpos_t (*_seek)(void *, fpos_t, int);
113 int (*_write)(void *, const char *, int);
114
115 /* extension data, to avoid further ABI breakage */
116 struct __sbuf _ext;
117 /* data for long sequences of ungetc() */
118 unsigned char *_up; /* saved _p when _p is doing ungetc data */
119 int _ur; /* saved _r when _r is counting ungetc data */
120
121 /* tricks to meet minimum requirements even when malloc() fails */
122 unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */
123 unsigned char _nbuf[1]; /* guarantee a getc() buffer */
124
125 /* separate buffer for fgetln() when line crosses buffer boundary */
126 struct __sbuf _lb; /* buffer for fgetln() */
127
128 /* Unix stdio files get aligned to block boundaries on fseek() */
129 int _blksize; /* stat.st_blksize (may be != _bf._size) */
130 fpos_t _offset; /* current lseek offset */
131} FILE;
132
133__BEGIN_DECLS
134extern FILE __sF[];
135__END_DECLS
136
137#define __SLBF0x0001 0x0001 /* line buffered */
138#define __SNBF0x0002 0x0002 /* unbuffered */
139#define __SRD0x0004 0x0004 /* OK to read */
140#define __SWR0x0008 0x0008 /* OK to write */
141 /* RD and WR are never simultaneously asserted */
142#define __SRW0x0010 0x0010 /* open for reading & writing */
143#define __SEOF0x0020 0x0020 /* found EOF */
144#define __SERR0x0040 0x0040 /* found error */
145#define __SMBF0x0080 0x0080 /* _buf is from malloc */
146#define __SAPP0x0100 0x0100 /* fdopen()ed in append mode */
147#define __SSTR0x0200 0x0200 /* this is an sprintf/snprintf string */
148#define __SOPT0x0400 0x0400 /* do fseek() optimisation */
149#define __SNPT0x0800 0x0800 /* do not do fseek() optimisation */
150#define __SOFF0x1000 0x1000 /* set iff _offset is in fact correct */
151#define __SMOD0x2000 0x2000 /* true => fgetln modified _p text */
152#define __SALC0x4000 0x4000 /* allocate string space dynamically */
153#define __SIGN0x8000 0x8000 /* ignore this file in _fwalk */
154
155/*
156 * The following three definitions are for ANSI C, which took them
157 * from System V, which brilliantly took internal interface macros and
158 * made them official arguments to setvbuf(), without renaming them.
159 * Hence, these ugly _IOxxx names are *supposed* to appear in user code.
160 *
161 * Although numbered as their counterparts above, the implementation
162 * does not rely on this.
163 */
164#define _IOFBF0 0 /* setvbuf should set fully buffered */
165#define _IOLBF1 1 /* setvbuf should set line buffered */
166#define _IONBF2 2 /* setvbuf should set unbuffered */
167
168#define BUFSIZ1024 1024 /* size of buffer used by setbuf */
169
170#define EOF(-1) (-1)
171
172/*
173 * FOPEN_MAX is a minimum maximum, and should be the number of descriptors
174 * that the kernel can provide without allocation of a resource that can
175 * fail without the process sleeping. Do not use this for anything.
176 */
177#define FOPEN_MAX20 20 /* must be <= OPEN_MAX <sys/syslimits.h> */
178#define FILENAME_MAX1024 1024 /* must be <= PATH_MAX <sys/syslimits.h> */
179
180/* System V/ANSI C; this is the wrong way to do this, do *not* use these. */
181#if __BSD_VISIBLE1 || __XPG_VISIBLE700
182#define P_tmpdir"/tmp/" "/tmp/"
183#endif
184#define L_tmpnam1024 1024 /* XXX must be == PATH_MAX */
185#define TMP_MAX0x7fffffff 0x7fffffff /* more, but don't overflow int */
186
187#ifndef SEEK_SET0
188#define SEEK_SET0 0 /* set file offset to offset */
189#endif
190#ifndef SEEK_CUR1
191#define SEEK_CUR1 1 /* set file offset to current plus offset */
192#endif
193#ifndef SEEK_END2
194#define SEEK_END2 2 /* set file offset to EOF plus offset */
195#endif
196
197#define stdin(&__sF[0]) (&__sF[0])
198#define stdout(&__sF[1]) (&__sF[1])
199#define stderr(&__sF[2]) (&__sF[2])
200
201/*
202 * Functions defined in ANSI C standard.
203 */
204__BEGIN_DECLS
205void clearerr(FILE *)(!__isthreaded ? ((void)((FILE *)->_flags &= ~(0x0040|
0x0020))) : (clearerr)(FILE *))
;
206#if __POSIX_VISIBLE200809 >= 200809
207int dprintf(int, const char * __restrict, ...)
208 __attribute__((__format__ (printf, 2, 3)))
209 __attribute__((__nonnull__ (2)));
210#endif
211int fclose(FILE *);
212int feof(FILE *)(!__isthreaded ? (((FILE *)->_flags & 0x0020) != 0) : (
feof)(FILE *))
;
213int ferror(FILE *)(!__isthreaded ? (((FILE *)->_flags & 0x0040) != 0) : (
ferror)(FILE *))
;
214int fflush(FILE *);
215int fgetc(FILE *);
216int fgetpos(FILE *, fpos_t *);
217char *fgets(char *, int, FILE *)
218 __attribute__((__bounded__ (__string__,1,2)));
219FILE *fopen(const char *, const char *);
220int fprintf(FILE *, const char *, ...);
221int fputc(int, FILE *);
222int fputs(const char *, FILE *);
223size_t fread(void *, size_t, size_t, FILE *)
224 __attribute__((__bounded__ (__size__,1,3,2)));
225FILE *freopen(const char *, const char *, FILE *);
226int fscanf(FILE *, const char *, ...);
227int fseek(FILE *, long, int);
228int fseeko(FILE *, off_t, int);
229int fsetpos(FILE *, const fpos_t *);
230long ftell(FILE *);
231off_t ftello(FILE *);
232size_t fwrite(const void *, size_t, size_t, FILE *)
233 __attribute__((__bounded__ (__size__,1,3,2)));
234int getc(FILE *)(!__isthreaded ? (--(FILE *)->_r < 0 ? __srget(FILE *) :
(int)(*(FILE *)->_p++)) : (getc)(FILE *))
;
235int getchar(void);
236#if __POSIX_VISIBLE200809 >= 200809
237ssize_t getdelim(char ** __restrict, size_t * __restrict, int,
238 FILE * __restrict);
239ssize_t getline(char ** __restrict, size_t * __restrict,
240 FILE * __restrict);
241#endif
242#if __BSD_VISIBLE1 && !defined(__SYS_ERRLIST)
243#define __SYS_ERRLIST
244
245extern int sys_nerr; /* perror(3) external variables */
246extern char *sys_errlist[];
247#endif
248void perror(const char *);
249int printf(const char *, ...);
250int putc(int, FILE *)(!__isthreaded ? __sputc(int, FILE *) : (putc)(int, FILE *));
251int putchar(int)(!__isthreaded ? __sputc(int, (&__sF[1])) : (putc)(int, (
&__sF[1])))
;
252int puts(const char *);
253int remove(const char *);
254int rename(const char *, const char *);
255#if __POSIX_VISIBLE200809 >= 200809
256int renameat(int, const char *, int, const char *);
257#endif
258void rewind(FILE *);
259int scanf(const char *, ...);
260void setbuf(FILE *, char *);
261int setvbuf(FILE *, char *, int, size_t);
262int sprintf(char *, const char *, ...);
263int sscanf(const char *, const char *, ...);
264FILE *tmpfile(void);
265char *tmpnam(char *);
266int ungetc(int, FILE *);
267int vfprintf(FILE *, const char *, __va_list);
268int vprintf(const char *, __va_list);
269int vsprintf(char *, const char *, __va_list);
270#if __POSIX_VISIBLE200809 >= 200809
271int vdprintf(int, const char * __restrict, __va_list)
272 __attribute__((__format__ (printf, 2, 0)))
273 __attribute__((__nonnull__ (2)));
274#endif
275
276#if __ISO_C_VISIBLE2011 >= 1999 || __XPG_VISIBLE700 >= 500 || __BSD_VISIBLE1
277int snprintf(char *, size_t, const char *, ...)
278 __attribute__((__format__ (printf, 3, 4)))
279 __attribute__((__nonnull__ (3)))
280 __attribute__((__bounded__ (__string__,1,2)));
281int vsnprintf(char *, size_t, const char *, __va_list)
282 __attribute__((__format__ (printf, 3, 0)))
283 __attribute__((__nonnull__ (3)))
284 __attribute__((__bounded__(__string__,1,2)));
285#endif /* __ISO_C_VISIBLE >= 1999 || __XPG_VISIBLE >= 500 || __BSD_VISIBLE */
286
287#if __ISO_C_VISIBLE2011 >= 1999 || __BSD_VISIBLE1
288int vfscanf(FILE *, const char *, __va_list)
289 __attribute__((__format__ (scanf, 2, 0)))
290 __attribute__((__nonnull__ (2)));
291int vscanf(const char *, __va_list)
292 __attribute__((__format__ (scanf, 1, 0)))
293 __attribute__((__nonnull__ (1)));
294int vsscanf(const char *, const char *, __va_list)
295 __attribute__((__format__ (scanf, 2, 0)))
296 __attribute__((__nonnull__ (2)));
297#endif /* __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE */
298
299__END_DECLS
300
301
302/*
303 * Functions defined in POSIX 1003.1.
304 */
305#if __BSD_VISIBLE1 || __POSIX_VISIBLE200809 || __XPG_VISIBLE700
306#define L_ctermid1024 1024 /* size for ctermid(); PATH_MAX */
307
308__BEGIN_DECLS
309char *ctermid(char *);
310FILE *fdopen(int, const char *);
311int fileno(FILE *)(!__isthreaded ? ((FILE *)->_file) : (fileno)(FILE *));
312
313#if __POSIX_VISIBLE200809 >= 199209
314int pclose(FILE *);
315FILE *popen(const char *, const char *);
316#endif
317
318#if __POSIX_VISIBLE200809 >= 199506
319void flockfile(FILE *);
320int ftrylockfile(FILE *);
321void funlockfile(FILE *);
322
323/*
324 * These are normally used through macros as defined below, but POSIX
325 * requires functions as well.
326 */
327int getc_unlocked(FILE *)(--(FILE *)->_r < 0 ? __srget(FILE *) : (int)(*(FILE *)
->_p++))
;
328int getchar_unlocked(void);
329int putc_unlocked(int, FILE *)__sputc(int, FILE *);
330int putchar_unlocked(int)__sputc(int, (&__sF[1]));
331#endif /* __POSIX_VISIBLE >= 199506 */
332
333#if __POSIX_VISIBLE200809 >= 200809
334FILE *fmemopen(void *, size_t, const char *);
335FILE *open_memstream(char **, size_t *);
336#endif /* __POSIX_VISIBLE >= 200809 */
337
338#if __XPG_VISIBLE700
339char *tempnam(const char *, const char *);
340#endif
341__END_DECLS
342
343#endif /* __BSD_VISIBLE || __POSIX_VISIBLE || __XPG_VISIBLE */
344
345/*
346 * Routines that are purely local.
347 */
348#if __BSD_VISIBLE1
349__BEGIN_DECLS
350int asprintf(char **, const char *, ...)
351 __attribute__((__format__ (printf, 2, 3)))
352 __attribute__((__nonnull__ (2)));
353char *fgetln(FILE *, size_t *);
354int fpurge(FILE *);
355int getw(FILE *);
356int putw(int, FILE *);
357void setbuffer(FILE *, char *, int);
358int setlinebuf(FILE *);
359int vasprintf(char **, const char *, __va_list)
360 __attribute__((__format__ (printf, 2, 0)))
361 __attribute__((__nonnull__ (2)));
362__END_DECLS
363
364/*
365 * Stdio function-access interface.
366 */
367__BEGIN_DECLS
368FILE *funopen(const void *,
369 int (*)(void *, char *, int),
370 int (*)(void *, const char *, int),
371 fpos_t (*)(void *, fpos_t, int),
372 int (*)(void *));
373__END_DECLS
374#define fropen(cookie, fn)funopen(cookie, fn, 0, 0, 0) funopen(cookie, fn, 0, 0, 0)
375#define fwopen(cookie, fn)funopen(cookie, 0, fn, 0, 0) funopen(cookie, 0, fn, 0, 0)
376#endif /* __BSD_VISIBLE */
377
378/*
379 * Functions internal to the implementation.
380 */
381__BEGIN_DECLS
382int __srget(FILE *);
383int __swbuf(int, FILE *);
384__END_DECLS
385
386/*
387 * The __sfoo macros are here so that we can
388 * define function versions in the C library.
389 */
390#define __sgetc(p)(--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++)) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
391static __inline int __sputc(int _c, FILE *_p) {
392 if (--_p->_w >= 0 || (_p->_w >= _p->_lbfsize && (char)_c != '\n'))
19
Access to field '_w' results in a dereference of a null pointer (loaded from variable '_p')
393 return (*_p->_p++ = _c);
394 else
395 return (__swbuf(_c, _p));
396}
397
398#define __sfeof(p)(((p)->_flags & 0x0020) != 0) (((p)->_flags & __SEOF0x0020) != 0)
399#define __sferror(p)(((p)->_flags & 0x0040) != 0) (((p)->_flags & __SERR0x0040) != 0)
400#define __sclearerr(p)((void)((p)->_flags &= ~(0x0040|0x0020))) ((void)((p)->_flags &= ~(__SERR0x0040|__SEOF0x0020)))
401#define __sfileno(p)((p)->_file) ((p)->_file)
402
403extern int __isthreaded;
404
405#define feof(p)(!__isthreaded ? (((p)->_flags & 0x0020) != 0) : (feof
)(p))
(!__isthreaded ? __sfeof(p)(((p)->_flags & 0x0020) != 0) : (feof)(p))
406#define ferror(p)(!__isthreaded ? (((p)->_flags & 0x0040) != 0) : (ferror
)(p))
(!__isthreaded ? __sferror(p)(((p)->_flags & 0x0040) != 0) : (ferror)(p))
407#define clearerr(p)(!__isthreaded ? ((void)((p)->_flags &= ~(0x0040|0x0020
))) : (clearerr)(p))
(!__isthreaded ? __sclearerr(p)((void)((p)->_flags &= ~(0x0040|0x0020))) : (clearerr)(p))
408
409#if __POSIX_VISIBLE200809
410#define fileno(p)(!__isthreaded ? ((p)->_file) : (fileno)(p)) (!__isthreaded ? __sfileno(p)((p)->_file) : (fileno)(p))
411#endif
412
413#define getc(fp)(!__isthreaded ? (--(fp)->_r < 0 ? __srget(fp) : (int)(
*(fp)->_p++)) : (getc)(fp))
(!__isthreaded ? __sgetc(fp)(--(fp)->_r < 0 ? __srget(fp) : (int)(*(fp)->_p++)) : (getc)(fp))
414
415#if __BSD_VISIBLE1
416/*
417 * The macro implementations of putc and putc_unlocked are not
418 * fully POSIX compliant; they do not set errno on failure
419 */
420#define putc(x, fp)(!__isthreaded ? __sputc(x, fp) : (putc)(x, fp)) (!__isthreaded ? __sputc(x, fp) : (putc)(x, fp))
421#endif /* __BSD_VISIBLE */
422
423#if __POSIX_VISIBLE200809 >= 199506
424#define getc_unlocked(fp)(--(fp)->_r < 0 ? __srget(fp) : (int)(*(fp)->_p++)) __sgetc(fp)(--(fp)->_r < 0 ? __srget(fp) : (int)(*(fp)->_p++))
425/*
426 * The macro implementations of putc and putc_unlocked are not
427 * fully POSIX compliant; they do not set errno on failure
428 */
429#if __BSD_VISIBLE1
430#define putc_unlocked(x, fp)__sputc(x, fp) __sputc(x, fp)
431#endif /* __BSD_VISIBLE */
432#endif /* __POSIX_VISIBLE >= 199506 */
433
434#define getchar()(!__isthreaded ? (--((&__sF[0]))->_r < 0 ? __srget(
(&__sF[0])) : (int)(*((&__sF[0]))->_p++)) : (getc)
((&__sF[0])))
getc(stdin)(!__isthreaded ? (--((&__sF[0]))->_r < 0 ? __srget(
(&__sF[0])) : (int)(*((&__sF[0]))->_p++)) : (getc)
((&__sF[0])))
435#define putchar(x)(!__isthreaded ? __sputc(x, (&__sF[1])) : (putc)(x, (&
__sF[1])))
putc(x, stdout)(!__isthreaded ? __sputc(x, (&__sF[1])) : (putc)(x, (&
__sF[1])))
436#define getchar_unlocked()(--((&__sF[0]))->_r < 0 ? __srget((&__sF[0])) :
(int)(*((&__sF[0]))->_p++))
getc_unlocked(stdin)(--((&__sF[0]))->_r < 0 ? __srget((&__sF[0])) :
(int)(*((&__sF[0]))->_p++))
437#define putchar_unlocked(c)__sputc(c, (&__sF[1])) putc_unlocked(c, stdout)__sputc(c, (&__sF[1]))
438
439#endif /* _STDIO_H_ */