xref: /netbsd-src/external/bsd/am-utils/dist/amd/nfs_start.c (revision a53f50b9b44dc9467ccc9c464999b1d1c509cb0c)
1*a53f50b9Schristos /*	$NetBSD: nfs_start.c,v 1.1.1.1 2008/09/19 20:07:16 christos Exp $	*/
2*a53f50b9Schristos 
3*a53f50b9Schristos /*
4*a53f50b9Schristos  * Copyright (c) 1997-2007 Erez Zadok
5*a53f50b9Schristos  * Copyright (c) 1990 Jan-Simon Pendry
6*a53f50b9Schristos  * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
7*a53f50b9Schristos  * Copyright (c) 1990 The Regents of the University of California.
8*a53f50b9Schristos  * All rights reserved.
9*a53f50b9Schristos  *
10*a53f50b9Schristos  * This code is derived from software contributed to Berkeley by
11*a53f50b9Schristos  * Jan-Simon Pendry at Imperial College, London.
12*a53f50b9Schristos  *
13*a53f50b9Schristos  * Redistribution and use in source and binary forms, with or without
14*a53f50b9Schristos  * modification, are permitted provided that the following conditions
15*a53f50b9Schristos  * are met:
16*a53f50b9Schristos  * 1. Redistributions of source code must retain the above copyright
17*a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer.
18*a53f50b9Schristos  * 2. Redistributions in binary form must reproduce the above copyright
19*a53f50b9Schristos  *    notice, this list of conditions and the following disclaimer in the
20*a53f50b9Schristos  *    documentation and/or other materials provided with the distribution.
21*a53f50b9Schristos  * 3. All advertising materials mentioning features or use of this software
22*a53f50b9Schristos  *    must display the following acknowledgment:
23*a53f50b9Schristos  *      This product includes software developed by the University of
24*a53f50b9Schristos  *      California, Berkeley and its contributors.
25*a53f50b9Schristos  * 4. Neither the name of the University nor the names of its contributors
26*a53f50b9Schristos  *    may be used to endorse or promote products derived from this software
27*a53f50b9Schristos  *    without specific prior written permission.
28*a53f50b9Schristos  *
29*a53f50b9Schristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
30*a53f50b9Schristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31*a53f50b9Schristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32*a53f50b9Schristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
33*a53f50b9Schristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34*a53f50b9Schristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35*a53f50b9Schristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36*a53f50b9Schristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37*a53f50b9Schristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38*a53f50b9Schristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39*a53f50b9Schristos  * SUCH DAMAGE.
40*a53f50b9Schristos  *
41*a53f50b9Schristos  *
42*a53f50b9Schristos  * File: am-utils/amd/nfs_start.c
43*a53f50b9Schristos  *
44*a53f50b9Schristos  */
45*a53f50b9Schristos 
46*a53f50b9Schristos #ifdef HAVE_CONFIG_H
47*a53f50b9Schristos # include <config.h>
48*a53f50b9Schristos #endif /* HAVE_CONFIG_H */
49*a53f50b9Schristos #include <am_defs.h>
50*a53f50b9Schristos #include <amd.h>
51*a53f50b9Schristos 
52*a53f50b9Schristos #ifndef SELECT_MAXWAIT
53*a53f50b9Schristos # define SELECT_MAXWAIT 16
54*a53f50b9Schristos #endif /* not SELECT_MAXWAIT */
55*a53f50b9Schristos 
56*a53f50b9Schristos SVCXPRT *nfsxprt = NULL;
57*a53f50b9Schristos u_short nfs_port = 0;
58*a53f50b9Schristos 
59*a53f50b9Schristos #ifndef HAVE_SIGACTION
60*a53f50b9Schristos # define MASKED_SIGS	(sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGCHLD)|sigmask(SIGHUP))
61*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
62*a53f50b9Schristos 
63*a53f50b9Schristos #ifdef DEBUG
64*a53f50b9Schristos /*
65*a53f50b9Schristos  * Check that we are not burning resources
66*a53f50b9Schristos  */
67*a53f50b9Schristos static void
68*a53f50b9Schristos checkup(void)
69*a53f50b9Schristos {
70*a53f50b9Schristos   static int max_fd = 0;
71*a53f50b9Schristos   static char *max_mem = NULL;
72*a53f50b9Schristos   int next_fd = dup(0);
73*a53f50b9Schristos   caddr_t next_mem = sbrk(0);
74*a53f50b9Schristos 
75*a53f50b9Schristos   close(next_fd);
76*a53f50b9Schristos 
77*a53f50b9Schristos   if (max_fd < next_fd) {
78*a53f50b9Schristos     dlog("%d new fds allocated; total is %d",
79*a53f50b9Schristos 	 next_fd - max_fd, next_fd);
80*a53f50b9Schristos     max_fd = next_fd;
81*a53f50b9Schristos   }
82*a53f50b9Schristos   if (max_mem < next_mem) {
83*a53f50b9Schristos #ifdef HAVE_GETPAGESIZE
84*a53f50b9Schristos     dlog("%#lx bytes of memory allocated; total is %#lx (%ld pages)",
85*a53f50b9Schristos 	 (long) (next_mem - max_mem), (unsigned long) next_mem,
86*a53f50b9Schristos 	 ((long) next_mem + getpagesize() - 1) / (long) getpagesize());
87*a53f50b9Schristos #else /* not HAVE_GETPAGESIZE */
88*a53f50b9Schristos     dlog("%#lx bytes of memory allocated; total is %#lx",
89*a53f50b9Schristos 	 (long) (next_mem - max_mem), (unsigned long) next_mem);
90*a53f50b9Schristos #endif /* not HAVE_GETPAGESIZE */
91*a53f50b9Schristos     max_mem = next_mem;
92*a53f50b9Schristos 
93*a53f50b9Schristos   }
94*a53f50b9Schristos }
95*a53f50b9Schristos #else  /* not DEBUG */
96*a53f50b9Schristos #define checkup()
97*a53f50b9Schristos #endif /* not DEBUG */
98*a53f50b9Schristos 
99*a53f50b9Schristos 
100*a53f50b9Schristos static int
101*a53f50b9Schristos #ifdef HAVE_SIGACTION
102*a53f50b9Schristos do_select(sigset_t smask, int fds, fd_set *fdp, struct timeval *tvp)
103*a53f50b9Schristos #else /* not HAVE_SIGACTION */
104*a53f50b9Schristos do_select(int smask, int fds, fd_set *fdp, struct timeval *tvp)
105*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
106*a53f50b9Schristos {
107*a53f50b9Schristos 
108*a53f50b9Schristos   int sig;
109*a53f50b9Schristos   int nsel;
110*a53f50b9Schristos 
111*a53f50b9Schristos   if ((sig = setjmp(select_intr))) {
112*a53f50b9Schristos     select_intr_valid = 0;
113*a53f50b9Schristos     /* Got a signal */
114*a53f50b9Schristos     switch (sig) {
115*a53f50b9Schristos     case SIGINT:
116*a53f50b9Schristos     case SIGTERM:
117*a53f50b9Schristos       amd_state = Finishing;
118*a53f50b9Schristos       reschedule_timeout_mp();
119*a53f50b9Schristos       break;
120*a53f50b9Schristos     }
121*a53f50b9Schristos     nsel = -1;
122*a53f50b9Schristos     errno = EINTR;
123*a53f50b9Schristos   } else {
124*a53f50b9Schristos     select_intr_valid = 1;
125*a53f50b9Schristos     /*
126*a53f50b9Schristos      * Allow interrupts.  If a signal
127*a53f50b9Schristos      * occurs, then it will cause a longjmp
128*a53f50b9Schristos      * up above.
129*a53f50b9Schristos      */
130*a53f50b9Schristos #ifdef HAVE_SIGACTION
131*a53f50b9Schristos     sigprocmask(SIG_SETMASK, &smask, NULL);
132*a53f50b9Schristos #else /* not HAVE_SIGACTION */
133*a53f50b9Schristos     (void) sigsetmask(smask);
134*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
135*a53f50b9Schristos 
136*a53f50b9Schristos     /*
137*a53f50b9Schristos      * Wait for input
138*a53f50b9Schristos      */
139*a53f50b9Schristos     nsel = select(fds, fdp, (fd_set *) NULL, (fd_set *) NULL,
140*a53f50b9Schristos 		  tvp->tv_sec ? tvp : (struct timeval *) NULL);
141*a53f50b9Schristos   }
142*a53f50b9Schristos 
143*a53f50b9Schristos #ifdef HAVE_SIGACTION
144*a53f50b9Schristos   sigprocmask(SIG_BLOCK, &masked_sigs, NULL);
145*a53f50b9Schristos #else /* not HAVE_SIGACTION */
146*a53f50b9Schristos   (void) sigblock(MASKED_SIGS);
147*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
148*a53f50b9Schristos 
149*a53f50b9Schristos   /*
150*a53f50b9Schristos    * Perhaps reload the cache?
151*a53f50b9Schristos    */
152*a53f50b9Schristos   if (do_mapc_reload < clocktime(NULL)) {
153*a53f50b9Schristos     mapc_reload();
154*a53f50b9Schristos     do_mapc_reload = clocktime(NULL) + gopt.map_reload_interval;
155*a53f50b9Schristos   }
156*a53f50b9Schristos   return nsel;
157*a53f50b9Schristos }
158*a53f50b9Schristos 
159*a53f50b9Schristos 
160*a53f50b9Schristos /*
161*a53f50b9Schristos  * Determine whether anything is left in
162*a53f50b9Schristos  * the RPC input queue.
163*a53f50b9Schristos  */
164*a53f50b9Schristos static int
165*a53f50b9Schristos rpc_pending_now(void)
166*a53f50b9Schristos {
167*a53f50b9Schristos   struct timeval tvv;
168*a53f50b9Schristos   int nsel;
169*a53f50b9Schristos   fd_set readfds;
170*a53f50b9Schristos 
171*a53f50b9Schristos   FD_ZERO(&readfds);
172*a53f50b9Schristos   FD_SET(fwd_sock, &readfds);
173*a53f50b9Schristos 
174*a53f50b9Schristos   tvv.tv_sec = tvv.tv_usec = 0;
175*a53f50b9Schristos   nsel = select(FD_SETSIZE, &readfds, (fd_set *) NULL, (fd_set *) NULL, &tvv);
176*a53f50b9Schristos   if (nsel < 1)
177*a53f50b9Schristos     return (0);
178*a53f50b9Schristos   if (FD_ISSET(fwd_sock, &readfds))
179*a53f50b9Schristos     return (1);
180*a53f50b9Schristos 
181*a53f50b9Schristos   return (0);
182*a53f50b9Schristos }
183*a53f50b9Schristos 
184*a53f50b9Schristos 
185*a53f50b9Schristos static serv_state
186*a53f50b9Schristos run_rpc(void)
187*a53f50b9Schristos {
188*a53f50b9Schristos #ifdef HAVE_SIGACTION
189*a53f50b9Schristos   sigset_t smask;
190*a53f50b9Schristos   sigprocmask(SIG_BLOCK, &masked_sigs, &smask);
191*a53f50b9Schristos #else /* not HAVE_SIGACTION */
192*a53f50b9Schristos   int smask = sigblock(MASKED_SIGS);
193*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
194*a53f50b9Schristos 
195*a53f50b9Schristos   next_softclock = clocktime(NULL);
196*a53f50b9Schristos 
197*a53f50b9Schristos   amd_state = Run;
198*a53f50b9Schristos 
199*a53f50b9Schristos   /*
200*a53f50b9Schristos    * Keep on trucking while we are in Run mode.  This state
201*a53f50b9Schristos    * is switched to Quit after all the file systems have
202*a53f50b9Schristos    * been unmounted.
203*a53f50b9Schristos    */
204*a53f50b9Schristos   while ((int) amd_state <= (int) Finishing) {
205*a53f50b9Schristos     struct timeval tvv;
206*a53f50b9Schristos     int nsel;
207*a53f50b9Schristos     time_t now;
208*a53f50b9Schristos     fd_set readfds;
209*a53f50b9Schristos 
210*a53f50b9Schristos #ifdef HAVE_SVC_GETREQSET
211*a53f50b9Schristos     memmove(&readfds, &svc_fdset, sizeof(svc_fdset));
212*a53f50b9Schristos #else /* not HAVE_SVC_GETREQSET */
213*a53f50b9Schristos     FD_ZERO(&readfds);
214*a53f50b9Schristos # ifdef HAVE_FD_SET_FDS_BITS
215*a53f50b9Schristos     readfds.fds_bits[0] = svc_fds;
216*a53f50b9Schristos # else /* not HAVE_FD_SET_FDS_BITS */
217*a53f50b9Schristos     readfds = svc_fds;
218*a53f50b9Schristos # endif  /* not HAVE_FD_SET_FDS_BITS */
219*a53f50b9Schristos #endif /* not HAVE_SVC_GETREQSET */
220*a53f50b9Schristos     FD_SET(fwd_sock, &readfds);
221*a53f50b9Schristos 
222*a53f50b9Schristos     checkup();
223*a53f50b9Schristos 
224*a53f50b9Schristos     /*
225*a53f50b9Schristos      * If the full timeout code is not called,
226*a53f50b9Schristos      * then recompute the time delta manually.
227*a53f50b9Schristos      */
228*a53f50b9Schristos     now = clocktime(NULL);
229*a53f50b9Schristos 
230*a53f50b9Schristos     if (next_softclock <= now) {
231*a53f50b9Schristos       if (amd_state == Finishing)
232*a53f50b9Schristos 	umount_exported();
233*a53f50b9Schristos       tvv.tv_sec = softclock();
234*a53f50b9Schristos     } else {
235*a53f50b9Schristos       tvv.tv_sec = next_softclock - now;
236*a53f50b9Schristos     }
237*a53f50b9Schristos     tvv.tv_usec = 0;
238*a53f50b9Schristos 
239*a53f50b9Schristos     if (amd_state == Finishing && get_exported_ap(0) == NULL) {
240*a53f50b9Schristos       flush_mntfs();
241*a53f50b9Schristos       amd_state = Quit;
242*a53f50b9Schristos       break;
243*a53f50b9Schristos     }
244*a53f50b9Schristos 
245*a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
246*a53f50b9Schristos     autofs_add_fdset(&readfds);
247*a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
248*a53f50b9Schristos 
249*a53f50b9Schristos     if (tvv.tv_sec <= 0)
250*a53f50b9Schristos       tvv.tv_sec = SELECT_MAXWAIT;
251*a53f50b9Schristos     if (tvv.tv_sec) {
252*a53f50b9Schristos       dlog("Select waits for %ds", (int) tvv.tv_sec);
253*a53f50b9Schristos     } else {
254*a53f50b9Schristos       dlog("Select waits for Godot");
255*a53f50b9Schristos     }
256*a53f50b9Schristos 
257*a53f50b9Schristos     nsel = do_select(smask, FD_SETSIZE, &readfds, &tvv);
258*a53f50b9Schristos 
259*a53f50b9Schristos     switch (nsel) {
260*a53f50b9Schristos     case -1:
261*a53f50b9Schristos       if (errno == EINTR) {
262*a53f50b9Schristos 	dlog("select interrupted");
263*a53f50b9Schristos 	continue;
264*a53f50b9Schristos       }
265*a53f50b9Schristos       plog(XLOG_ERROR, "select: %m");
266*a53f50b9Schristos       break;
267*a53f50b9Schristos 
268*a53f50b9Schristos     case 0:
269*a53f50b9Schristos       break;
270*a53f50b9Schristos 
271*a53f50b9Schristos     default:
272*a53f50b9Schristos       /*
273*a53f50b9Schristos        * Read all pending NFS responses at once to avoid having responses
274*a53f50b9Schristos        * queue up as a consequence of retransmissions.
275*a53f50b9Schristos        */
276*a53f50b9Schristos       if (FD_ISSET(fwd_sock, &readfds)) {
277*a53f50b9Schristos 	FD_CLR(fwd_sock, &readfds);
278*a53f50b9Schristos 	--nsel;
279*a53f50b9Schristos 	do {
280*a53f50b9Schristos 	  fwd_reply();
281*a53f50b9Schristos 	} while (rpc_pending_now() > 0);
282*a53f50b9Schristos       }
283*a53f50b9Schristos 
284*a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
285*a53f50b9Schristos       if (nsel)
286*a53f50b9Schristos 	nsel = autofs_handle_fdset(&readfds, nsel);
287*a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
288*a53f50b9Schristos 
289*a53f50b9Schristos       if (nsel) {
290*a53f50b9Schristos 	/*
291*a53f50b9Schristos 	 * Anything left must be a normal
292*a53f50b9Schristos 	 * RPC request.
293*a53f50b9Schristos 	 */
294*a53f50b9Schristos #ifdef HAVE_SVC_GETREQSET
295*a53f50b9Schristos 	svc_getreqset(&readfds);
296*a53f50b9Schristos #else /* not HAVE_SVC_GETREQSET */
297*a53f50b9Schristos # ifdef HAVE_FD_SET_FDS_BITS
298*a53f50b9Schristos 	svc_getreq(readfds.fds_bits[0]);
299*a53f50b9Schristos # else /* not HAVE_FD_SET_FDS_BITS */
300*a53f50b9Schristos 	svc_getreq(readfds);
301*a53f50b9Schristos # endif /* not HAVE_FD_SET_FDS_BITS */
302*a53f50b9Schristos #endif /* not HAVE_SVC_GETREQSET */
303*a53f50b9Schristos       }
304*a53f50b9Schristos       break;
305*a53f50b9Schristos     }
306*a53f50b9Schristos   }
307*a53f50b9Schristos 
308*a53f50b9Schristos #ifdef HAVE_SIGACTION
309*a53f50b9Schristos   sigprocmask(SIG_SETMASK, &smask, NULL);
310*a53f50b9Schristos #else /* not HAVE_SIGACTION */
311*a53f50b9Schristos   (void) sigsetmask(smask);
312*a53f50b9Schristos #endif /* not HAVE_SIGACTION */
313*a53f50b9Schristos 
314*a53f50b9Schristos   if (amd_state == Quit)
315*a53f50b9Schristos     amd_state = Done;
316*a53f50b9Schristos 
317*a53f50b9Schristos   return amd_state;
318*a53f50b9Schristos }
319*a53f50b9Schristos 
320*a53f50b9Schristos 
321*a53f50b9Schristos int
322*a53f50b9Schristos mount_automounter(int ppid)
323*a53f50b9Schristos {
324*a53f50b9Schristos   /*
325*a53f50b9Schristos    * Old code replaced by rpc-trash patch.
326*a53f50b9Schristos    * Erez Zadok <ezk@cs.columbia.edu>
327*a53f50b9Schristos    int so = socket(AF_INET, SOCK_DGRAM, 0);
328*a53f50b9Schristos    */
329*a53f50b9Schristos   SVCXPRT *udp_amqp = NULL, *tcp_amqp = NULL;
330*a53f50b9Schristos   int nmount, ret;
331*a53f50b9Schristos   int soNFS;
332*a53f50b9Schristos   int udp_soAMQ, tcp_soAMQ;
333*a53f50b9Schristos   struct netconfig *udp_amqncp, *tcp_amqncp;
334*a53f50b9Schristos 
335*a53f50b9Schristos   /*
336*a53f50b9Schristos    * This must be done first, because it attempts to bind
337*a53f50b9Schristos    * to various UDP ports and we don't want anything else
338*a53f50b9Schristos    * potentially taking over those ports before we get a chance
339*a53f50b9Schristos    * to reserve them.
340*a53f50b9Schristos    */
341*a53f50b9Schristos   if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
342*a53f50b9Schristos     restart_automounter_nodes();
343*a53f50b9Schristos 
344*a53f50b9Schristos   /*
345*a53f50b9Schristos    * Start RPC forwarding
346*a53f50b9Schristos    */
347*a53f50b9Schristos   if (fwd_init() != 0)
348*a53f50b9Schristos     return 3;
349*a53f50b9Schristos 
350*a53f50b9Schristos   /*
351*a53f50b9Schristos    * Construct the root automount node
352*a53f50b9Schristos    */
353*a53f50b9Schristos   make_root_node();
354*a53f50b9Schristos 
355*a53f50b9Schristos   /*
356*a53f50b9Schristos    * Pick up the pieces from a previous run
357*a53f50b9Schristos    * This is likely to (indirectly) need the rpc_fwd package
358*a53f50b9Schristos    * so it *must* come after the call to fwd_init().
359*a53f50b9Schristos    */
360*a53f50b9Schristos   if (gopt.flags & CFM_RESTART_EXISTING_MOUNTS)
361*a53f50b9Schristos     restart();
362*a53f50b9Schristos 
363*a53f50b9Schristos   /*
364*a53f50b9Schristos    * Create the nfs service for amd
365*a53f50b9Schristos    * If nfs_port is already initialized, it means we
366*a53f50b9Schristos    * already created the service during restart_automounter_nodes().
367*a53f50b9Schristos    */
368*a53f50b9Schristos   if (nfs_port == 0) {
369*a53f50b9Schristos     ret = create_nfs_service(&soNFS, &nfs_port, &nfsxprt, nfs_program_2);
370*a53f50b9Schristos     if (ret != 0)
371*a53f50b9Schristos       return ret;
372*a53f50b9Schristos   }
373*a53f50b9Schristos   xsnprintf(pid_fsname, sizeof(pid_fsname), "%s:(pid%ld,port%u)",
374*a53f50b9Schristos 	    am_get_hostname(), (long) am_mypid, nfs_port);
375*a53f50b9Schristos 
376*a53f50b9Schristos   /* security: if user sets -D noamq, don't even create listening socket */
377*a53f50b9Schristos   if (amuDebug(D_AMQ)) {
378*a53f50b9Schristos     ret = create_amq_service(&udp_soAMQ,
379*a53f50b9Schristos 			     &udp_amqp,
380*a53f50b9Schristos 			     &udp_amqncp,
381*a53f50b9Schristos 			     &tcp_soAMQ,
382*a53f50b9Schristos 			     &tcp_amqp,
383*a53f50b9Schristos 			     &tcp_amqncp,
384*a53f50b9Schristos 			     gopt.preferred_amq_port);
385*a53f50b9Schristos     if (ret != 0)
386*a53f50b9Schristos       return ret;
387*a53f50b9Schristos   }
388*a53f50b9Schristos 
389*a53f50b9Schristos #ifdef HAVE_FS_AUTOFS
390*a53f50b9Schristos   if (amd_use_autofs) {
391*a53f50b9Schristos     /*
392*a53f50b9Schristos      * Create the autofs service for amd.
393*a53f50b9Schristos      */
394*a53f50b9Schristos     ret = create_autofs_service();
395*a53f50b9Schristos     /* if autofs service fails it is OK if using a test amd */
396*a53f50b9Schristos     if (ret != 0) {
397*a53f50b9Schristos       plog(XLOG_WARNING, "autofs service registration failed, turning off autofs support");
398*a53f50b9Schristos       amd_use_autofs = 0;
399*a53f50b9Schristos     }
400*a53f50b9Schristos   }
401*a53f50b9Schristos #endif /* HAVE_FS_AUTOFS */
402*a53f50b9Schristos 
403*a53f50b9Schristos   /*
404*a53f50b9Schristos    * Mount the top-level auto-mountpoints
405*a53f50b9Schristos    */
406*a53f50b9Schristos   nmount = mount_exported();
407*a53f50b9Schristos 
408*a53f50b9Schristos   /*
409*a53f50b9Schristos    * Now safe to tell parent that we are up and running
410*a53f50b9Schristos    */
411*a53f50b9Schristos   if (ppid)
412*a53f50b9Schristos     kill(ppid, SIGQUIT);
413*a53f50b9Schristos 
414*a53f50b9Schristos   if (nmount == 0) {
415*a53f50b9Schristos     plog(XLOG_FATAL, "No work to do - quitting");
416*a53f50b9Schristos     amd_state = Done;
417*a53f50b9Schristos     return 0;
418*a53f50b9Schristos   }
419*a53f50b9Schristos 
420*a53f50b9Schristos   if (amuDebug(D_AMQ)) {
421*a53f50b9Schristos     /*
422*a53f50b9Schristos      * Complete registration of amq (first TCP service then UDP)
423*a53f50b9Schristos      */
424*a53f50b9Schristos     int tcp_ok = 0, udp_ok = 0;
425*a53f50b9Schristos 
426*a53f50b9Schristos     unregister_amq();	 /* unregister leftover Amd, if any, just in case */
427*a53f50b9Schristos 
428*a53f50b9Schristos     tcp_ok = amu_svc_register(tcp_amqp, get_amd_program_number(), AMQ_VERSION,
429*a53f50b9Schristos 			      amq_program_1, IPPROTO_TCP, tcp_amqncp);
430*a53f50b9Schristos     if (!tcp_ok)
431*a53f50b9Schristos       plog(XLOG_FATAL,
432*a53f50b9Schristos 	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, tcp)",
433*a53f50b9Schristos 	   get_amd_program_number());
434*a53f50b9Schristos 
435*a53f50b9Schristos     udp_ok = amu_svc_register(udp_amqp, get_amd_program_number(), AMQ_VERSION,
436*a53f50b9Schristos 			      amq_program_1, IPPROTO_UDP, udp_amqncp);
437*a53f50b9Schristos     if (!udp_ok)
438*a53f50b9Schristos       plog(XLOG_FATAL,
439*a53f50b9Schristos 	   "unable to register (AMQ_PROGRAM=%lu, AMQ_VERSION, udp)",
440*a53f50b9Schristos 	   get_amd_program_number());
441*a53f50b9Schristos 
442*a53f50b9Schristos     /* return error only if both failed */
443*a53f50b9Schristos     if (!tcp_ok && !udp_ok) {
444*a53f50b9Schristos       amd_state = Done;
445*a53f50b9Schristos       return 3;
446*a53f50b9Schristos     }
447*a53f50b9Schristos   }
448*a53f50b9Schristos 
449*a53f50b9Schristos   /*
450*a53f50b9Schristos    * Start timeout_mp rolling
451*a53f50b9Schristos    */
452*a53f50b9Schristos   reschedule_timeout_mp();
453*a53f50b9Schristos 
454*a53f50b9Schristos   /*
455*a53f50b9Schristos    * Start the server
456*a53f50b9Schristos    */
457*a53f50b9Schristos   if (run_rpc() != Done) {
458*a53f50b9Schristos     plog(XLOG_FATAL, "run_rpc failed");
459*a53f50b9Schristos     amd_state = Done;
460*a53f50b9Schristos   }
461*a53f50b9Schristos   return 0;
462*a53f50b9Schristos }
463