clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ypserv.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/usr.sbin/ypserv/ypserv/obj -resource-dir /usr/local/lib/clang/13.0.0 -D DAEMON -D OPTDB -I /usr/src/usr.sbin/ypserv/ypserv/../common -I . -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/usr.sbin/ypserv/ypserv/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/usr.sbin/ypserv/ypserv/ypserv.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | #include <sys/types.h> |
30 | #include <sys/socket.h> |
31 | #include <sys/ioctl.h> |
32 | #include <netinet/in.h> |
33 | #include <rpcsvc/yp.h> |
34 | #include "ypv1.h" |
35 | #include <stdio.h> |
36 | #include <stdlib.h> |
37 | #include <string.h> |
38 | #include <netdb.h> |
39 | #include <signal.h> |
40 | #include <errno.h> |
41 | #include <util.h> |
42 | #include <unistd.h> |
43 | #include <fcntl.h> |
44 | #include <rpc/pmap_clnt.h> |
45 | #include <ndbm.h> |
46 | #include <syslog.h> |
47 | #include "acl.h" |
48 | #include "yplog.h" |
49 | #include "ypdef.h" |
50 | #include "ypserv.h" |
51 | #include <sys/wait.h> |
52 | |
53 | void ypdb_init(void); |
54 | |
55 | #ifdef DEBUG |
56 | #define RPC_SVC_FG |
57 | #endif |
58 | |
59 | #define _RPCSVC_CLOSEDOWN 120 |
60 | static int _rpcpmstart; |
61 | static int _rpcfdtype; |
62 | static int _rpcsvcdirty; |
63 | |
64 | int usedns = FALSE; |
65 | char *aclfile = NULL; |
66 | |
67 | void sig_child(int); |
68 | void sig_hup(int); |
69 | volatile sig_atomic_t wantsighup; |
70 | |
71 | static void |
72 | _msgout(char *msg) |
73 | { |
74 | #ifdef RPC_SVC_FG |
75 | if (_rpcpmstart) |
76 | syslog(LOG_ERR, "%s", msg); |
77 | else |
78 | (void) fprintf(stderr, "%s\n", msg); |
79 | #else |
80 | syslog(LOG_ERR, "%s", msg); |
81 | #endif |
82 | } |
83 | |
84 | |
85 | static void |
86 | closedown(int sig) |
87 | { |
88 | int save_errno = errno; |
89 | |
90 | if (_rpcsvcdirty == 0) { |
91 | int i, openfd; |
92 | |
93 | if (_rpcfdtype == SOCK_DGRAM) |
94 | exit(0); |
95 | for (i = 0, openfd = 0; i < svc_max_pollfd && openfd < 2; i++) |
96 | if (svc_pollfd[i].fd != -1) |
97 | openfd++; |
98 | if (openfd <= (_rpcpmstart ? 0 : 1)) |
99 | _exit(0); |
100 | } |
101 | (void) alarm(_RPCSVC_CLOSEDOWN); |
102 | errno = save_errno; |
103 | } |
104 | |
105 | static void |
106 | ypprog_1(struct svc_req *rqstp, SVCXPRT *transp) |
107 | { |
108 | union { |
109 | domainname ypoldproc_domain_1_arg; |
110 | domainname ypoldproc_domain_nonack_1_arg; |
111 | yprequest ypoldproc_match_1_arg; |
112 | yprequest ypoldproc_first_1_arg; |
113 | yprequest ypoldproc_next_1_arg; |
114 | yprequest ypoldproc_poll_1_arg; |
115 | yprequest ypoldproc_push_1_arg; |
116 | yprequest ypoldproc_pull_1_arg; |
117 | yprequest ypoldproc_get_1_arg; |
118 | } argument; |
119 | char *result; |
120 | xdrproc_t xdr_argument, xdr_result; |
121 | char *(*local)(char *, struct svc_req *); |
122 | |
123 | _rpcsvcdirty = 1; |
124 | switch (rqstp->rq_proc) { |
125 | case YPOLDPROC_NULL: |
126 | xdr_argument = (xdrproc_t) xdr_void; |
127 | xdr_result = (xdrproc_t) xdr_void; |
128 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_null_1_svc; |
129 | break; |
130 | |
131 | case YPOLDPROC_DOMAIN: |
132 | xdr_argument = (xdrproc_t) xdr_domainname; |
133 | xdr_result = (xdrproc_t) xdr_bool; |
134 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_domain_1_svc; |
135 | break; |
136 | |
137 | case YPOLDPROC_DOMAIN_NONACK: |
138 | xdr_argument = (xdrproc_t) xdr_domainname; |
139 | xdr_result = (xdrproc_t) xdr_bool; |
140 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_domain_nonack_1_svc; |
141 | break; |
142 | |
143 | case YPOLDPROC_MATCH: |
144 | xdr_argument = (xdrproc_t) xdr_yprequest; |
145 | xdr_result = (xdrproc_t) xdr_ypresponse; |
146 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_match_1_svc; |
147 | break; |
148 | |
149 | case YPOLDPROC_FIRST: |
150 | xdr_argument = (xdrproc_t) xdr_yprequest; |
151 | xdr_result = (xdrproc_t) xdr_ypresponse; |
152 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_first_1_svc; |
153 | break; |
154 | |
155 | case YPOLDPROC_NEXT: |
156 | xdr_argument = (xdrproc_t) xdr_yprequest; |
157 | xdr_result = (xdrproc_t) xdr_ypresponse; |
158 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_next_1_svc; |
159 | break; |
160 | |
161 | case YPOLDPROC_POLL: |
162 | xdr_argument = (xdrproc_t) xdr_yprequest; |
163 | xdr_result = (xdrproc_t) xdr_ypresponse; |
164 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_poll_1_svc; |
165 | break; |
166 | |
167 | case YPOLDPROC_PUSH: |
168 | xdr_argument = (xdrproc_t) xdr_yprequest; |
169 | xdr_result = (xdrproc_t) xdr_void; |
170 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_push_1_svc; |
171 | break; |
172 | |
173 | case YPOLDPROC_PULL: |
174 | xdr_argument = (xdrproc_t) xdr_yprequest; |
175 | xdr_result = (xdrproc_t) xdr_void; |
176 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_pull_1_svc; |
177 | break; |
178 | |
179 | case YPOLDPROC_GET: |
180 | xdr_argument = (xdrproc_t) xdr_yprequest; |
181 | xdr_result = (xdrproc_t) xdr_void; |
182 | local = (char *(*)(char *, struct svc_req *)) ypoldproc_get_1_svc; |
183 | break; |
184 | |
185 | default: |
186 | svcerr_noproc(transp); |
187 | _rpcsvcdirty = 0; |
188 | return; |
189 | } |
190 | (void) memset(&argument, 0, sizeof(argument)); |
191 | if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { |
192 | svcerr_decode(transp); |
193 | _rpcsvcdirty = 0; |
194 | return; |
195 | } |
196 | result = (*local)((char *)&argument, rqstp); |
197 | if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { |
198 | svcerr_systemerr(transp); |
199 | } |
200 | if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { |
201 | _msgout("unable to free arguments"); |
202 | exit(1); |
203 | } |
204 | _rpcsvcdirty = 0; |
205 | } |
206 | |
207 | static void |
208 | ypprog_2(struct svc_req *rqstp, SVCXPRT *transp) |
209 | { |
210 | union { |
211 | domainname ypproc_domain_2_arg; |
212 | domainname ypproc_domain_nonack_2_arg; |
213 | ypreq_key ypproc_match_2_arg; |
214 | ypreq_nokey ypproc_first_2_arg; |
215 | ypreq_key ypproc_next_2_arg; |
216 | ypreq_xfr ypproc_xfr_2_arg; |
217 | ypreq_nokey ypproc_all_2_arg; |
218 | ypreq_nokey ypproc_master_2_arg; |
219 | ypreq_nokey ypproc_order_2_arg; |
220 | domainname ypproc_maplist_2_arg; |
221 | } argument; |
222 | char *result; |
223 | xdrproc_t xdr_argument, xdr_result; |
224 | char *(*local)(char *, struct svc_req *); |
225 | |
226 | _rpcsvcdirty = 1; |
227 | switch (rqstp->rq_proc) { |
228 | case YPPROC_NULL: |
229 | xdr_argument = (xdrproc_t) xdr_void; |
230 | xdr_result = (xdrproc_t) xdr_void; |
231 | local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc; |
232 | break; |
233 | |
234 | case YPPROC_DOMAIN: |
235 | xdr_argument = (xdrproc_t) xdr_domainname; |
236 | xdr_result = (xdrproc_t) xdr_bool; |
237 | local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc; |
238 | break; |
239 | |
240 | case YPPROC_DOMAIN_NONACK: |
241 | xdr_argument = (xdrproc_t) xdr_domainname; |
242 | xdr_result = (xdrproc_t) xdr_bool; |
243 | local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc; |
244 | break; |
245 | |
246 | case YPPROC_MATCH: |
247 | xdr_argument = (xdrproc_t) xdr_ypreq_key; |
248 | xdr_result = (xdrproc_t) xdr_ypresp_val; |
249 | local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc; |
250 | break; |
251 | |
252 | case YPPROC_FIRST: |
253 | xdr_argument = (xdrproc_t) xdr_ypreq_nokey; |
254 | xdr_result = (xdrproc_t) xdr_ypresp_key_val; |
255 | local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc; |
256 | break; |
257 | |
258 | case YPPROC_NEXT: |
259 | xdr_argument = (xdrproc_t) xdr_ypreq_key; |
260 | xdr_result = (xdrproc_t) xdr_ypresp_key_val; |
261 | local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc; |
262 | break; |
263 | |
264 | case YPPROC_XFR: |
265 | xdr_argument = (xdrproc_t) xdr_ypreq_xfr; |
266 | xdr_result = (xdrproc_t) xdr_ypresp_xfr; |
267 | local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc; |
268 | break; |
269 | |
270 | case YPPROC_CLEAR: |
271 | xdr_argument = (xdrproc_t) xdr_void; |
272 | xdr_result = (xdrproc_t) xdr_void; |
273 | local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc; |
274 | break; |
275 | |
276 | case YPPROC_ALL: |
277 | xdr_argument = (xdrproc_t) xdr_ypreq_nokey; |
278 | xdr_result = (xdrproc_t) xdr_ypresp_all; |
279 | local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc; |
280 | break; |
281 | |
282 | case YPPROC_MASTER: |
283 | xdr_argument = (xdrproc_t) xdr_ypreq_nokey; |
284 | xdr_result = (xdrproc_t) xdr_ypresp_master; |
285 | local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc; |
286 | break; |
287 | |
288 | case YPPROC_ORDER: |
289 | xdr_argument = (xdrproc_t) xdr_ypreq_nokey; |
290 | xdr_result = (xdrproc_t) xdr_ypresp_order; |
291 | local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc; |
292 | break; |
293 | |
294 | case YPPROC_MAPLIST: |
295 | xdr_argument = (xdrproc_t) xdr_domainname; |
296 | xdr_result = (xdrproc_t) xdr_ypresp_maplist; |
297 | local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc; |
298 | break; |
299 | |
300 | default: |
301 | svcerr_noproc(transp); |
302 | _rpcsvcdirty = 0; |
303 | return; |
304 | } |
305 | (void) memset(&argument, 0, sizeof(argument)); |
306 | if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { |
307 | svcerr_decode(transp); |
308 | _rpcsvcdirty = 0; |
309 | return; |
310 | } |
311 | result = (*local)((char *)&argument, rqstp); |
312 | if (result != NULL && !svc_sendreply(transp, xdr_result, result)) { |
313 | svcerr_systemerr(transp); |
314 | } |
315 | if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { |
316 | _msgout("unable to free arguments"); |
317 | exit(1); |
318 | } |
319 | _rpcsvcdirty = 0; |
320 | } |
321 | |
322 | static void |
323 | hup(void) |
324 | { |
325 | |
326 | ypcloselog(); |
327 | ypopenlog(); |
328 | |
329 | acl_reset(); |
330 | if (aclfile != NULL) { |
331 | yplog("sig_hup: reread %s", aclfile); |
332 | (void)acl_init(aclfile); |
333 | } else { |
334 | yplog("sig_hup: reread %s", YP_SECURENET_FILE); |
335 | (void)acl_securenet(YP_SECURENET_FILE); |
336 | } |
337 | |
338 | ypdb_close_all(); |
339 | } |
340 | |
341 | static void |
342 | my_svc_run(void) |
343 | { |
344 | struct pollfd *pfd = NULL, *newp; |
345 | int nready, saved_max_pollfd = 0; |
346 | |
347 | for (;;) { |
348 | if (wantsighup) { |
349 | wantsighup = 0; |
350 | hup(); |
351 | } |
352 | if (svc_max_pollfd > saved_max_pollfd) { |
353 | newp = reallocarray(pfd, svc_max_pollfd, sizeof(*pfd)); |
354 | if (newp == NULL) { |
355 | free(pfd); |
356 | perror("svc_run: - realloc failed"); |
357 | return; |
358 | } |
359 | pfd = newp; |
360 | saved_max_pollfd = svc_max_pollfd; |
361 | } |
362 | memcpy(pfd, svc_pollfd, sizeof(*pfd) * svc_max_pollfd); |
363 | |
364 | nready = poll(pfd, svc_max_pollfd, INFTIM); |
365 | switch (nready) { |
366 | case -1: |
367 | if (errno == EINTR) |
368 | continue; |
369 | perror("svc_run: - poll failed"); |
370 | free(pfd); |
371 | return; |
372 | case 0: |
373 | continue; |
374 | default: |
375 | svc_getreq_poll(pfd, nready); |
376 | } |
377 | } |
378 | } |
379 | |
380 | static void |
381 | usage(void) |
382 | { |
383 | (void)fprintf(stderr, "usage: ypserv [-1dx] [-a aclfile]\n"); |
384 | exit(1); |
385 | } |
386 | |
387 | int |
388 | main(int argc, char *argv[]) |
389 | { |
390 | int xflag = 0, allowv1 = 0, ch, sock, proto; |
| 1 | 'proto' declared without an initial value | |
|
391 | struct sockaddr_in saddr; |
392 | socklen_t asize = sizeof(saddr); |
393 | extern char *optarg; |
394 | SVCXPRT *transp = NULL; |
395 | |
396 | while ((ch = getopt(argc, argv, "1a:dx")) != -1) |
| 2 | | Assuming the condition is true | |
|
| 3 | | Loop condition is true. Entering loop body | |
|
| 6 | | Assuming the condition is false | |
|
| 7 | | Loop condition is false. Execution continues on line 415 | |
|
397 | switch (ch) { |
| 4 | | Control jumps to 'case 49:' at line 398 | |
|
398 | case '1': |
399 | allowv1 = TRUE; |
400 | break; |
| 5 | | Execution continues on line 396 | |
|
401 | case 'a': |
402 | aclfile = optarg; |
403 | break; |
404 | case 'd': |
405 | usedns = TRUE; |
406 | break; |
407 | case 'x': |
408 | xflag = TRUE; |
409 | break; |
410 | default: |
411 | usage(); |
412 | break; |
413 | } |
414 | |
415 | if (geteuid() != 0) { |
| 8 | | Assuming the condition is false | |
|
| |
416 | (void)fprintf(stderr, "ypserv: must be root to run.\n"); |
417 | exit(1); |
418 | } |
419 | |
420 | if (aclfile != NULL) |
| |
421 | (void)acl_init(aclfile); |
422 | else |
423 | (void)acl_securenet(YP_SECURENET_FILE); |
424 | |
425 | if (xflag) |
| |
426 | exit(1); |
427 | |
428 | if (getsockname(0, (struct sockaddr *)&saddr, &asize) == 0) { |
| 12 | | Assuming the condition is false | |
|
| |
429 | socklen_t ssize = sizeof(int); |
430 | |
431 | if (saddr.sin_family != AF_INET) |
432 | exit(1); |
433 | if (getsockopt(0, SOL_SOCKET, SO_TYPE, |
434 | &_rpcfdtype, &ssize) == -1) |
435 | exit(1); |
436 | sock = 0; |
437 | _rpcpmstart = 1; |
438 | proto = 0; |
439 | openlog("ypserv", LOG_PID, LOG_DAEMON); |
440 | } else { |
441 | #ifndef RPC_SVC_FG |
442 | int i; |
443 | pid_t pid; |
444 | |
445 | pid = fork(); |
446 | if (pid < 0) { |
| |
| |
447 | perror("cannot fork"); |
448 | exit(1); |
449 | } |
450 | if (pid) |
| |
| |
451 | exit(0); |
452 | closefrom(0); |
453 | i = open("/dev/console", O_RDWR); |
454 | (void) dup2(i, 1); |
455 | (void) dup2(i, 2); |
456 | i = open("/dev/tty", O_RDWR); |
457 | if (i >= 0) { |
| |
| |
458 | (void) ioctl(i, TIOCNOTTY, NULL); |
459 | (void) close(i); |
460 | } |
461 | openlog("ypserv", LOG_PID, LOG_DAEMON); |
462 | #endif |
463 | sock = RPC_ANYSOCK; |
464 | (void) pmap_unset(YPPROG, YPVERS); |
465 | (void) pmap_unset(YPPROG, YPOLDVERS); |
466 | } |
467 | |
468 | ypopenlog(); |
469 | ypdb_init(); |
470 | |
471 | chdir("/"); |
472 | |
473 | (void)signal(SIGCHLD, sig_child); |
474 | (void)signal(SIGHUP, sig_hup); |
475 | |
476 | if (_rpcfdtype == 0 || _rpcfdtype == SOCK_DGRAM) { |
| 20 | | Assuming '_rpcfdtype' is not equal to 0 | |
|
| 21 | | Assuming '_rpcfdtype' is not equal to SOCK_DGRAM | |
|
| |
477 | transp = svcudp_create(sock); |
478 | if (transp == NULL) { |
479 | _msgout("cannot create udp service."); |
480 | exit(1); |
481 | } |
482 | if (transp->xp_port >= IPPORT_RESERVED) { |
483 | _msgout("cannot allocate udp privileged port."); |
484 | exit(1); |
485 | } |
486 | if (!_rpcpmstart) |
487 | proto = IPPROTO_UDP; |
488 | if (allowv1) { |
489 | if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { |
490 | _msgout("unable to register (YPPROG, YPOLDVERS, udp)."); |
491 | exit(1); |
492 | } |
493 | } |
494 | if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { |
495 | _msgout("unable to register (YPPROG, YPVERS, udp)."); |
496 | exit(1); |
497 | } |
498 | } |
499 | |
500 | if (_rpcfdtype == 0 || _rpcfdtype == SOCK_STREAM) { |
| 23 | | Assuming '_rpcfdtype' is equal to SOCK_STREAM | |
|
| |
501 | if (_rpcpmstart) |
| 25 | | Assuming '_rpcpmstart' is not equal to 0 | |
|
| |
502 | transp = svcfd_create(sock, 0, 0); |
503 | else |
504 | transp = svctcp_create(sock, 0, 0); |
505 | if (transp == NULL) { |
| 27 | | Assuming 'transp' is not equal to NULL | |
|
| |
506 | _msgout("cannot create tcp service."); |
507 | exit(1); |
508 | } |
509 | if (transp->xp_port >= IPPORT_RESERVED) { |
| 29 | | Assuming field 'xp_port' is < IPPORT_RESERVED | |
|
| |
510 | _msgout("cannot allocate tcp privileged port."); |
511 | exit(1); |
512 | } |
513 | if (!_rpcpmstart) |
| |
514 | proto = IPPROTO_TCP; |
515 | if (allowv1) { |
| |
516 | if (!svc_register(transp, YPPROG, YPOLDVERS, ypprog_1, proto)) { |
| 33 | | 5th function call argument is an uninitialized value |
|
517 | _msgout("unable to register (YPPROG, YPOLDVERS, tcp)."); |
518 | exit(1); |
519 | } |
520 | } |
521 | if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, proto)) { |
522 | _msgout("unable to register (YPPROG, YPVERS, tcp)."); |
523 | exit(1); |
524 | } |
525 | } |
526 | |
527 | if (transp == NULL) { |
528 | _msgout("could not create a handle"); |
529 | exit(1); |
530 | } |
531 | if (_rpcpmstart) { |
532 | (void) signal(SIGALRM, closedown); |
533 | (void) alarm(_RPCSVC_CLOSEDOWN); |
534 | } |
535 | my_svc_run(); |
536 | _msgout("svc_run returned"); |
537 | exit(1); |
538 | |
539 | } |
540 | |
541 | |
542 | void |
543 | sig_child(int signo) |
544 | { |
545 | int save_errno = errno; |
546 | |
547 | while (wait3(NULL, WNOHANG, NULL) > 0) |
548 | ; |
549 | errno = save_errno; |
550 | } |
551 | |
552 | |
553 | void |
554 | sig_hup(int signo) |
555 | { |
556 | wantsighup = 1; |
557 | } |