]>
git.saurik.com Git - apple/network_cmds.git/blob - rpc_statd.tproj/statd.c
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>
56 #include <sys/sysctl.h>
59 int debug
= 0; /* Controls syslog() calls for debug messages */
60 int notify_only
= 0; /* only send SM_NOTIFY messages */
61 const char *pid_file
= NULL
; /* name of any pid file that has been claimed */
63 extern void sm_prog_1(struct svc_req
*rqstp
, SVCXPRT
*transp
);
64 static void handle_sigchld(int sig
);
65 static void handle_sig_cleanup(int sig
);
66 static void cleanup_pid_file(void);
67 static void usage(void);
70 main(int argc
, char **argv
)
81 while ((c
= getopt(argc
, argv
, "dn")) != EOF
)
93 /* Install signal handler to remove any pid file */
94 signal(SIGINT
, handle_sig_cleanup
);
95 signal(SIGTERM
, handle_sig_cleanup
);
96 signal(SIGHUP
, handle_sig_cleanup
);
97 signal(SIGQUIT
, handle_sig_cleanup
);
99 init_file("/var/db/statd.status");
101 openlog("rpc.statd", 0, LOG_DAEMON
);
108 /* Note that it is NOT sensible to run this program from inetd - the */
109 /* protocol assumes that it will run immediately at boot time. */
113 mib
[1] = KERN_PROCDELAYTERM
;
119 if (sysctl(mib
, 2, &oldstate
, &oldsize
, &newstate
, 4) < 0) {
120 syslog(LOG_INFO
, "cannot mark pid for delayed termination");
124 if (claim_pid_file("/var/run/statd.pid", 0) < 0)
125 errx(1, "rpc.statd already running");
127 (void)pmap_unset(SM_PROG
, SM_VERS
);
129 transp
= svcudp_create(RPC_ANYSOCK
);
131 errx(1, "cannot create udp service");
132 if (!svc_register(transp
, SM_PROG
, SM_VERS
, sm_prog_1
, IPPROTO_UDP
))
133 errx(1, "unable to register (SM_PROG, SM_VERS, udp)");
135 transp
= svctcp_create(RPC_ANYSOCK
, 0, 0);
137 errx(1, "cannot create tcp service");
138 if (!svc_register(transp
, SM_PROG
, SM_VERS
, sm_prog_1
, IPPROTO_TCP
))
139 errx(1, "unable to register (SM_PROG, SM_VERS, tcp)");
141 if (debug
) syslog(LOG_INFO
, "Starting - debug enabled");
142 else syslog(LOG_INFO
, "Starting");
144 /* Install signal handler to collect exit status of child processes */
145 sa
.sa_handler
= handle_sigchld
;
146 sigemptyset(&sa
.sa_mask
);
147 sigaddset(&sa
.sa_mask
, SIGCHLD
);
148 sa
.sa_flags
= SA_RESTART
;
149 sigaction(SIGCHLD
, &sa
, NULL
);
151 /* Initialisation now complete - start operating */
152 notify_hosts(); /* Forks a process (if necessary) to do the */
153 /* SM_NOTIFY calls, which may be slow. */
155 svc_run(); /* Should never return */
162 fprintf(stderr
, "usage: rpc.statd [-dn]\n");
166 /* handle_sigchld ---------------------------------------------------------- */
168 Purpose: Catch SIGCHLD and collect process status
170 Notes: No special action required, other than to collect the
171 process status and hence allow the child to die:
172 we only use child processes for asynchronous transmission
173 of SM_NOTIFY to other systems, so it is normal for the
174 children to exit when they have done their work.
177 static void handle_sigchld(int sig __unused
)
180 pid
= wait4(-1, &status
, WNOHANG
, (struct rusage
*)0);
181 if (!pid
) syslog(LOG_ERR
, "Phantom SIGCHLD??");
182 else if (status
== 0)
184 if (debug
) syslog(LOG_DEBUG
, "Child %d exited OK", pid
);
186 else syslog(LOG_ERR
, "Child %d failed with status %d", pid
,
187 WEXITSTATUS(status
));
191 /* claim_pid_file ---------------------------------------------------------- */
193 Purpose: take ownership of and store pid in given pid_file
194 Returns: 0 on success or -1 on failure
195 Notes: force parameter requests that current owner (if any) of
196 pid file be terminated.
200 claim_pid_file(const char *name
, int force
)
202 int pidfd
, rv
, retried
= 0;
207 /* attempt exclusive open of pid file */
208 pidfd
= open(name
, O_EXCL
|O_CREAT
|O_WRONLY
,
209 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
);
217 /* pid file busy, check validity */
218 pidfd
= open(name
, O_RDONLY
);
221 rv
= read(pidfd
, buf
, 15);
228 rv
= kill(pid
, force
? SIGKILL
: 0);
229 /* if can't signal, assume stale pid file */
230 if ((rv
< 0) || force
)
235 atexit(cleanup_pid_file
);
237 pidfile
= fdopen(pidfd
, "w");
239 fchmod(pidfd
, S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
);
240 fprintf(pidfile
, "%d\n", getpid());
249 /* cleanup_pid_file -------------------------------------------------------- */
251 Purpose: delete any pid_file that has been claimed
256 cleanup_pid_file(void)
265 /* handle_sig_cleanup ------------------------------------------------------ */
267 Purpose: call pid file cleanup function on signal
272 handle_sig_cleanup(int sig __unused
)