]>
git.saurik.com Git - apple/network_cmds.git/blob - rpc_statd.tproj/statd.c
a0d24789b93c0ec4effc4214fef551a742c3fdb7
3 * A.R. Gordon (andrew.gordon@net-tel.co.uk). All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed for the FreeBSD project
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY ANDREW GORDON AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 static const char rcsid
[] =
39 /* main() function for status monitor daemon. Some of the code in this */
40 /* file was generated by running rpcgen /usr/include/rpcsvc/sm_inter.x */
41 /* The actual program logic is in the file procs.c */
47 #include <rpc/pmap_clnt.h>
50 #include <sys/types.h>
58 int debug
= 0; /* Controls syslog() calls for debug messages */
59 int notify_only
= 0; /* only send SM_NOTIFY messages */
60 const char *pid_file
= NULL
; /* name of any pid file that has been claimed */
62 extern void sm_prog_1(struct svc_req
*rqstp
, SVCXPRT
*transp
);
63 static void handle_sigchld(int sig
);
64 static void handle_sig_cleanup(int sig
);
65 static void cleanup_pid_file(void);
66 static void usage(void);
69 main(int argc
, char **argv
)
76 while ((c
= getopt(argc
, argv
, "dn")) != EOF
)
88 /* Install signal handler to remove any pid file */
89 signal(SIGINT
, handle_sig_cleanup
);
90 signal(SIGTERM
, handle_sig_cleanup
);
91 signal(SIGHUP
, handle_sig_cleanup
);
92 signal(SIGQUIT
, handle_sig_cleanup
);
94 init_file("/var/db/statd.status");
96 openlog("rpc.statd", 0, LOG_DAEMON
);
103 /* Note that it is NOT sensible to run this program from inetd - the */
104 /* protocol assumes that it will run immediately at boot time. */
107 if (claim_pid_file("/var/run/statd.pid", 0) < 0)
108 errx(1, "rpc.statd already running");
110 /* start portmapper, in case it hasn't been started yet */
112 /* sleep a little to give portmap a chance to start */
113 /* (better to sleep 50ms now than to timeout on portmap calls) */
115 ts
.tv_nsec
= 50*1000*1000;
116 nanosleep(&ts
, NULL
);
118 (void)pmap_unset(SM_PROG
, SM_VERS
);
120 transp
= svcudp_create(RPC_ANYSOCK
);
122 errx(1, "cannot create udp service");
123 if (!svc_register(transp
, SM_PROG
, SM_VERS
, sm_prog_1
, IPPROTO_UDP
))
124 errx(1, "unable to register (SM_PROG, SM_VERS, udp)");
126 transp
= svctcp_create(RPC_ANYSOCK
, 0, 0);
128 errx(1, "cannot create tcp service");
129 if (!svc_register(transp
, SM_PROG
, SM_VERS
, sm_prog_1
, IPPROTO_TCP
))
130 errx(1, "unable to register (SM_PROG, SM_VERS, tcp)");
132 if (debug
) syslog(LOG_INFO
, "Starting - debug enabled");
133 else syslog(LOG_INFO
, "Starting");
135 /* Install signal handler to collect exit status of child processes */
136 sa
.sa_handler
= handle_sigchld
;
137 sigemptyset(&sa
.sa_mask
);
138 sigaddset(&sa
.sa_mask
, SIGCHLD
);
139 sa
.sa_flags
= SA_RESTART
;
140 sigaction(SIGCHLD
, &sa
, NULL
);
142 /* Initialisation now complete - start operating */
143 notify_hosts(); /* Forks a process (if necessary) to do the */
144 /* SM_NOTIFY calls, which may be slow. */
146 svc_run(); /* Should never return */
153 fprintf(stderr
, "usage: rpc.statd [-dn]\n");
157 /* handle_sigchld ---------------------------------------------------------- */
159 Purpose: Catch SIGCHLD and collect process status
161 Notes: No special action required, other than to collect the
162 process status and hence allow the child to die:
163 we only use child processes for asynchronous transmission
164 of SM_NOTIFY to other systems, so it is normal for the
165 children to exit when they have done their work.
168 static void handle_sigchld(int sig __unused
)
171 pid
= wait4(-1, &status
, WNOHANG
, (struct rusage
*)0);
172 if (!pid
) syslog(LOG_ERR
, "Phantom SIGCHLD??");
173 else if (status
== 0)
175 if (debug
) syslog(LOG_DEBUG
, "Child %d exited OK", pid
);
177 else syslog(LOG_ERR
, "Child %d failed with status %d", pid
,
178 WEXITSTATUS(status
));
182 /* claim_pid_file ---------------------------------------------------------- */
184 Purpose: take ownership of and store pid in given pid_file
185 Returns: 0 on success or -1 on failure
186 Notes: force parameter requests that current owner (if any) of
187 pid file be terminated.
191 claim_pid_file(const char *name
, int force
)
193 int pidfd
, rv
, retried
= 0;
198 /* attempt exclusive open of pid file */
199 pidfd
= open(name
, O_EXCL
|O_CREAT
|O_WRONLY
,
200 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
);
208 /* pid file busy, check validity */
209 pidfd
= open(name
, O_RDONLY
);
212 rv
= read(pidfd
, buf
, 15);
219 rv
= kill(pid
, force
? SIGKILL
: 0);
220 /* if can't signal, assume stale pid file */
221 if ((rv
< 0) || force
)
226 atexit(cleanup_pid_file
);
228 pidfile
= fdopen(pidfd
, "w");
230 fchmod(pidfd
, S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
);
231 fprintf(pidfile
, "%d\n", getpid());
240 /* cleanup_pid_file -------------------------------------------------------- */
242 Purpose: delete any pid_file that has been claimed
247 cleanup_pid_file(void)
256 /* handle_sig_cleanup ------------------------------------------------------ */
258 Purpose: call pid file cleanup function on signal
263 handle_sig_cleanup(int sig __unused
)