4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
27 #include <stdio_ext.h>
31 #include <sys/types.h>
34 #include <netconfig.h>
36 #include <sys/resource.h>
37 #include <sys/systeminfo.h>
40 #include <sys/sockio.h>
49 #include "automount.h"
51 #include <sys/mnttab.h>
52 #include <arpa/inet.h>
53 #include <rpcsvc/daemon_utils.h>
57 #include <tsol/label.h>
58 #include <sys/utsname.h>
59 #include <sys/thread.h>
60 #include <nfs/rnode.h>
67 static void autofs_doorfunc(void *, char *, size_t, door_desc_t
*, uint_t
);
68 static void autofs_setdoor(int);
69 static void autofs_mntinfo_1_r(autofs_lookupargs
*, autofs_mountres
*);
70 static void autofs_mount_1_free_r(struct autofs_mountres
*);
71 static void autofs_lookup_1_r(autofs_lookupargs
*, autofs_lookupres
*);
72 static void autofs_lookup_1_free_args(autofs_lookupargs
*);
73 static void autofs_unmount_1_r(umntrequest
*, umntres
*);
74 static void autofs_unmount_1_free_args(umntrequest
*);
75 static void autofs_readdir_1_r(autofs_rddirargs
*, autofs_rddirres
*);
76 static void autofs_readdir_1_free_r(struct autofs_rddirres
*);
77 static int decode_args(xdrproc_t
, autofs_door_args_t
*, caddr_t
*, int);
78 static bool_t
encode_res(xdrproc_t
, autofs_door_res_t
**, caddr_t
, int *);
80 static void warn_hup(int);
81 static void free_action_list();
82 static int start_autofs_svcs();
83 static void automountd_wait_for_cleanup(pid_t
);
86 * Private autofs system call
88 extern int _autofssys(int, void *);
90 #define CTIME_BUF_LEN 26
92 #define RESOURCE_FACTOR 8
94 #define AUTOFS_DOOR "/var/run/autofs_door"
97 static thread_key_t s_thr_key
;
99 struct autodir
*dir_head
;
100 struct autodir
*dir_tail
;
106 int automountd_nobrowse
= 0;
120 if (geteuid() != 0) {
121 (void) fprintf(stderr
, "%s must be run as root\n", argv
[0]);
126 * Read in the values from SMF first before we check
127 * commandline options so the options override the file.
130 ret
= autofs_smf_get_prop("automountd_verbose", defval
,
131 DEFAULT_INSTANCE
, SCF_TYPE_BOOLEAN
, AUTOMOUNTD
, &bufsz
);
133 if (strncasecmp("true", defval
, 4) == 0)
139 ret
= autofs_smf_get_prop("nobrowse", defval
, DEFAULT_INSTANCE
,
140 SCF_TYPE_BOOLEAN
, AUTOMOUNTD
, &bufsz
);
142 if (strncasecmp("true", defval
, 4) == 0)
143 automountd_nobrowse
= TRUE
;
145 automountd_nobrowse
= FALSE
;
148 ret
= autofs_smf_get_prop("trace", defval
, DEFAULT_INSTANCE
,
149 SCF_TYPE_INTEGER
, AUTOMOUNTD
, &bufsz
);
152 trace
= strtol(defval
, (char **)NULL
, 10);
156 put_automountd_env();
158 while ((c
= getopt(argc
, argv
, "vnTD:")) != EOF
) {
164 automountd_nobrowse
++;
170 (void) putenv(optarg
);
177 if (sysinfo(SI_HOSTNAME
, self
, sizeof (self
)) == -1) {
179 (void) fprintf(stderr
,
180 "automountd: can't determine hostname, error: %d\n",
188 perror("cannot fork");
196 openlog("automountd", LOG_PID
, LOG_DAEMON
);
197 (void) setlocale(LC_ALL
, "");
200 * Create the door_servers to manage fork/exec requests for
201 * mounts and executable automount maps
203 if ((did_fork_exec
= door_create(automountd_do_fork_exec
,
204 NULL
, NULL
)) == -1) {
205 syslog(LOG_ERR
, "door_create failed: %m, Exiting.");
208 if ((did_exec_map
= door_create(automountd_do_exec_map
,
209 NULL
, NULL
)) == -1) {
210 syslog(LOG_ERR
, "door_create failed: %m, Exiting.");
211 if (door_revoke(did_fork_exec
) == -1) {
212 syslog(LOG_ERR
, "failed to door_revoke(%d) %m",
218 * Before we become multithreaded we fork allowing the parent
219 * to become a door server to handle all mount and unmount
220 * requests. This works around a potential hang in using
221 * fork1() within a multithreaded environment
227 "can't fork the automountd mount process %m");
228 if (door_revoke(did_fork_exec
) == -1) {
229 syslog(LOG_ERR
, "failed to door_revoke(%d) %m",
232 if (door_revoke(did_exec_map
) == -1) {
233 syslog(LOG_ERR
, "failed to door_revoke(%d) %m",
237 } else if (pid
> 0) {
238 /* this is the door server process */
239 automountd_wait_for_cleanup(pid
);
243 (void) rwlock_init(&cache_lock
, USYNC_THREAD
, NULL
);
244 (void) rwlock_init(&autofs_rddir_cache_lock
, USYNC_THREAD
, NULL
);
247 * initialize the name services, use NULL arguments to ensure
248 * we don't initialize the stack of files used in file service
250 (void) ns_setup(NULL
, NULL
);
253 * we're using doors and its thread management now so we need to
254 * make sure we have more than the default of 256 file descriptors
257 rlset
.rlim_cur
= RLIM_INFINITY
;
258 rlset
.rlim_max
= RLIM_INFINITY
;
259 if (setrlimit(RLIMIT_NOFILE
, &rlset
) == -1)
260 syslog(LOG_ERR
, "setrlimit failed for %s: %s", AUTOMOUNTD
,
263 (void) enable_extended_FILE_stdio(-1, -1);
266 * establish our lock on the lock file and write our pid to it.
267 * exit if some other process holds the lock, or if there's any
268 * error in writing/locking the file.
270 pid
= _enter_daemon_lock(AUTOMOUNTD
);
275 syslog(LOG_ERR
, "error locking for %s: %m", AUTOMOUNTD
);
278 /* daemon was already running */
283 * If we coredump it'll be /core.
286 syslog(LOG_ERR
, "chdir /: %m");
289 * Create cache_cleanup thread
291 if (thr_create(NULL
, 0, (void *(*)(void *))cache_cleanup
, NULL
,
292 THR_DETACHED
| THR_DAEMON
| THR_NEW_LWP
, NULL
)) {
293 syslog(LOG_ERR
, "unable to create cache_cleanup thread");
297 /* other initializations */
298 (void) rwlock_init(&portmap_cache_lock
, USYNC_THREAD
, NULL
);
301 * On a labeled system, allow read-down nfs mounts if privileged
302 * (PRIV_NET_MAC_AWARE) to do so. Otherwise, ignore the error
303 * and "mount equal label only" behavior will result.
305 if (is_system_labeled()) {
306 (void) setpflags(NET_MAC_AWARE
, 1);
307 (void) setpflags(NET_MAC_AWARE_INHERIT
, 1);
310 (void) signal(SIGHUP
, warn_hup
);
313 return (start_autofs_svcs());
318 * The old automounter supported a SIGHUP
319 * to allow it to resynchronize internal
320 * state with the /etc/mnttab.
321 * This is no longer relevant, but we
322 * need to catch the signal and warn
330 syslog(LOG_ERR
, "SIGHUP received: ignored");
331 (void) signal(SIGHUP
, warn_hup
);
337 (void) fprintf(stderr
, "Usage: automountd\n"
338 "\t[-T]\t\t(trace requests)\n"
339 "\t[-v]\t\t(verbose error msgs)\n"
340 "\t[-D n=s]\t(define env variable)\n");
347 autofs_rddirargs
*req
,
348 autofs_rddirres
*res
)
351 trace_prt(1, "READDIR REQUEST : %s @ %ld\n",
352 req
->rda_map
, req
->rda_offset
);
354 do_readdir(req
, res
);
356 trace_prt(1, "READDIR REPLY : status=%d\n", res
->rd_status
);
360 autofs_readdir_1_free_r(struct autofs_rddirres
*res
)
362 if (res
->rd_status
== AUTOFS_OK
) {
363 if (res
->rd_rddir
.rddir_entries
)
364 free(res
->rd_rddir
.rddir_entries
);
375 struct umntrequest
*ul
;
378 char ctime_buf
[CTIME_BUF_LEN
];
379 if (ctime_r(&timenow
, ctime_buf
, CTIME_BUF_LEN
) == NULL
)
382 trace_prt(1, "UNMOUNT REQUEST: %s", ctime_buf
);
383 for (ul
= m
; ul
; ul
= ul
->next
)
384 trace_prt(1, " resource=%s fstype=%s mntpnt=%s"
390 ul
->isdirect
? "direct" : "indirect");
394 res
->status
= do_unmount1(m
);
397 trace_prt(1, "UNMOUNT REPLY: status=%d\n", res
->status
);
402 autofs_lookupargs
*m
,
403 autofs_lookupres
*res
)
405 autofs_action_t action
;
410 char ctime_buf
[CTIME_BUF_LEN
];
411 if (ctime_r(&timenow
, ctime_buf
, CTIME_BUF_LEN
) == NULL
)
414 trace_prt(1, "LOOKUP REQUEST: %s", ctime_buf
);
415 trace_prt(1, " name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
416 m
->name
, m
->subdir
, m
->map
, m
->opts
, m
->path
, m
->isdirect
);
419 bzero(&link
, sizeof (struct linka
));
421 status
= do_lookup1(m
->map
, m
->name
, m
->subdir
, m
->opts
, m
->path
,
422 (uint_t
)m
->isdirect
, m
->uid
, &action
, &link
);
425 * Return action list to kernel.
427 res
->lu_res
= AUTOFS_OK
;
428 if ((res
->lu_type
.action
= action
) == AUTOFS_LINK_RQ
) {
429 res
->lu_type
.lookup_result_type_u
.lt_linka
= link
;
435 res
->lu_res
= AUTOFS_NOENT
;
437 res
->lu_verbose
= verbose
;
440 trace_prt(1, "LOOKUP REPLY : status=%d\n", res
->lu_res
);
445 autofs_lookupargs
*m
,
446 autofs_mountres
*res
)
449 action_list
*alp
= NULL
;
452 char ctime_buf
[CTIME_BUF_LEN
];
453 if (ctime_r(&timenow
, ctime_buf
, CTIME_BUF_LEN
) == NULL
)
456 trace_prt(1, "MOUNT REQUEST: %s", ctime_buf
);
457 trace_prt(1, " name=%s[%s] map=%s opts=%s path=%s direct=%d\n",
458 m
->name
, m
->subdir
, m
->map
, m
->opts
, m
->path
, m
->isdirect
);
461 status
= do_mount1(m
->map
, m
->name
, m
->subdir
, m
->opts
, m
->path
,
462 (uint_t
)m
->isdirect
, m
->uid
, &alp
, DOMOUNT_USER
);
465 * An error occurred, free action list if allocated.
468 free_action_list(alp
);
474 * Return action list to kernel.
476 res
->mr_type
.status
= AUTOFS_ACTION
;
477 res
->mr_type
.mount_result_type_u
.list
= alp
;
480 * No work to do left for the kernel
482 res
->mr_type
.status
= AUTOFS_DONE
;
483 res
->mr_type
.mount_result_type_u
.error
= status
;
487 switch (res
->mr_type
.status
) {
490 "MOUNT REPLY : status=%d, AUTOFS_ACTION\n",
495 "MOUNT REPLY : status=%d, AUTOFS_DONE\n",
499 trace_prt(1, "MOUNT REPLY : status=%d, UNKNOWN\n",
504 if (status
&& verbose
) {
507 syslog(LOG_ERR
, "mount of %s failed", m
->path
);
511 "mount of %s/%s failed", m
->path
, m
->name
);
517 autofs_mount_1_free_r(struct autofs_mountres
*res
)
519 if (res
->mr_type
.status
== AUTOFS_ACTION
) {
521 trace_prt(1, "freeing action list\n");
522 free_action_list(res
->mr_type
.mount_result_type_u
.list
);
527 * Used for reporting messages from code shared with automount command.
528 * Formats message into a buffer and calls syslog.
530 * Print an error. Works like printf (fmt string and variable args)
531 * except that it will subsititute an error message for a "%m" string
535 pr_msg(const char *fmt
, ...)
538 char fmtbuff
[BUFSIZ
], buff
[BUFSIZ
];
545 for (p1
= fmt
; *p1
; p1
++) {
546 if (*p1
== '%' && *(p1
+ 1) == 'm') {
547 (void) strcpy(p2
, strerror(errno
));
554 if (p2
> fmtbuff
&& *(p2
-1) != '\n')
559 (void) vsprintf(buff
, fmtbuff
, ap
);
561 syslog(LOG_ERR
, buff
);
565 free_action_list(action_list
*alp
)
567 action_list
*p
, *next
= NULL
;
570 for (p
= alp
; p
!= NULL
; p
= next
) {
571 switch (p
->action
.action
) {
572 case AUTOFS_MOUNT_RQ
:
573 mp
= &(p
->action
.action_list_entry_u
.mounta
);
574 /* LINTED pointer alignment */
576 if (strcmp(mp
->fstype
, "autofs") == 0) {
577 free_autofs_args((autofs_args
*)
579 } else if (strncmp(mp
->fstype
, "nfs", 3) == 0) {
580 free_nfs_args((struct nfs_args
*)
590 "non AUTOFS_MOUNT_RQ requests not implemented\n");
594 "non AUTOFS_MOUNT_RQ requests not implemented\n");
603 autofs_lookup_1_free_args(autofs_lookupargs
*args
)
618 autofs_unmount_1_free_args(umntrequest
*args
)
620 if (args
->mntresource
)
621 free(args
->mntresource
);
629 autofs_unmount_1_free_args(args
->next
);
633 autofs_setdoor(int did
)
640 (void) _autofssys(AUTOFS_SETDOOR
, &did
);
644 autofs_get_buffer(size_t size
)
646 autofs_tsd_t
*tsd
= NULL
;
649 * Make sure the buffer size is aligned
651 (void) thr_getspecific(s_thr_key
, (void **)&tsd
);
653 tsd
= (autofs_tsd_t
*)malloc(sizeof (autofs_tsd_t
));
657 tsd
->atsd_buf
= malloc(size
);
658 if (tsd
->atsd_buf
!= NULL
)
659 tsd
->atsd_len
= size
;
662 (void) thr_setspecific(s_thr_key
, tsd
);
664 if (tsd
->atsd_buf
&& (tsd
->atsd_len
< size
)) {
666 tsd
->atsd_buf
= malloc(size
);
667 if (tsd
->atsd_buf
!= NULL
)
668 tsd
->atsd_len
= size
;
675 bzero(tsd
->atsd_buf
, size
);
676 return (tsd
->atsd_buf
);
679 gettext("Can't Allocate tsd buffer, size %d"), size
);
685 * Each request will automatically spawn a new thread with this
686 * as its entry point.
702 autofs_lookupargs
*xdrargs
;
703 autofs_lookupres lookup_res
;
704 autofs_rddirargs
*rddir_args
;
705 autofs_rddirres rddir_res
;
706 autofs_mountres mount_res
;
707 umntrequest
*umnt_args
;
709 autofs_door_res_t
*door_res
;
710 autofs_door_res_t failed_res
;
712 if (arg_size
< sizeof (autofs_door_args_t
)) {
713 failed_res
.res_status
= EINVAL
;
714 error
= door_return((char *)&failed_res
,
715 sizeof (autofs_door_res_t
), NULL
, 0);
717 * If we got here the door_return() failed.
719 syslog(LOG_ERR
, "Bad argument, door_return failure %d", error
);
723 timenow
= time((time_t *)NULL
);
725 which
= ((autofs_door_args_t
*)argp
)->cmd
;
728 if (error
= decode_args(xdr_autofs_lookupargs
,
729 (autofs_door_args_t
*)argp
, (caddr_t
*)&xdrargs
,
730 sizeof (autofs_lookupargs
))) {
732 "error allocating lookup arguments buffer");
733 failed_res
.res_status
= error
;
734 failed_res
.xdr_len
= 0;
735 res
= (caddr_t
)&failed_res
;
739 bzero(&lookup_res
, sizeof (autofs_lookupres
));
741 autofs_lookup_1_r(xdrargs
, &lookup_res
);
743 autofs_lookup_1_free_args(xdrargs
);
746 if (!encode_res(xdr_autofs_lookupres
, &door_res
,
747 (caddr_t
)&lookup_res
, &res_size
)) {
749 "error allocating lookup results buffer");
750 failed_res
.res_status
= EINVAL
;
751 failed_res
.xdr_len
= 0;
752 res
= (caddr_t
)&failed_res
;
754 door_res
->res_status
= 0;
755 res
= (caddr_t
)door_res
;
760 if (error
= decode_args(xdr_autofs_lookupargs
,
761 (autofs_door_args_t
*)argp
, (caddr_t
*)&xdrargs
,
762 sizeof (autofs_lookupargs
))) {
764 "error allocating lookup arguments buffer");
765 failed_res
.res_status
= error
;
766 failed_res
.xdr_len
= 0;
767 res
= (caddr_t
)&failed_res
;
772 autofs_mntinfo_1_r((autofs_lookupargs
*)xdrargs
, &mount_res
);
774 autofs_lookup_1_free_args(xdrargs
);
778 * Only reason we would get a NULL res is because
779 * we could not allocate a results buffer. Use
780 * a local one to return the error EAGAIN as has
781 * always been done when memory allocations fail.
783 if (!encode_res(xdr_autofs_mountres
, &door_res
,
784 (caddr_t
)&mount_res
, &res_size
)) {
786 "error allocating mount results buffer");
787 failed_res
.res_status
= EAGAIN
;
788 failed_res
.xdr_len
= 0;
789 res
= (caddr_t
)&failed_res
;
791 door_res
->res_status
= 0;
792 res
= (caddr_t
)door_res
;
794 autofs_mount_1_free_r(&mount_res
);
798 if (error
= decode_args(xdr_umntrequest
,
799 (autofs_door_args_t
*)argp
,
800 (caddr_t
*)&umnt_args
, sizeof (umntrequest
))) {
802 "error allocating unmount argument buffer");
803 failed_res
.res_status
= error
;
804 failed_res
.xdr_len
= 0;
805 res
= (caddr_t
)&failed_res
;
806 res_size
= sizeof (autofs_door_res_t
);
810 autofs_unmount_1_r(umnt_args
, &umount_res
);
812 error
= umount_res
.status
;
814 autofs_unmount_1_free_args(umnt_args
);
817 if (!encode_res(xdr_umntres
, &door_res
, (caddr_t
)&umount_res
,
820 "error allocating unmount results buffer");
821 failed_res
.res_status
= EINVAL
;
822 failed_res
.xdr_len
= 0;
823 res
= (caddr_t
)&failed_res
;
824 res_size
= sizeof (autofs_door_res_t
);
826 door_res
->res_status
= 0;
827 res
= (caddr_t
)door_res
;
832 if (error
= decode_args(xdr_autofs_rddirargs
,
833 (autofs_door_args_t
*)argp
,
834 (caddr_t
*)&rddir_args
,
835 sizeof (autofs_rddirargs
))) {
837 "error allocating readdir argument buffer");
838 failed_res
.res_status
= error
;
839 failed_res
.xdr_len
= 0;
840 res
= (caddr_t
)&failed_res
;
841 res_size
= sizeof (autofs_door_res_t
);
845 autofs_readdir_1_r(rddir_args
, &rddir_res
);
847 free(rddir_args
->rda_map
);
850 if (!encode_res(xdr_autofs_rddirres
, &door_res
,
851 (caddr_t
)&rddir_res
, &res_size
)) {
853 "error allocating readdir results buffer");
854 failed_res
.res_status
= ENOMEM
;
855 failed_res
.xdr_len
= 0;
856 res
= (caddr_t
)&failed_res
;
857 res_size
= sizeof (autofs_door_res_t
);
859 door_res
->res_status
= 0;
860 res
= (caddr_t
)door_res
;
862 autofs_readdir_1_free_r(&rddir_res
);
865 case AUTOFS_DUMP_DEBUG
:
866 check_leaks("/var/tmp/automountd.leak");
867 error
= door_return(NULL
, 0, NULL
, 0);
869 * If we got here, door_return() failed
871 syslog(LOG_ERR
, "dump debug door_return failure %d",
880 failed_res
.res_status
= EINVAL
;
881 res
= (char *)&failed_res
;
882 res_size
= sizeof (autofs_door_res_t
);
888 error
= door_return(res
, res_size
, NULL
, 0);
890 if (errno
== E2BIG
) {
892 * Failed due to encoded results being bigger than the
893 * kernel expected bufsize. Passing actual results size
894 * back down to kernel.
896 failed_res
.res_status
= EOVERFLOW
;
897 failed_res
.xdr_len
= srsz
;
898 res
= (caddr_t
)&failed_res
;
899 res_size
= sizeof (autofs_door_res_t
);
901 syslog(LOG_ERR
, "door_return failed %d, buffer %p, "
902 "buffer size %d", error
, (void *)res
, res_size
);
906 (void) door_return(res
, res_size
, NULL
, 0);
911 start_autofs_svcs(void)
918 if ((doorfd
= door_create(autofs_doorfunc
, NULL
,
919 DOOR_REFUSE_DESC
| DOOR_NO_CANCEL
)) == -1) {
920 syslog(LOG_ERR
, gettext("Unable to create door\n"));
926 * Create a file system path for the door
928 if ((dfd
= open(AUTOFS_DOOR
, O_RDWR
|O_CREAT
|O_TRUNC
,
929 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IROTH
)) == -1) {
930 syslog(LOG_ERR
, "Unable to open %s: %m\n", AUTOFS_DOOR
);
931 (void) close(doorfd
);
936 * stale associations clean up
938 (void) fdetach(AUTOFS_DOOR
);
941 * Register in the namespace to the kernel to door_ki_open.
943 if (fattach(doorfd
, AUTOFS_DOOR
) == -1) {
944 syslog(LOG_ERR
, "Unable to fattach door %m\n", AUTOFS_DOOR
);
946 (void) close(doorfd
);
952 * Pass door name to kernel for door_ki_open
954 autofs_setdoor(doorfd
);
956 (void) thr_keycreate(&s_thr_key
, NULL
);
959 * Wait for incoming calls
966 syslog(LOG_ERR
, gettext("Door server exited"));
973 autofs_door_args_t
*argp
,
979 caddr_t tmpargs
= (caddr_t
)&((autofs_door_args_t
*)argp
)->xdr_arg
;
980 size_t arg_size
= ((autofs_door_args_t
*)argp
)->xdr_len
;
982 xdrmem_create(&xdrs
, tmpargs
, arg_size
, XDR_DECODE
);
984 *xdrargs
= malloc(size
);
985 if (*xdrargs
== NULL
) {
986 syslog(LOG_ERR
, "error allocating arguments buffer");
990 bzero(*xdrargs
, size
);
992 if (!(*xdrfunc
)(&xdrs
, *xdrargs
)) {
995 syslog(LOG_ERR
, "error decoding arguments");
1006 autofs_door_res_t
**results
,
1012 *size
= xdr_sizeof((*xdrfunc
), resp
);
1013 *results
= autofs_get_buffer(
1014 sizeof (autofs_door_res_t
) + *size
);
1015 if (*results
== NULL
) {
1016 (*results
)->res_status
= ENOMEM
;
1019 (*results
)->xdr_len
= *size
;
1020 *size
= sizeof (autofs_door_res_t
) + (*results
)->xdr_len
;
1021 xdrmem_create(&xdrs
, (caddr_t
)((*results
)->xdr_res
),
1022 (*results
)->xdr_len
, XDR_ENCODE
);
1023 if (!(*xdrfunc
)(&xdrs
, resp
)) {
1024 (*results
)->res_status
= EINVAL
;
1025 syslog(LOG_ERR
, "error encoding results");
1028 (*results
)->res_status
= 0;
1033 automountd_wait_for_cleanup(pid_t pid
)
1039 * Wait for the main automountd process to exit so we cleanup
1041 (void) waitpid(pid
, &status
, 0);
1043 child_exitval
= WEXITSTATUS(status
);
1046 * Shutdown the door server for mounting and unmounting
1049 if (door_revoke(did_fork_exec
) == -1) {
1050 syslog(LOG_ERR
, "failed to door_revoke(%d) %m", did_fork_exec
);
1052 if (door_revoke(did_exec_map
) == -1) {
1053 syslog(LOG_ERR
, "failed to door_revoke(%d) %m", did_exec_map
);
1055 exit(child_exitval
);