]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/rpcbind/rpcbind.c
fix line wrap.
[FreeBSD/FreeBSD.git] / usr.sbin / rpcbind / rpcbind.c
1 /*      $NetBSD: rpcbind.c,v 1.1 2000/06/02 23:15:42 fvdl Exp $ */
2 /*      $FreeBSD$ */
3
4 /*
5  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
6  * unrestricted use provided that this legend is included on all tape
7  * media and as a part of the software program in whole or part.  Users
8  * may copy or modify Sun RPC without charge, but are not authorized
9  * to license or distribute it to anyone else except as part of a product or
10  * program developed by the user.
11  * 
12  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
13  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
14  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
15  * 
16  * Sun RPC is provided with no support and without any obligation on the
17  * part of Sun Microsystems, Inc. to assist in its use, correction,
18  * modification or enhancement.
19  * 
20  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
21  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
22  * OR ANY PART THEREOF.
23  * 
24  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
25  * or profits or other special, indirect and consequential damages, even if
26  * Sun has been advised of the possibility of such damages.
27  * 
28  * Sun Microsystems, Inc.
29  * 2550 Garcia Avenue
30  * Mountain View, California  94043
31  */
32 /*
33  * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
34  */
35
36 /* #ident       "@(#)rpcbind.c  1.19    94/04/25 SMI" */
37
38 #if 0
39 #ifndef lint
40 static  char sccsid[] = "@(#)rpcbind.c 1.35 89/04/21 Copyr 1984 Sun Micro";
41 #endif
42 #endif
43
44 /*
45  * rpcbind.c
46  * Implements the program, version to address mapping for rpc.
47  *
48  */
49
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <sys/errno.h>
53 #include <sys/time.h>
54 #include <sys/resource.h>
55 #include <sys/wait.h>
56 #include <sys/signal.h>
57 #include <sys/socket.h>
58 #include <sys/un.h>
59 #include <rpc/rpc.h>
60 #ifdef PORTMAP
61 #include <netinet/in.h>
62 #endif
63 #include <netdb.h>
64 #include <stdio.h>
65 #include <netconfig.h>
66 #include <stdlib.h>
67 #include <unistd.h>
68 #include <syslog.h>
69 #include <err.h>
70 #include <libutil.h>
71 #include <pwd.h>
72 #include <string.h>
73 #include <errno.h>
74 #include "rpcbind.h"
75
76 /* Global variables */
77 int debugging = 0;      /* Tell me what's going on */
78 int doabort = 0;        /* When debugging, do an abort on errors */
79 rpcblist_ptr list_rbl;  /* A list of version 3/4 rpcbind services */
80
81 /* who to suid to if -s is given */
82 #define RUN_AS  "daemon"
83
84 int runasdaemon = 0;
85 int insecure = 0;
86 int oldstyle_local = 0;
87 int verboselog = 0;
88
89 char **hosts = NULL;
90 int nhosts = 0;
91 int on = 1;
92
93 #ifdef WARMSTART
94 /* Local Variable */
95 static int warmstart = 0;       /* Grab a old copy of registrations */
96 #endif
97
98 #ifdef PORTMAP
99 struct pmaplist *list_pml;      /* A list of version 2 rpcbind services */
100 char *udptrans;         /* Name of UDP transport */
101 char *tcptrans;         /* Name of TCP transport */
102 char *udp_uaddr;        /* Universal UDP address */
103 char *tcp_uaddr;        /* Universal TCP address */
104 #endif
105 static char servname[] = "rpcbind";
106 static char superuser[] = "superuser";
107
108 int main __P((int, char *[]));
109
110 static int init_transport __P((struct netconfig *));
111 static void rbllist_add __P((rpcprog_t, rpcvers_t, struct netconfig *,
112                              struct netbuf *));
113 static void terminate __P((int));
114 static void parseargs __P((int, char *[]));
115
116 int
117 main(int argc, char *argv[])
118 {
119         struct netconfig *nconf;
120         void *nc_handle;        /* Net config handle */
121         struct rlimit rl;
122
123         parseargs(argc, argv);
124
125         getrlimit(RLIMIT_NOFILE, &rl);
126         if (rl.rlim_cur < 128) {
127                 if (rl.rlim_max <= 128)
128                         rl.rlim_cur = rl.rlim_max;
129                 else
130                         rl.rlim_cur = 128;
131                 setrlimit(RLIMIT_NOFILE, &rl);
132         }
133         openlog("rpcbind", LOG_CONS, LOG_DAEMON);
134         if (geteuid()) { /* This command allowed only to root */
135                 fprintf(stderr, "Sorry. You are not superuser\n");
136                 exit(1);
137         }
138         nc_handle = setnetconfig();     /* open netconfig file */
139         if (nc_handle == NULL) {
140                 syslog(LOG_ERR, "could not read /etc/netconfig");
141                 exit(1);
142         }
143 #ifdef PORTMAP
144         udptrans = "";
145         tcptrans = "";
146 #endif
147
148         nconf = getnetconfigent("unix");
149         if (nconf == NULL) {
150                 syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
151                 exit(1);
152         }
153         init_transport(nconf);
154
155         while ((nconf = getnetconfig(nc_handle))) {
156                 if (nconf->nc_flag & NC_VISIBLE)
157                         init_transport(nconf);
158         }
159         endnetconfig(nc_handle);
160
161         /* catch the usual termination signals for graceful exit */
162         (void) signal(SIGCHLD, reap);
163         (void) signal(SIGINT, terminate);
164         (void) signal(SIGTERM, terminate);
165         (void) signal(SIGQUIT, terminate);
166         /* ignore others that could get sent */
167         (void) signal(SIGPIPE, SIG_IGN);
168         (void) signal(SIGHUP, SIG_IGN);
169         (void) signal(SIGUSR1, SIG_IGN);
170         (void) signal(SIGUSR2, SIG_IGN);
171 #ifdef WARMSTART
172         if (warmstart) {
173                 read_warmstart();
174         }
175 #endif
176         if (debugging) {
177                 printf("rpcbind debugging enabled.");
178                 if (doabort) {
179                         printf("  Will abort on errors!\n");
180                 } else {
181                         printf("\n");
182                 }
183         } else {
184                 if (daemon(0, 0))
185                         err(1, "fork failed");
186         }
187
188         if (runasdaemon) {
189                 struct passwd *p;
190
191                 if((p = getpwnam(RUN_AS)) == NULL) {
192                         syslog(LOG_ERR, "cannot get uid of daemon: %m");
193                         exit(1);
194                 }
195                 if (setuid(p->pw_uid) == -1) {
196                         syslog(LOG_ERR, "setuid to daemon failed: %m");
197                         exit(1);
198                 }
199         }
200
201         network_init();
202
203         my_svc_run();
204         syslog(LOG_ERR, "svc_run returned unexpectedly");
205         rpcbind_abort();
206         /* NOTREACHED */
207
208         return 0;
209 }
210
211 /*
212  * Adds the entry into the rpcbind database.
213  * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
214  * Returns 0 if succeeds, else fails
215  */
216 static int
217 init_transport(struct netconfig *nconf)
218 {
219         int fd;
220         struct t_bind taddr;
221         struct addrinfo hints, *res = NULL;
222         struct __rpc_sockinfo si;
223         SVCXPRT *my_xprt;
224         int status;     /* bound checking ? */
225         int aicode;
226         int addrlen;
227         int nhostsbak;
228         int checkbind;
229         struct sockaddr *sa;
230         u_int32_t host_addr[4];  /* IPv4 or IPv6 */
231         struct sockaddr_un sun;
232         mode_t oldmask;
233
234         if ((nconf->nc_semantics != NC_TPI_CLTS) &&
235                 (nconf->nc_semantics != NC_TPI_COTS) &&
236                 (nconf->nc_semantics != NC_TPI_COTS_ORD))
237                 return (1);     /* not my type */
238 #ifdef ND_DEBUG
239         if (debugging) {
240                 int i;
241                 char **s;
242
243                 (void) fprintf(stderr, "%s: %ld lookup routines :\n",
244                         nconf->nc_netid, nconf->nc_nlookups);
245                 for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
246                      i++, s++)
247                         fprintf(stderr, "[%d] - %s\n", i, *s);
248         }
249 #endif
250
251         /*
252          * XXX - using RPC library internal functions. For NC_TPI_CLTS
253          * we call this later, for each socket we like to bind.
254          */
255         if (nconf->nc_semantics != NC_TPI_CLTS) {
256                 if ((fd = __rpc_nconf2fd(nconf)) < 0) {
257                         syslog(LOG_ERR, "cannot create socket for %s",
258                             nconf->nc_netid);
259                         return (1);
260                 }
261         }
262
263         if (!__rpc_nconf2sockinfo(nconf, &si)) {
264                 syslog(LOG_ERR, "cannot get information for %s",
265                     nconf->nc_netid);
266                 return (1);
267         }
268
269         if (!strcmp(nconf->nc_netid, "unix")) {
270                 memset(&sun, 0, sizeof sun);
271                 sun.sun_family = AF_LOCAL;
272                 unlink(_PATH_RPCBINDSOCK);
273                 strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
274                 sun.sun_len = SUN_LEN(&sun);
275                 addrlen = sizeof (struct sockaddr_un);
276                 sa = (struct sockaddr *)&sun;
277         } else {
278                 /* Get rpcbind's address on this transport */
279
280                 memset(&hints, 0, sizeof hints);
281                 hints.ai_flags = AI_PASSIVE;
282                 hints.ai_family = si.si_af;
283                 hints.ai_socktype = si.si_socktype;
284                 hints.ai_protocol = si.si_proto;
285         }
286         if (nconf->nc_semantics == NC_TPI_CLTS) {
287                 /*
288                  * If no hosts were specified, just bind to INADDR_ANY.  Otherwise
289                  * make sure 127.0.0.1 is added to the list.
290                  */
291                 nhostsbak = nhosts;
292                 nhostsbak++;
293                 hosts = realloc(hosts, nhostsbak * sizeof(char *));
294                 if (nhostsbak == 1)
295                         hosts[0] = "*";
296                 else {
297                         if (hints.ai_family == AF_INET) {
298                                 hosts[nhostsbak - 1] = "127.0.0.1";
299                         } else if (hints.ai_family == AF_INET6) {
300                                 hosts[nhostsbak - 1] = "::1";
301                         } else
302                                 return 1;
303                 }
304
305                /*
306                 * Bind to specific IPs if asked to
307                 */
308                 checkbind = 1;
309                 while (nhostsbak > 0) {
310                         --nhostsbak;
311                         /*
312                          * XXX - using RPC library internal functions.
313                          */
314                         if ((fd = __rpc_nconf2fd(nconf)) < 0) {
315                                 syslog(LOG_ERR, "cannot create socket for %s",
316                                     nconf->nc_netid);
317                                 return (1);
318                         }
319                         switch (hints.ai_family) {
320                         case AF_INET:
321                                 if (inet_pton(AF_INET, hosts[nhostsbak],
322                                     host_addr) == 1) {
323                                         hints.ai_flags &= AI_NUMERICHOST;
324                                 } else {
325                                         /*
326                                          * Skip if we have a AF_INET6 adress
327                                          */
328                                         if (inet_pton(AF_INET6,
329                                             hosts[nhostsbak], host_addr) == 1)
330                                                 continue;
331                                 }
332                                 break;
333                         case AF_INET6:
334                                 if (inet_pton(AF_INET6, hosts[nhostsbak],
335                                     host_addr) == 1) {
336                                         hints.ai_flags &= AI_NUMERICHOST;
337                                 } else {
338                                         /*
339                                          * Skip if we have a AF_INET adress
340                                          */
341                                         if (inet_pton(AF_INET, hosts[nhostsbak],
342                                             host_addr) == 1)
343                                                 continue;
344                                 }
345                                 if (setsockopt(fd, IPPROTO_IPV6,
346                                     IPV6_V6ONLY, &on, sizeof on) < 0) {
347                                         syslog(LOG_ERR,
348                                             "can't set v6-only binding for "
349                                             "udp6 socket: %m");
350                                         continue;
351                                 }
352                                 break;
353                         default:
354                                 break;
355                         }
356
357                         /*
358                          * If no hosts were specified, just bind to INADDR_ANY
359                          */
360                         if (strcmp("*", hosts[nhostsbak]) == 0)
361                                 hosts[nhostsbak] = NULL;
362
363                         if ((aicode = getaddrinfo(hosts[nhostsbak],
364                             servname, &hints, &res)) != 0) {
365                                 syslog(LOG_ERR,
366                                     "cannot get local address for %s: %s",
367                                     nconf->nc_netid, gai_strerror(aicode));
368                                 continue;
369                         }
370                         addrlen = res->ai_addrlen;
371                         sa = (struct sockaddr *)res->ai_addr;
372                         oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
373                         if (bind(fd, sa, addrlen) != 0) {
374                                 syslog(LOG_ERR, "cannot bind %s on %s: %m",
375                                         (hosts[nhostsbak] == NULL) ? "*" :
376                                         hosts[nhostsbak], nconf->nc_netid);
377                                 if (res != NULL)
378                                         freeaddrinfo(res);
379                                 continue;
380                         } else
381                                 checkbind++;
382                         (void) umask(oldmask);
383
384                         /* Copy the address */
385                         taddr.addr.len = taddr.addr.maxlen = addrlen;
386                         taddr.addr.buf = malloc(addrlen);
387                         if (taddr.addr.buf == NULL) {
388                                 syslog(LOG_ERR,
389                                     "cannot allocate memory for %s address",
390                                     nconf->nc_netid);
391                                 if (res != NULL)
392                                         freeaddrinfo(res);
393                                 return 1;
394                         }
395                         memcpy(taddr.addr.buf, sa, addrlen);
396 #ifdef ND_DEBUG
397                         if (debugging) {
398                                 /*
399                                  * for debugging print out our universal
400                                  * address
401                                  */
402                                 char *uaddr;
403                                 struct netbuf nb;
404
405                                 nb.buf = sa;
406                                 nb.len = nb.maxlen = sa->sa_len;
407                                 uaddr = taddr2uaddr(nconf, &nb);
408                                 (void) fprintf(stderr,
409                                     "rpcbind : my address is %s\n", uaddr);
410                                 (void) free(uaddr);
411                         }
412 #endif
413
414                         if (nconf->nc_semantics != NC_TPI_CLTS)
415                                 listen(fd, SOMAXCONN);
416
417                         my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
418                             0, 0);
419                         if (my_xprt == (SVCXPRT *)NULL) {
420                                 syslog(LOG_ERR, "%s: could not create service",
421                                         nconf->nc_netid);
422                                 goto error;
423                         }
424                 }
425                 if (!checkbind)
426                         return 1;
427         } else {
428                 if (strcmp(nconf->nc_netid, "unix") != 0) {
429                         if ((aicode = getaddrinfo(NULL, servname, &hints, &res))
430                             != 0) {
431                                 syslog(LOG_ERR,
432                                     "cannot get local address for %s: %s",
433                                     nconf->nc_netid, gai_strerror(aicode));
434                                 return 1;
435                         }
436                         addrlen = res->ai_addrlen;
437                         sa = (struct sockaddr *)res->ai_addr;
438                 }
439                 oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
440                 if (bind(fd, sa, addrlen) < 0) {
441                         syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
442                         if (res != NULL)
443                                 freeaddrinfo(res);
444                         return 1;
445                 }
446                 (void) umask(oldmask);
447
448                 /* Copy the address */
449                 taddr.addr.len = taddr.addr.maxlen = addrlen;
450                 taddr.addr.buf = malloc(addrlen);
451                 if (taddr.addr.buf == NULL) {
452                         syslog(LOG_ERR, "cannot allocate memory for %s address",
453                             nconf->nc_netid);
454                         if (res != NULL)
455                                 freeaddrinfo(res);
456                         return 1;
457                 }
458                 memcpy(taddr.addr.buf, sa, addrlen);
459 #ifdef ND_DEBUG
460                 if (debugging) {
461                         /* for debugging print out our universal address */
462                         char *uaddr;
463                         struct netbuf nb;
464
465                         nb.buf = sa;
466                         nb.len = nb.maxlen = sa->sa_len;
467                         uaddr = taddr2uaddr(nconf, &nb);
468                         (void) fprintf(stderr, "rpcbind : my address is %s\n",
469                             uaddr);
470                         (void) free(uaddr);
471                 }
472 #endif
473
474                 if (nconf->nc_semantics != NC_TPI_CLTS)
475                         listen(fd, SOMAXCONN);
476
477                 my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, 0, 0);
478                 if (my_xprt == (SVCXPRT *)NULL) {
479                         syslog(LOG_ERR, "%s: could not create service",
480                                         nconf->nc_netid);
481                         goto error;
482                 }
483         }
484
485 #ifdef PORTMAP
486         /*
487          * Register both the versions for tcp/ip, udp/ip and local.
488          */
489         if ((strcmp(nconf->nc_protofmly, NC_INET) == 0 &&
490                 (strcmp(nconf->nc_proto, NC_TCP) == 0 ||
491                 strcmp(nconf->nc_proto, NC_UDP) == 0)) ||
492                 strcmp(nconf->nc_netid, "unix") == 0) {
493                 struct pmaplist *pml;
494
495                 if (!svc_register(my_xprt, PMAPPROG, PMAPVERS,
496                         pmap_service, NULL)) {
497                         syslog(LOG_ERR, "could not register on %s",
498                                         nconf->nc_netid);
499                         goto error;
500                 }
501                 pml = malloc(sizeof (struct pmaplist));
502                 if (pml == NULL) {
503                         syslog(LOG_ERR, "no memory!");
504                         exit(1);
505                 }
506                 pml->pml_map.pm_prog = PMAPPROG;
507                 pml->pml_map.pm_vers = PMAPVERS;
508                 pml->pml_map.pm_port = PMAPPORT;
509                 if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
510                         if (tcptrans[0]) {
511                                 syslog(LOG_ERR,
512                                 "cannot have more than one TCP transport");
513                                 goto error;
514                         }
515                         tcptrans = strdup(nconf->nc_netid);
516                         pml->pml_map.pm_prot = IPPROTO_TCP;
517
518                         /* Let's snarf the universal address */
519                         /* "h1.h2.h3.h4.p1.p2" */
520                         tcp_uaddr = taddr2uaddr(nconf, &taddr.addr);
521                 } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
522                         if (udptrans[0]) {
523                                 syslog(LOG_ERR,
524                                 "cannot have more than one UDP transport");
525                                 goto error;
526                         }
527                         udptrans = strdup(nconf->nc_netid);
528                         pml->pml_map.pm_prot = IPPROTO_UDP;
529
530                         /* Let's snarf the universal address */
531                         /* "h1.h2.h3.h4.p1.p2" */
532                         udp_uaddr = taddr2uaddr(nconf, &taddr.addr);
533                 } else if (strcmp(nconf->nc_netid, "unix") == 0)
534                         pml->pml_map.pm_prot = IPPROTO_ST;
535                 pml->pml_next = list_pml;
536                 list_pml = pml;
537
538                 /* Add version 3 information */
539                 pml = malloc(sizeof (struct pmaplist));
540                 if (pml == NULL) {
541                         syslog(LOG_ERR, "no memory!");
542                         exit(1);
543                 }
544                 pml->pml_map = list_pml->pml_map;
545                 pml->pml_map.pm_vers = RPCBVERS;
546                 pml->pml_next = list_pml;
547                 list_pml = pml;
548
549                 /* Add version 4 information */
550                 pml = malloc (sizeof (struct pmaplist));
551                 if (pml == NULL) {
552                         syslog(LOG_ERR, "no memory!");
553                         exit(1);
554                 }
555                 pml->pml_map = list_pml->pml_map;
556                 pml->pml_map.pm_vers = RPCBVERS4;
557                 pml->pml_next = list_pml;
558                 list_pml = pml;
559
560                 /* Also add version 2 stuff to rpcbind list */
561                 rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
562         }
563 #endif
564
565         /* version 3 registration */
566         if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
567                 syslog(LOG_ERR, "could not register %s version 3",
568                                 nconf->nc_netid);
569                 goto error;
570         }
571         rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
572
573         /* version 4 registration */
574         if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
575                 syslog(LOG_ERR, "could not register %s version 4",
576                                 nconf->nc_netid);
577                 goto error;
578         }
579         rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
580
581         /* decide if bound checking works for this transport */
582         status = add_bndlist(nconf, &taddr.addr);
583 #ifdef BIND_DEBUG
584         if (debugging) {
585                 if (status < 0) {
586                         fprintf(stderr, "Error in finding bind status for %s\n",
587                                 nconf->nc_netid);
588                 } else if (status == 0) {
589                         fprintf(stderr, "check binding for %s\n",
590                                 nconf->nc_netid);
591                 } else if (status > 0) {
592                         fprintf(stderr, "No check binding for %s\n",
593                                 nconf->nc_netid);
594                 }
595         }
596 #endif
597         /*
598          * rmtcall only supported on CLTS transports for now.
599          */
600         if (nconf->nc_semantics == NC_TPI_CLTS) {
601                 status = create_rmtcall_fd(nconf);
602
603 #ifdef BIND_DEBUG
604                 if (debugging) {
605                         if (status < 0) {
606                                 fprintf(stderr,
607                                     "Could not create rmtcall fd for %s\n",
608                                         nconf->nc_netid);
609                         } else {
610                                 fprintf(stderr, "rmtcall fd for %s is %d\n",
611                                         nconf->nc_netid, status);
612                         }
613                 }
614 #endif
615         }
616         return (0);
617 error:
618         close(fd);
619         return (1);
620 }
621
622 static void
623 rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
624             struct netbuf *addr)
625 {
626         rpcblist_ptr rbl;
627
628         rbl = malloc(sizeof (rpcblist));
629         if (rbl == NULL) {
630                 syslog(LOG_ERR, "no memory!");
631                 exit(1);
632         }
633
634         rbl->rpcb_map.r_prog = prog;
635         rbl->rpcb_map.r_vers = vers;
636         rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
637         rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
638         rbl->rpcb_map.r_owner = strdup(superuser);
639         rbl->rpcb_next = list_rbl;      /* Attach to global list */
640         list_rbl = rbl;
641 }
642
643 /*
644  * Catch the signal and die
645  */
646 static void
647 terminate(int dummy)
648 {
649 #ifdef WARMSTART
650         syslog(LOG_ERR,
651                 "rpcbind terminating on signal. Restart with \"rpcbind -w\"");
652         write_warmstart();      /* Dump yourself */
653 #endif
654         exit(2);
655 }
656
657 void
658 rpcbind_abort()
659 {
660 #ifdef WARMSTART
661         write_warmstart();      /* Dump yourself */
662 #endif
663         abort();
664 }
665
666 /* get command line options */
667 static void
668 parseargs(int argc, char *argv[])
669 {
670         int c;
671
672         while ((c = getopt(argc, argv, "dwah:ilLs")) != -1) {
673                 switch (c) {
674                 case 'a':
675                         doabort = 1;    /* when debugging, do an abort on */
676                         break;          /* errors; for rpcbind developers */
677                                         /* only! */
678                 case 'd':
679                         debugging = 1;
680                         break;
681                 case 'h':
682                         ++nhosts;
683                         hosts = realloc(hosts, nhosts * sizeof(char *));
684                         if (hosts == NULL)
685                                 errx(1, "Out of memory");
686                         hosts[nhosts - 1] = strdup(optarg);
687                         if (hosts[nhosts - 1] == NULL)
688                                 errx(1, "Out of memory");
689                         break;
690                 case 'i':
691                         insecure = 1;
692                         break;
693                 case 'L':
694                         oldstyle_local = 1;
695                         break;
696                 case 'l':
697                         verboselog = 1;
698                         break;
699                 case 's':
700                         runasdaemon = 1;
701                         break;
702 #ifdef WARMSTART
703                 case 'w':
704                         warmstart = 1;
705                         break;
706 #endif
707                 default:        /* error */
708                         fprintf(stderr, "usage: rpcbind [-Idwils]\n");
709                         exit (1);
710                 }
711         }
712         if (doabort && !debugging) {
713             fprintf(stderr,
714                 "-a (abort) specified without -d (debugging) -- ignored.\n");
715             doabort = 0;
716         }
717 }
718
719 void
720 reap(int dummy)
721 {
722         int save_errno = errno;
723  
724         while (wait3(NULL, WNOHANG, NULL) > 0)
725                 ;       
726         errno = save_errno;
727 }
728
729 void
730 toggle_verboselog(int dummy)
731 {
732         verboselog = !verboselog;
733 }