Blame daemon/automount.c

Packit 8480eb
/* ----------------------------------------------------------------------- *
Packit 8480eb
 *
Packit 8480eb
 *  automount.c - Linux automounter daemon
Packit 8480eb
 *   
Packit 8480eb
 *   Copyright 1997 Transmeta Corporation - All Rights Reserved
Packit 8480eb
 *   Copyright 1999-2000 Jeremy Fitzhardinge <jeremy@goop.org>
Packit 8480eb
 *   Copyright 2001-2005 Ian Kent <raven@themaw.net>
Packit 8480eb
 *
Packit 8480eb
 *   This program is free software; you can redistribute it and/or modify
Packit 8480eb
 *   it under the terms of the GNU General Public License as published by
Packit 8480eb
 *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
Packit 8480eb
 *   USA; either version 2 of the License, or (at your option) any later
Packit 8480eb
 *   version.
Packit 8480eb
 *   
Packit 8480eb
 *   This program is distributed in the hope that it will be useful,
Packit 8480eb
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8480eb
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8480eb
 *   GNU General Public License for more details.
Packit 8480eb
 *
Packit 8480eb
 * ----------------------------------------------------------------------- */
Packit 8480eb
Packit 8480eb
#include <dirent.h>
Packit 8480eb
#include <getopt.h>
Packit 8480eb
#include <signal.h>
Packit 8480eb
#include <stdio.h>
Packit 8480eb
#include <stdlib.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <sys/ioctl.h>
Packit 8480eb
#include <ctype.h>
Packit 8480eb
#include <sys/types.h>
Packit 8480eb
#include <sys/wait.h>
Packit 8480eb
#include <sys/stat.h>
Packit 8480eb
#include <sys/time.h>
Packit 8480eb
#include <sys/resource.h>
Packit 8480eb
#include <sys/poll.h>
Packit 8480eb
#include <dirent.h>
Packit 8480eb
#include <sys/vfs.h>
Packit 8480eb
#include <sys/utsname.h>
Packit Service b3e495
#ifdef WITH_SYSTEMD
Packit Service b3e495
#include <systemd/sd-daemon.h>
Packit Service b3e495
#endif
Packit 8480eb
Packit 8480eb
#include "automount.h"
Packit 8480eb
#if defined(LIBXML2_WORKAROUND) || defined(TIRPC_WORKAROUND)
Packit 8480eb
#include <dlfcn.h>
Packit 8480eb
#ifdef WITH_LDAP
Packit 8480eb
#include <libxml/parser.h>
Packit 8480eb
#endif
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
const char *program;		/* Initialized with argv[0] */
Packit 8480eb
const char *version = VERSION_STRING;	/* Program version */
Packit 8480eb
const char *libdir = AUTOFS_LIB_DIR;	/* Location of library modules */
Packit 8480eb
const char *mapdir = AUTOFS_MAP_DIR;	/* Location of mount maps */
Packit 8480eb
const char *confdir = AUTOFS_CONF_DIR;	/* Location of autofs config file */
Packit 8480eb
Packit Service a565d0
unsigned int mp_mode = 0755;
Packit Service a565d0
Packit 8480eb
unsigned int nfs_mount_uses_string_options = 0;
Packit 8480eb
static struct nfs_mount_vers vers, check = {1, 1, 1};
Packit 8480eb
Packit 8480eb
/* autofs fifo name prefix */
Packit Service 42268b
const char *fifodir = AUTOFS_FIFO_DIR "/autofs.fifo";
Packit 8480eb
Packit 8480eb
const char *global_options;		/* Global option, from command line */
Packit 8480eb
Packit 8480eb
static char *pid_file = NULL;		/* File in which to keep pid */
Packit 8480eb
unsigned int global_selection_options;
Packit 8480eb
Packit 8480eb
long global_negative_timeout = -1;
Packit 8480eb
int do_force_unlink = 0;		/* Forceably unlink mount tree at startup */
Packit 8480eb
Packit Service b3e495
static int start_pipefd[2] = {-1, -1};
Packit 8480eb
static int st_stat = 1;
Packit 8480eb
static int *pst_stat = &st_stat;
Packit 8480eb
static pthread_t state_mach_thid;
Packit 8480eb
Packit 8480eb
static sigset_t block_sigs;
Packit 8480eb
Packit 8480eb
/* Pre-calculated kernel packet length */
Packit 8480eb
static size_t kpkt_len;
Packit 8480eb
Packit 8480eb
/* Attributes for creating detached and joinable threads */
Packit 8480eb
pthread_attr_t th_attr;
Packit 8480eb
pthread_attr_t th_attr_detached;
Packit 8480eb
size_t detached_thread_stack_size = PTHREAD_STACK_MIN * 144;
Packit 8480eb
Packit 8480eb
struct master_readmap_cond mrc = {
Packit 8480eb
	PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, NULL, 0, 0, 0, 0};
Packit 8480eb
Packit 8480eb
struct startup_cond suc = {
Packit 8480eb
	PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0};
Packit 8480eb
Packit 8480eb
pthread_key_t key_thread_stdenv_vars;
Packit 8480eb
pthread_key_t key_thread_attempt_id = (pthread_key_t) 0L;
Packit 8480eb
Packit 8480eb
#define MAX_OPEN_FILES		10240
Packit 8480eb
Packit 8480eb
int aquire_flag_file(void);
Packit 8480eb
void release_flag_file(void);
Packit 8480eb
static int umount_all(struct autofs_point *ap, int force);
Packit 8480eb
Packit 8480eb
extern struct master *master_list;
Packit 8480eb
Packit 8480eb
/* simple string hash based on public domain sdbm library */
Packit 8480eb
static unsigned long sdbm_hash(const char *str, unsigned long seed)
Packit 8480eb
{
Packit 8480eb
	unsigned long hash = seed;
Packit 8480eb
	char c;
Packit 8480eb
Packit 8480eb
	while ((c = *str++))
Packit 8480eb
		hash = c + (hash << 6) + (hash << 16) - hash;
Packit 8480eb
	return hash;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void set_thread_mount_request_log_id(struct pending_args *mt)
Packit 8480eb
{
Packit 8480eb
	char attempt_id_comp[20];
Packit 8480eb
	unsigned long *attempt_id;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	if (!defaults_get_use_mount_request_log_id())
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	attempt_id = pthread_getspecific(key_thread_attempt_id);
Packit 8480eb
	if (attempt_id == NULL) {
Packit 8480eb
		attempt_id = (unsigned long *) calloc(1, sizeof(unsigned long));
Packit 8480eb
		if (attempt_id  == NULL)
Packit 8480eb
			fatal(ENOMEM);
Packit 8480eb
		snprintf(attempt_id_comp, 20, "%ld", mt->wait_queue_token);
Packit 8480eb
		*attempt_id = sdbm_hash(attempt_id_comp, 0);
Packit 8480eb
		snprintf(attempt_id_comp, 20, "%u", mt->pid);
Packit 8480eb
		*attempt_id = sdbm_hash(attempt_id_comp, *attempt_id);
Packit 8480eb
		*attempt_id = sdbm_hash(mt->name, *attempt_id);
Packit 8480eb
		status = pthread_setspecific(key_thread_attempt_id, attempt_id);
Packit 8480eb
		if (status != 0)
Packit 8480eb
			fatal(status);
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int is_remote_fstype(unsigned int fs_type)
Packit 8480eb
{
Packit 8480eb
	int ret = 0;
Packit 8480eb
	switch (fs_type) {
Packit 8480eb
	case SMB_SUPER_MAGIC:
Packit 8480eb
	case CIFS_MAGIC_NUMBER:
Packit 8480eb
	case NCP_SUPER_MAGIC:
Packit 8480eb
	case NFS_SUPER_MAGIC:
Packit 8480eb
		ret = 1;
Packit 8480eb
		break;
Packit 8480eb
	};
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_mkdir(const char *parent, const char *path, mode_t mode)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
	mode_t mask;
Packit 8480eb
	struct stat st, root;
Packit 8480eb
	struct statfs fs;
Packit 8480eb
Packit 8480eb
	/* If path exists we're done */
Packit 8480eb
	status = stat(path, &st);
Packit 8480eb
	if (status == 0) {
Packit 8480eb
		errno = EEXIST;
Packit 8480eb
		if (!S_ISDIR(st.st_mode))
Packit 8480eb
			errno = ENOTDIR;
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * We don't want to create the path on a remote file system
Packit 8480eb
	 * unless it's the root file system.
Packit 8480eb
	 * An empty parent means it's the root directory and always ok.
Packit 8480eb
	 */
Packit 8480eb
	if (*parent) {
Packit 8480eb
		status = statfs(parent, &fs);
Packit 8480eb
		if (status == -1)
Packit 8480eb
			goto fail;
Packit 8480eb
Packit 8480eb
		if (is_remote_fstype(fs.f_type)) {
Packit 8480eb
			status = stat(parent, &st);
Packit 8480eb
			if (status == -1)
Packit 8480eb
				goto fail;
Packit 8480eb
Packit 8480eb
			status = stat("/", &root);
Packit 8480eb
			if (status == -1)
Packit 8480eb
				goto fail;
Packit 8480eb
Packit 8480eb
			if (st.st_dev != root.st_dev)
Packit 8480eb
				goto fail;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mask = umask(0022);
Packit 8480eb
	status = mkdir(path, mode);
Packit 8480eb
	(void) umask(mask);
Packit 8480eb
	if (status == -1)
Packit 8480eb
		goto fail;
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
fail:
Packit 8480eb
	errno = EACCES;
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int mkdir_path(const char *path, mode_t mode)
Packit 8480eb
{
Packit 8480eb
	char buf[PATH_MAX];
Packit 8480eb
	char parent[PATH_MAX];
Packit 8480eb
	const char *cp = path, *lcp = path;
Packit 8480eb
	char *bp = buf, *pp = parent;
Packit 8480eb
Packit 8480eb
	*parent = '\0';
Packit 8480eb
Packit 8480eb
	do {
Packit 8480eb
		if (cp != path && (*cp == '/' || *cp == '\0')) {
Packit 8480eb
			memcpy(bp, lcp, cp - lcp);
Packit 8480eb
			bp += cp - lcp;
Packit 8480eb
			*bp = '\0';
Packit 8480eb
			if (!do_mkdir(parent, buf, mode)) {
Packit 8480eb
				if (*cp != '\0') {
Packit 8480eb
					memcpy(pp, lcp, cp - lcp);
Packit 8480eb
					pp += cp - lcp;
Packit 8480eb
					*pp = '\0';
Packit 8480eb
					lcp = cp;
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
				return -1;
Packit 8480eb
			}
Packit 8480eb
			memcpy(pp, lcp, cp - lcp);
Packit 8480eb
			pp += cp - lcp;
Packit 8480eb
			*pp = '\0';
Packit 8480eb
			lcp = cp;
Packit 8480eb
		}
Packit 8480eb
	} while (*cp++ != '\0');
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Remove as much as possible of a path */
Packit 8480eb
int rmdir_path(struct autofs_point *ap, const char *path, dev_t dev)
Packit 8480eb
{
Packit 8480eb
	int len = strlen(path);
Packit 8480eb
	char buf[PATH_MAX];
Packit 8480eb
	char *cp;
Packit 8480eb
	int first = 1;
Packit 8480eb
	struct stat st;
Packit 8480eb
	struct statfs fs;
Packit 8480eb
Packit 8480eb
	strcpy(buf, path);
Packit 8480eb
	cp = buf + len;
Packit 8480eb
Packit 8480eb
	do {
Packit 8480eb
		*cp = '\0';
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 *  Before removing anything, perform some sanity checks to
Packit 8480eb
		 *  ensure that we are looking at files in the automount
Packit 8480eb
		 *  file system.
Packit 8480eb
		 */
Packit 8480eb
		memset(&st, 0, sizeof(st));
Packit 8480eb
		if (lstat(buf, &st) != 0) {
Packit 8480eb
			crit(ap->logopt, "lstat of %s failed", buf);
Packit 8480eb
			return -1;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* Termination condition removing full path within autofs fs */
Packit 8480eb
		if (st.st_dev != dev)
Packit 8480eb
			return 0;
Packit 8480eb
Packit 8480eb
		if (statfs(buf, &fs) != 0) {
Packit 8480eb
			error(ap->logopt, "could not stat fs of %s", buf);
Packit 8480eb
			return -1;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (fs.f_type != (__SWORD_TYPE) AUTOFS_SUPER_MAGIC) {
Packit 8480eb
			crit(ap->logopt, "attempt to remove directory from a "
Packit 8480eb
			     "non-autofs filesystem!");
Packit 8480eb
			crit(ap->logopt,
Packit 8480eb
			     "requester dev == %llu, \"%s\" owner dev == %llu",
Packit 8480eb
			     dev, buf, st.st_dev);
Packit 8480eb
			return -1;
Packit 8480eb
		}
Packit 8480eb
			     
Packit 8480eb
		/*
Packit 8480eb
		 * Last element of path may be a symbolic link; all others
Packit 8480eb
		 * are directories (and the last directory element is
Packit 8480eb
		 * processed first, hence the variable name)
Packit 8480eb
		 */
Packit 8480eb
		if (rmdir(buf) == -1) {
Packit 8480eb
			if (first && errno == ENOTDIR) {
Packit 8480eb
				/*
Packit 8480eb
				 *  Ensure that we will only remove
Packit 8480eb
				 *  symbolic links.
Packit 8480eb
				 */
Packit 8480eb
				if (S_ISLNK(st.st_mode)) {
Packit 8480eb
					if (unlink(buf) == -1)
Packit 8480eb
						return -1;
Packit 8480eb
				} else {
Packit 8480eb
					crit(ap->logopt,
Packit 8480eb
					   "file \"%s\" is neither a directory"
Packit 8480eb
					   " nor a symbolic link. mode %d",
Packit 8480eb
					   buf, st.st_mode);
Packit 8480eb
					return -1;
Packit 8480eb
				}
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			/*
Packit 8480eb
			 *  If we fail to remove a directory for any reason,
Packit 8480eb
			 *  we need to return an error.
Packit 8480eb
			 */
Packit 8480eb
			return -1;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		first = 0;
Packit 8480eb
	} while ((cp = strrchr(buf, '/')) != NULL && cp != buf);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Like ftw, except fn gets called twice: before a directory is
Packit 8480eb
   entered, and after.  If the before call returns 0, the directory
Packit 8480eb
   isn't entered. */
Packit 8480eb
static int walk_tree(const char *base, int (*fn) (struct autofs_point *ap,
Packit 8480eb
						  const char *file,
Packit 8480eb
						  const struct stat * st,
Packit 8480eb
						  int, void *), int incl,
Packit 8480eb
						  struct autofs_point *ap,
Packit 8480eb
						  void *arg)
Packit 8480eb
{
Packit 8480eb
	char buf[PATH_MAX + 1];
Packit 8480eb
	struct stat st, *pst = &st;
Packit 8480eb
	int ret;
Packit 8480eb
Packit Service 42268b
	if (!is_mounted(_PATH_MOUNTED, base, MNTS_REAL))
Packit 8480eb
		ret = lstat(base, pst);
Packit 8480eb
	else {
Packit 8480eb
		pst = NULL;
Packit 8480eb
		ret = 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (ret != -1 && (fn) (ap, base, pst, 0, arg)) {
Packit 8480eb
		if (S_ISDIR(st.st_mode)) {
Packit 8480eb
			struct dirent **de;
Packit 8480eb
			int n;
Packit 8480eb
Packit 8480eb
			n = scandir(base, &de, 0, alphasort);
Packit 8480eb
			if (n < 0)
Packit 8480eb
				return -1;
Packit 8480eb
Packit 8480eb
			while (n--) {
Packit 8480eb
				if (strcmp(de[n]->d_name, ".") == 0 ||
Packit 8480eb
				    strcmp(de[n]->d_name, "..") == 0) {
Packit 8480eb
					free(de[n]);
Packit 8480eb
					continue;
Packit 8480eb
				}
Packit 8480eb
Packit 8480eb
				if (!cat_path(buf, sizeof(buf), base, de[n]->d_name)) {
Packit 8480eb
					do {
Packit 8480eb
						free(de[n]);
Packit 8480eb
					} while (n--);
Packit 8480eb
					free(de);
Packit 8480eb
					return -1;
Packit 8480eb
				}
Packit 8480eb
Packit 8480eb
				walk_tree(buf, fn, 1, ap, arg);
Packit 8480eb
				free(de[n]);
Packit 8480eb
			}
Packit 8480eb
			free(de);
Packit 8480eb
		}
Packit 8480eb
		if (incl)
Packit 8480eb
			(fn) (ap, base, pst, 1, arg);
Packit 8480eb
	}
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int rm_unwanted_fn(struct autofs_point *ap,
Packit 8480eb
			  const char *file, const struct stat *st,
Packit 8480eb
			  int when, void *arg)
Packit 8480eb
{
Packit 8480eb
	dev_t dev = *(dev_t *) arg;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
	struct stat newst;
Packit 8480eb
Packit 8480eb
	if (!st)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	if (when == 0) {
Packit 8480eb
		if (st->st_dev != dev)
Packit 8480eb
			return 0;
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (lstat(file, &newst)) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "unable to stat file, possible race condition");
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (newst.st_dev != dev) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "file %s has the wrong device, possible race condition",
Packit 8480eb
		     file);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (S_ISDIR(newst.st_mode)) {
Packit 8480eb
		debug(ap->logopt, "removing directory %s", file);
Packit 8480eb
		if (rmdir(file)) {
Packit 8480eb
			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
			warn(ap->logopt,
Packit 8480eb
			      "unable to remove directory %s: %s", file, estr);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
	} else if (S_ISREG(newst.st_mode)) {
Packit 8480eb
		crit(ap->logopt, "attempting to remove files from a mounted "
Packit 8480eb
		     "directory. file %s", file);
Packit 8480eb
		return 0;
Packit 8480eb
	} else if (S_ISLNK(newst.st_mode)) {
Packit 8480eb
		debug(ap->logopt, "removing symlink %s", file);
Packit 8480eb
		unlink(file);
Packit 8480eb
	}
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void rm_unwanted(struct autofs_point *ap, const char *path, int incl)
Packit 8480eb
{
Packit 8480eb
	walk_tree(path, rm_unwanted_fn, incl, ap, &ap->dev);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
struct counter_args {
Packit 8480eb
	unsigned int count;
Packit 8480eb
	dev_t dev;
Packit 8480eb
};
Packit 8480eb
Packit 8480eb
static int counter_fn(struct autofs_point *ap, const char *file,
Packit 8480eb
		      const struct stat *st, int when, void *arg)
Packit 8480eb
{
Packit 8480eb
	struct counter_args *counter = (struct counter_args *) arg;
Packit 8480eb
Packit 8480eb
	if (!st || (S_ISLNK(st->st_mode) || (S_ISDIR(st->st_mode)
Packit 8480eb
		&& st->st_dev != counter->dev))) {
Packit 8480eb
		counter->count++;
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Count mounted filesystems and symlinks */
Packit 8480eb
int count_mounts(struct autofs_point *ap, const char *path, dev_t dev)
Packit 8480eb
{
Packit 8480eb
	struct counter_args counter;
Packit 8480eb
Packit 8480eb
	counter.count = 0;
Packit 8480eb
	counter.dev = dev;
Packit 8480eb
	
Packit 8480eb
	if (walk_tree(path, counter_fn, 1, ap, &counter) == -1)
Packit 8480eb
		return -1;
Packit 8480eb
Packit 8480eb
	return counter.count;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void check_rm_dirs(struct autofs_point *ap, const char *path, int incl)
Packit 8480eb
{
Packit 8480eb
	/*
Packit 8480eb
	 * If we're a submount the kernel can't know we're trying to
Packit 8480eb
	 * shutdown and so cannot block processes walking into the
Packit 8480eb
	 * mount point directory. If this is the call to umount_multi()
Packit 8480eb
	 * made during shutdown (incl == 0) we have to leave any mount
Packit 8480eb
	 * point directories in place so we can recover if needed. The
Packit 8480eb
	 * umount itself will clean these directories up for us
Packit 8480eb
	 * automagically.
Packit 8480eb
	 */
Packit 8480eb
	if (!incl && ap->submount)
Packit 8480eb
		return;
Packit 8480eb
Packit 8480eb
	if ((!(ap->flags & MOUNT_FLAG_GHOST)) ||
Packit 8480eb
	    (ap->state == ST_SHUTDOWN_PENDING ||
Packit 8480eb
	     ap->state == ST_SHUTDOWN_FORCE ||
Packit 8480eb
	     ap->state == ST_SHUTDOWN))
Packit 8480eb
		rm_unwanted(ap, path, incl);
Packit 8480eb
	else if ((ap->flags & MOUNT_FLAG_GHOST) && (ap->type == LKP_INDIRECT))
Packit 8480eb
		rm_unwanted(ap, path, 0);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Try to purge cache entries kept around due to existing mounts */
Packit 8480eb
static void update_map_cache(struct autofs_point *ap, const char *path)
Packit 8480eb
{
Packit 8480eb
	struct map_source *map;
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	const char *key;
Packit 8480eb
Packit 8480eb
	if (ap->type == LKP_INDIRECT)
Packit 8480eb
		key = strrchr(path, '/') + 1;
Packit 8480eb
	else
Packit 8480eb
		key = path;
Packit 8480eb
Packit 8480eb
	map = ap->entry->maps;
Packit 8480eb
	while (map) {
Packit 8480eb
		struct mapent *me = NULL;
Packit 8480eb
Packit 8480eb
		/* Skip current, in-use cache */
Packit 8480eb
		if (ap->entry->age <= map->age) {
Packit 8480eb
			map = map->next;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		mc = map->mc;
Packit 8480eb
		/* If the lock is busy try later */
Packit 8480eb
		if (cache_try_writelock(mc)) {
Packit 8480eb
			me = cache_lookup_distinct(mc, key);
Packit 8480eb
			if (me && me->ioctlfd == -1)
Packit 8480eb
				cache_delete(mc, key);
Packit 8480eb
			cache_unlock(mc);
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		map = map->next;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int umount_subtree_mounts(struct autofs_point *ap, const char *path, unsigned int is_autofs_fs)
Packit 8480eb
{
Packit 8480eb
	struct mapent_cache *mc;
Packit 8480eb
	struct mapent *me;
Packit 8480eb
	unsigned int is_mm_root = 0;
Packit 8480eb
	int left;
Packit 8480eb
Packit 8480eb
	me = lookup_source_mapent(ap, path, LKP_DISTINCT);
Packit 8480eb
	if (!me) {
Packit 8480eb
		char *ind_key;
Packit 8480eb
Packit 8480eb
		ind_key = strrchr(path, '/');
Packit 8480eb
		if (ind_key)
Packit 8480eb
			ind_key++;
Packit 8480eb
Packit 8480eb
		me = lookup_source_mapent(ap, ind_key, LKP_NORMAL);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (me) {
Packit 8480eb
		mc = me->mc;
Packit 8480eb
		is_mm_root = (me->multi == me);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	left = 0;
Packit 8480eb
Packit 8480eb
	if (me && me->multi) {
Packit 8480eb
		char root[PATH_MAX];
Packit 8480eb
		char *base;
Packit 8480eb
		int cur_state;
Packit 8480eb
Packit 8480eb
		pthread_cleanup_push(cache_lock_cleanup, mc);
Packit 8480eb
Packit 8480eb
		if (!strchr(me->multi->key, '/'))
Packit 8480eb
			/* Indirect multi-mount root */
Packit 8480eb
			/* sprintf okay - if it's mounted, it's
Packit 8480eb
			 * PATH_MAX or less bytes */
Packit 8480eb
			sprintf(root, "%s/%s", ap->path, me->multi->key);
Packit 8480eb
		else
Packit 8480eb
			strcpy(root, me->multi->key);
Packit 8480eb
Packit 8480eb
		if (is_mm_root)
Packit 8480eb
			base = NULL;
Packit 8480eb
		else
Packit 8480eb
			base = me->key + strlen(root);
Packit 8480eb
Packit 8480eb
		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Packit 8480eb
		/* Lock the closest parent nesting point for umount */
Packit 8480eb
		cache_multi_writelock(me->parent);
Packit 8480eb
		if (umount_multi_triggers(ap, me, root, base)) {
Packit 8480eb
			warn(ap->logopt,
Packit 8480eb
			     "some offset mounts still present under %s", path);
Packit 8480eb
			left++;
Packit 8480eb
		}
Packit 8480eb
		cache_multi_unlock(me->parent);
Packit 8480eb
		if (ap->entry->maps &&
Packit 8480eb
		    (ap->entry->maps->flags & MAP_FLAG_FORMAT_AMD))
Packit 8480eb
			cache_pop_mapent(me);
Packit 8480eb
		pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
		pthread_cleanup_pop(0);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (me)
Packit 8480eb
		cache_unlock(mc);
Packit 8480eb
Packit 8480eb
	if (left || is_autofs_fs)
Packit 8480eb
		return left;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * If this is the root of a multi-mount we've had to umount
Packit 8480eb
	 * it already to ensure it's ok to remove any offset triggers.
Packit 8480eb
	 */
Packit Service 42268b
	if (!is_mm_root && is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
Packit 8480eb
		struct amd_entry *entry;
Packit 8480eb
		debug(ap->logopt, "unmounting dir = %s", path);
Packit 8480eb
		if (umount_ent(ap, path) &&
Packit Service 42268b
		    is_mounted(_PATH_MOUNTED, path, MNTS_REAL)) {
Packit 8480eb
			warn(ap->logopt, "could not umount dir %s", path);
Packit 8480eb
			left++;
Packit 8480eb
			goto done;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* Check for an external mount and umount if possible */
Packit 8480eb
		mounts_mutex_lock(ap);
Packit 8480eb
		entry = __master_find_amdmount(ap, path);
Packit 8480eb
		if (!entry) {
Packit 8480eb
			mounts_mutex_unlock(ap);
Packit 8480eb
			goto done;
Packit 8480eb
		}
Packit 8480eb
		list_del(&entry->entries);
Packit 8480eb
		mounts_mutex_unlock(ap);
Packit 8480eb
		umount_amd_ext_mount(ap, entry);
Packit 8480eb
		free_amd_entry(entry);
Packit 8480eb
	}
Packit 8480eb
done:
Packit 8480eb
	return left;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* umount all filesystems mounted under path.  If incl is true, then
Packit 8480eb
   it also tries to umount path itself */
Packit 8480eb
int umount_multi(struct autofs_point *ap, const char *path, int incl)
Packit 8480eb
{
Packit 8480eb
	int is_autofs_fs;
Packit 8480eb
	struct stat st;
Packit 8480eb
	int left;
Packit 8480eb
Packit 8480eb
	debug(ap->logopt, "path %s incl %d", path, incl);
Packit 8480eb
Packit 8480eb
	if (lstat(path, &st)) {
Packit 8480eb
		warn(ap->logopt,
Packit 8480eb
		     "failed to stat directory or symlink %s", path);
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* if this is a symlink we can handle it now */
Packit 8480eb
	if (S_ISLNK(st.st_mode)) {
Packit 8480eb
		struct amd_entry *entry;
Packit 8480eb
		if (st.st_dev != ap->dev) {
Packit 8480eb
			crit(ap->logopt,
Packit 8480eb
			     "symlink %s has the wrong device, "
Packit 8480eb
			     "possible race condition", path);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		debug(ap->logopt, "removing symlink %s", path);
Packit 8480eb
		if (unlink(path)) {
Packit 8480eb
			error(ap->logopt,
Packit 8480eb
			      "failed to remove symlink %s", path);
Packit 8480eb
			return 1;
Packit 8480eb
		}
Packit 8480eb
		/* Check for an external mount and attempt umount if needed */
Packit 8480eb
		mounts_mutex_lock(ap);
Packit 8480eb
		entry = __master_find_amdmount(ap, path);
Packit 8480eb
		if (!entry) {
Packit 8480eb
			mounts_mutex_unlock(ap);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
		list_del(&entry->entries);
Packit 8480eb
		mounts_mutex_unlock(ap);
Packit 8480eb
		umount_amd_ext_mount(ap, entry);
Packit 8480eb
		free_amd_entry(entry);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	is_autofs_fs = 0;
Packit 8480eb
	if (master_find_submount(ap, path))
Packit 8480eb
		is_autofs_fs = 1;
Packit 8480eb
Packit 8480eb
	left = 0;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * If we are a submount we need to umount any offsets our
Packit 8480eb
	 * parent may have mounted over top of us.
Packit 8480eb
	 */
Packit 8480eb
	if (ap->submount)
Packit 8480eb
		left += umount_subtree_mounts(ap->parent, path, 1);
Packit 8480eb
Packit 8480eb
	left += umount_subtree_mounts(ap, path, is_autofs_fs);
Packit 8480eb
Packit 8480eb
	/* Delete detritus like unwanted mountpoints and symlinks */
Packit 8480eb
	if (left == 0 &&
Packit 8480eb
	    ap->state != ST_READMAP &&
Packit 8480eb
	    !count_mounts(ap, path, ap->dev)) {
Packit 8480eb
		update_map_cache(ap, path);
Packit 8480eb
		check_rm_dirs(ap, path, incl);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return left;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int umount_all(struct autofs_point *ap, int force)
Packit 8480eb
{
Packit 8480eb
	int left;
Packit 8480eb
Packit 8480eb
	left = umount_multi(ap, ap->path, 0);
Packit 8480eb
	if (force && left)
Packit 8480eb
		warn(ap->logopt, "could not unmount %d dirs under %s",
Packit 8480eb
		     left, ap->path);
Packit 8480eb
Packit 8480eb
	return left;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int umount_autofs(struct autofs_point *ap, const char *root, int force)
Packit 8480eb
{
Packit 8480eb
	int ret = 0;
Packit 8480eb
Packit 8480eb
	if (ap->state == ST_INIT)
Packit 8480eb
		return -1;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * Since lookup.c is lazy about closing lookup modules
Packit 8480eb
	 * to prevent unneeded opens, we need to clean them up
Packit 8480eb
	 * before umount.
Packit 8480eb
	 */
Packit 8480eb
	lookup_close_lookup(ap);
Packit 8480eb
Packit 8480eb
	if (ap->type == LKP_INDIRECT) {
Packit 8480eb
		if (umount_all(ap, force) && !force)
Packit 8480eb
			return -1;
Packit 8480eb
		ret = umount_autofs_indirect(ap, root);
Packit 8480eb
	} else
Packit 8480eb
		ret = umount_autofs_direct(ap);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static size_t get_kpkt_len(void)
Packit 8480eb
{
Packit 8480eb
	size_t pkt_len = sizeof(struct autofs_v5_packet);
Packit 8480eb
	struct utsname un;
Packit 8480eb
	int kern_vers;
Packit 8480eb
Packit 8480eb
	kern_vers = linux_version_code();
Packit 8480eb
	if (kern_vers >= KERNEL_VERSION(3, 3, 0))
Packit 8480eb
		return pkt_len;
Packit 8480eb
Packit 8480eb
	uname(&un;;
Packit 8480eb
Packit 8480eb
	if (pkt_len % 8) {
Packit 8480eb
		if (strcmp(un.machine, "alpha") == 0 ||
Packit 8480eb
		    strcmp(un.machine, "ia64") == 0 ||
Packit 8480eb
		    strcmp(un.machine, "x86_64") == 0 ||
Packit 8480eb
		    strcmp(un.machine, "parisc64") == 0 ||
Packit 8480eb
		    strcmp(un.machine, "ppc64") == 0)
Packit 8480eb
			pkt_len += 4;
Packit 8480eb
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return pkt_len;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int fullread(int fd, void *ptr, size_t len)
Packit 8480eb
{
Packit 8480eb
	char *buf = (char *) ptr;
Packit 8480eb
Packit 8480eb
	while (len > 0) {
Packit 8480eb
		ssize_t r = read(fd, buf, len);
Packit 8480eb
Packit 8480eb
		if (r == -1) {
Packit 8480eb
			if (errno == EINTR)
Packit 8480eb
				continue;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		buf += r;
Packit 8480eb
		len -= r;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return len;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static char *automount_path_to_fifo(unsigned logopt, const char *path)
Packit 8480eb
{
Packit 8480eb
	char *fifo_name, *p;
Packit 8480eb
	int  name_len = strlen(path) + strlen(fifodir) + 1;
Packit 8480eb
	int ret;
Packit 8480eb
Packit 8480eb
	fifo_name = malloc(name_len);
Packit 8480eb
	if (!fifo_name)
Packit 8480eb
		return NULL;
Packit 8480eb
	ret = snprintf(fifo_name, name_len, "%s%s", fifodir, path);
Packit 8480eb
	if (ret >= name_len) {
Packit 8480eb
		info(logopt,
Packit 8480eb
		     "fifo path for \"%s\" truncated to \"%s\".  This may "
Packit 8480eb
		     "lead to --set-log-priority commands being sent to the "
Packit 8480eb
		     "wrong automount daemon.", path, fifo_name);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 *  An automount path can be made up of subdirectories.  So, to
Packit 8480eb
	 *  create the fifo name, we will just replace instances of '/' with
Packit 8480eb
	 *  '-'. 
Packit 8480eb
	 */
Packit 8480eb
	p = fifo_name + strlen(fifodir);
Packit 8480eb
	while (*p != '\0') {
Packit 8480eb
		if (*p == '/')
Packit 8480eb
			*p = '-';
Packit 8480eb
		p++;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	debug(logopt, "fifo name %s",fifo_name);
Packit 8480eb
Packit 8480eb
	return fifo_name;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int create_logpri_fifo(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	int ret = -1;
Packit 8480eb
	int fd;
Packit 8480eb
	char *fifo_name;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
Packit 8480eb
	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
Packit 8480eb
	if (!fifo_name) {
Packit 8480eb
		crit(ap->logopt, "Failed to allocate memory!");
Packit 8480eb
		goto out_free; /* free(NULL) is okay */
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ret = unlink(fifo_name);
Packit 8480eb
	if (ret != 0 && errno != ENOENT) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "Failed to unlink FIFO. Is the automount daemon "
Packit 8480eb
		     "already running?");
Packit 8480eb
		goto out_free;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ret = mkfifo(fifo_name, S_IRUSR|S_IWUSR);
Packit 8480eb
	if (ret != 0) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "mkfifo for %s failed: %s", fifo_name, estr);
Packit 8480eb
		goto out_free;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	fd = open_fd(fifo_name, O_RDWR|O_NONBLOCK);
Packit 8480eb
	if (fd < 0) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "Failed to open %s: %s", fifo_name, estr);
Packit 8480eb
		unlink(fifo_name);
Packit 8480eb
		ret = -1;
Packit 8480eb
		goto out_free;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ap->logpri_fifo = fd;
Packit 8480eb
Packit 8480eb
out_free:
Packit 8480eb
	free(fifo_name);
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int destroy_logpri_fifo(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	int ret = -1;
Packit 8480eb
	int fd = ap->logpri_fifo;
Packit 8480eb
	char *fifo_name;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
Packit 8480eb
	if (fd == -1)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	fifo_name = automount_path_to_fifo(ap->logopt, ap->path);
Packit 8480eb
	if (!fifo_name) {
Packit 8480eb
		crit(ap->logopt, "Failed to allocate memory!");
Packit 8480eb
		goto out_free; /* free(NULL) is okay */
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ap->logpri_fifo = -1;
Packit 8480eb
Packit 8480eb
	ret = close(fd);
Packit 8480eb
	if (ret != 0) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		warn(ap->logopt,
Packit 8480eb
		     "close for fifo %s: %s", fifo_name, estr);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ret = unlink(fifo_name);
Packit 8480eb
	if (ret != 0) {
Packit 8480eb
		warn(ap->logopt,
Packit 8480eb
		     "Failed to unlink FIFO. Was the fifo created OK?");
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
out_free:
Packit 8480eb
	free(fifo_name);
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void handle_fifo_message(struct autofs_point *ap, int fd)
Packit 8480eb
{
Packit 8480eb
	int ret;
Packit 8480eb
	char buffer[PIPE_BUF];
Packit 8480eb
	char *end;
Packit 8480eb
	long pri;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
Packit 8480eb
	memset(buffer, 0, sizeof(buffer));
Packit 8480eb
	ret = read(fd, &buffer, sizeof(buffer));
Packit 8480eb
	if (ret < 0) {
Packit 8480eb
		char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
		warn(ap->logopt, "read on fifo returned error: %s", estr);
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (ret != 2) {
Packit 8480eb
		debug(ap->logopt, "expected 2 bytes, received %d.", ret);
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	errno = 0;
Packit 8480eb
	pri = strtol(buffer, &end, 10);
Packit 8480eb
	if ((pri == LONG_MIN || pri == LONG_MAX) && errno == ERANGE) {
Packit 8480eb
		debug(ap->logopt, "strtol reported an %s.  Failed to set "
Packit 8480eb
		      "log priority.", pri == LONG_MIN ? "underflow" : "overflow");
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
	if ((pri == 0 && errno == EINVAL) || end == buffer) {
Packit 8480eb
		debug(ap->logopt, "priority is expected to be an integer "
Packit 8480eb
		      "in the range 0-7 inclusive.");
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (pri > LOG_DEBUG || pri < LOG_EMERG) {
Packit 8480eb
		debug(ap->logopt, "invalid log priority (%ld) received "
Packit 8480eb
		      "on fifo", pri);
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * OK, the message passed all of the sanity checks.  The
Packit 8480eb
	 * automounter actually only supports three log priorities.
Packit 8480eb
	 * Everything is logged at log level debug, deamon messages
Packit 8480eb
	 * and everything except debug messages are logged with the
Packit 8480eb
	 * verbose setting and only error and critical messages are
Packit 8480eb
	 * logged when debugging isn't enabled.
Packit 8480eb
	 */
Packit 8480eb
	if (pri >= LOG_WARNING) {
Packit 8480eb
		if (pri == LOG_DEBUG) {
Packit 8480eb
			set_log_debug_ap(ap);
Packit 8480eb
			info(ap->logopt, "Debug logging set for %s", ap->path);
Packit 8480eb
		} else {
Packit 8480eb
			set_log_verbose_ap(ap);
Packit 8480eb
			info(ap->logopt, "Verbose logging set for %s", ap->path);
Packit 8480eb
		}
Packit 8480eb
	} else {
Packit 8480eb
		if (ap->logopt & LOGOPT_ANY)
Packit 8480eb
			info(ap->logopt, "Basic logging set for %s", ap->path);
Packit 8480eb
		set_log_norm_ap(ap);
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int set_log_priority(const char *path, int priority)
Packit 8480eb
{
Packit 8480eb
	int fd;
Packit 8480eb
	char *fifo_name;
Packit 8480eb
	char buf[2];
Packit 8480eb
Packit 8480eb
	if (priority > LOG_DEBUG || priority < LOG_EMERG) {
Packit 8480eb
		fprintf(stderr, "Log priority %d is invalid.\n", priority);
Packit 8480eb
		fprintf(stderr, "Please specify a number in the range 0-7.\n");
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * This is an ascii based protocol, so we want the string
Packit 8480eb
	 * representation of the integer log priority.
Packit 8480eb
	 */
Packit 8480eb
	snprintf(buf, sizeof(buf), "%d", priority);
Packit 8480eb
Packit 8480eb
	fifo_name = automount_path_to_fifo(LOGOPT_NONE, path);
Packit 8480eb
	if (!fifo_name) {
Packit 8480eb
		fprintf(stderr, "%s: Failed to allocate memory!\n",
Packit 8480eb
			__FUNCTION__);
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * Specify O_NONBLOCK so that the open will fail if there is no
Packit 8480eb
	 * daemon reading from the other side of the FIFO.
Packit 8480eb
	 */
Packit 8480eb
	fd = open_fd(fifo_name, O_WRONLY|O_NONBLOCK);
Packit 8480eb
	if (fd < 0) {
Packit 8480eb
		fprintf(stderr, "%s: open of %s failed with %s\n",
Packit 8480eb
			__FUNCTION__, fifo_name, strerror(errno));
Packit 8480eb
		fprintf(stderr, "%s: perhaps the fifo wasn't setup,"
Packit 8480eb
			" please check your log for more information\n", __FUNCTION__);
Packit 8480eb
		free(fifo_name);
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (write(fd, buf, sizeof(buf)) != sizeof(buf)) {
Packit 8480eb
		fprintf(stderr, "Failed to change logging priority.  ");
Packit 8480eb
		fprintf(stderr, "write to fifo failed: %s.\n",
Packit 8480eb
			strerror(errno));
Packit 8480eb
		close(fd);
Packit 8480eb
		free(fifo_name);
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
	close(fd);
Packit 8480eb
	free(fifo_name);
Packit 8480eb
	fprintf(stdout, "Successfully set log priority for %s.\n", path);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int get_pkt(struct autofs_point *ap, union autofs_v5_packet_union *pkt)
Packit 8480eb
{
Packit 8480eb
	struct pollfd fds[3];
Packit 8480eb
	int pollfds = 3;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
	size_t read;
Packit 8480eb
	char *estr;
Packit 8480eb
Packit 8480eb
	fds[0].fd = ap->pipefd;
Packit 8480eb
	fds[0].events = POLLIN;
Packit 8480eb
	fds[1].fd = ap->state_pipe[0];
Packit 8480eb
	fds[1].events = POLLIN;
Packit 8480eb
	fds[2].fd = ap->logpri_fifo;
Packit 8480eb
	fds[2].events = POLLIN;
Packit 8480eb
	if (fds[2].fd  == -1)
Packit 8480eb
		pollfds--;
Packit 8480eb
Packit 8480eb
	for (;;) {
Packit 8480eb
		if (poll(fds, pollfds, -1) == -1) {
Packit 8480eb
			if (errno == EINTR)
Packit 8480eb
				continue;
Packit 8480eb
			estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
			logerr("poll failed: %s", estr);
Packit 8480eb
			return -1;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (fds[1].revents & POLLIN) {
Packit 8480eb
			enum states next_state;
Packit 8480eb
			size_t read_size = sizeof(next_state);
Packit 8480eb
			int state_pipe;
Packit 8480eb
Packit 8480eb
			next_state = ST_INVAL;
Packit 8480eb
Packit 8480eb
			st_mutex_lock();
Packit 8480eb
Packit 8480eb
			state_pipe = ap->state_pipe[0];
Packit 8480eb
Packit 8480eb
			read = fullread(state_pipe, &next_state, read_size);
Packit 8480eb
			if (read) {
Packit 8480eb
				estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
				error(ap->logopt,
Packit 8480eb
				      "read error on state pipe, "
Packit 8480eb
				      "read %u, error %s",
Packit 8480eb
				      read, estr);
Packit 8480eb
				st_mutex_unlock();
Packit 8480eb
				continue;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			st_mutex_unlock();
Packit 8480eb
Packit 8480eb
			if (next_state == ST_SHUTDOWN)
Packit 8480eb
				return -1;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (fds[0].revents & POLLIN) {
Packit 8480eb
			read = fullread(ap->pipefd, pkt, kpkt_len);
Packit 8480eb
			if (read) {
Packit 8480eb
				estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
				error(ap->logopt,
Packit 8480eb
				      "read error on request pipe, "
Packit 8480eb
				      "read %u, expected %u error %s",
Packit 8480eb
				       read, kpkt_len, estr);
Packit 8480eb
			}
Packit 8480eb
			return read;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (fds[2].fd != -1 && fds[2].revents & POLLIN) {
Packit 8480eb
			debug(ap->logopt, "message pending on control fifo.");
Packit 8480eb
			handle_fifo_message(ap, fds[2].fd);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int do_expire(struct autofs_point *ap, const char *name, int namelen)
Packit 8480eb
{
Packit 8480eb
	char buf[PATH_MAX];
Packit 8480eb
	int len, ret;
Packit 8480eb
Packit 8480eb
	if (*name != '/') {
Packit 8480eb
		len = ncat_path(buf, sizeof(buf), ap->path, name, namelen);
Packit 8480eb
	} else {
Packit 8480eb
		len = snprintf(buf, PATH_MAX, "%s", name);
Packit 8480eb
		if (len >= PATH_MAX)
Packit 8480eb
			len = 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!len) {
Packit 8480eb
		crit(ap->logopt, "path too long for buffer");
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	info(ap->logopt, "expiring path %s", buf);
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(master_source_lock_cleanup, ap->entry);
Packit 8480eb
	master_source_readlock(ap->entry);
Packit 8480eb
	ret = umount_multi(ap, buf, 1);
Packit 8480eb
	if (ret == 0)
Packit 8480eb
		info(ap->logopt, "expired %s", buf);
Packit 8480eb
	else
Packit 8480eb
		warn(ap->logopt, "couldn't complete expire of %s", buf);
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int autofs_init_ap(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	int pipefd[2];
Packit 8480eb
Packit 8480eb
	if ((ap->state != ST_INIT)) {
Packit 8480eb
		/* This can happen if an autofs process is already running*/
Packit 8480eb
		error(ap->logopt, "bad state %d", ap->state);
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ap->pipefd = ap->kpipefd = ap->ioctlfd = -1;
Packit 8480eb
Packit 8480eb
	/* Pipe for kernel communications */
Packit 8480eb
	if (open_pipe(pipefd) < 0) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "failed to create commumication pipe for autofs path %s",
Packit 8480eb
		     ap->path);
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	ap->pipefd = pipefd[0];
Packit 8480eb
	ap->kpipefd = pipefd[1];
Packit 8480eb
Packit 8480eb
	/* Pipe state changes from signal handler to main loop */
Packit 8480eb
	if (open_pipe(ap->state_pipe) < 0) {
Packit 8480eb
		crit(ap->logopt,
Packit 8480eb
		     "failed create state pipe for autofs path %s", ap->path);
Packit 8480eb
		close(ap->pipefd);
Packit 8480eb
		close(ap->kpipefd);	/* Close kernel pipe end */
Packit 8480eb
		return -1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (create_logpri_fifo(ap) < 0) {
Packit 8480eb
		logmsg("could not create FIFO for path %s\n", ap->path);
Packit 8480eb
		logmsg("dynamic log level changes not available for %s", ap->path);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int mount_autofs(struct autofs_point *ap, const char *root)
Packit 8480eb
{
Packit 8480eb
	int status = 0;
Packit 8480eb
Packit Service 42268b
	if (autofs_init_ap(ap) != 0)
Packit Service 42268b
		return -1;
Packit 8480eb
Packit 8480eb
	if (ap->type == LKP_DIRECT)
Packit 8480eb
		status = mount_autofs_direct(ap);
Packit 8480eb
	else
Packit 8480eb
		status = mount_autofs_indirect(ap, root);
Packit 8480eb
Packit Service 42268b
	if (status < 0)
Packit 8480eb
		return -1;
Packit 8480eb
Packit 8480eb
	st_add_task(ap, ST_READY);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int handle_packet(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	union autofs_v5_packet_union pkt;
Packit 8480eb
Packit 8480eb
	if (get_pkt(ap, &pkt))
Packit 8480eb
		return -1;
Packit 8480eb
Packit 8480eb
	debug(ap->logopt, "type = %d", pkt.hdr.type);
Packit 8480eb
Packit 8480eb
	switch (pkt.hdr.type) {
Packit 8480eb
	case autofs_ptype_missing_indirect:
Packit 8480eb
		return handle_packet_missing_indirect(ap, &pkt.v5_packet);
Packit 8480eb
Packit 8480eb
	case autofs_ptype_missing_direct:
Packit 8480eb
		return handle_packet_missing_direct(ap, &pkt.v5_packet);
Packit 8480eb
Packit 8480eb
	case autofs_ptype_expire_indirect:
Packit 8480eb
		return handle_packet_expire_indirect(ap, &pkt.v5_packet);
Packit 8480eb
Packit 8480eb
	case autofs_ptype_expire_direct:
Packit 8480eb
		return handle_packet_expire_direct(ap, &pkt.v5_packet);
Packit 8480eb
	}
Packit 8480eb
	error(ap->logopt, "unknown packet type %d", pkt.hdr.type);
Packit 8480eb
	return -1;
Packit 8480eb
}
Packit 8480eb
Packit Service 42268b
static void become_daemon(unsigned foreground, unsigned daemon_check)
Packit 8480eb
{
Packit 8480eb
	FILE *pidfp;
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
	int res;
Packit 8480eb
	pid_t pid;
Packit 8480eb
Packit 8480eb
	/* Don't BUSY any directories unnecessarily */
Packit 8480eb
	if (chdir("/")) {
Packit 8480eb
		fprintf(stderr, "%s: failed change working directory.\n",
Packit 8480eb
			program);
Packit 8480eb
		exit(0);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Detach from foreground process */
Packit Service 42268b
	if (foreground) {
Packit Service 42268b
		if (daemon_check && !aquire_flag_file()) {
Packit 8480eb
			fprintf(stderr, "%s: program is already running.\n",
Packit 8480eb
				program);
Packit 8480eb
			exit(1);
Packit 8480eb
		}
Packit 8480eb
		log_to_stderr();
Packit 8480eb
	} else {
Packit Service b3e495
		if (open_pipe(start_pipefd) < 0) {
Packit Service b3e495
			fprintf(stderr, "%s: failed to create start_pipefd.\n",
Packit Service b3e495
				program);
Packit Service b3e495
			exit(0);
Packit Service b3e495
		}
Packit Service b3e495
Packit 8480eb
		pid = fork();
Packit 8480eb
		if (pid > 0) {
Packit 8480eb
			close(start_pipefd[1]);
Packit 8480eb
			res = read(start_pipefd[0], pst_stat, sizeof(*pst_stat));
Packit 8480eb
			if (res < 0)
Packit 8480eb
				exit(1);
Packit 8480eb
			exit(*pst_stat);
Packit 8480eb
		} else if (pid < 0) {
Packit 8480eb
			fprintf(stderr, "%s: Could not detach process\n",
Packit 8480eb
				program);
Packit 8480eb
			exit(1);
Packit 8480eb
		}
Packit 8480eb
		close(start_pipefd[0]);
Packit 8480eb
Packit Service 42268b
		if (daemon_check && !aquire_flag_file()) {
Packit 8480eb
			fprintf(stderr, "%s: program is already running.\n",
Packit 8480eb
				program);
Packit 8480eb
			/* Return success if already running */
Packit 8480eb
			st_stat = 0;
Packit 8480eb
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit 8480eb
			if (res < 0)
Packit 8480eb
				exit(1);
Packit 8480eb
			close(start_pipefd[1]);
Packit 8480eb
			exit(*pst_stat);
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * Make our own process group for "magic" reason: processes that share
Packit 8480eb
		 * our pgrp see the raw filesystem behind the magic.
Packit 8480eb
		 */
Packit 8480eb
		if (setsid() == -1) {
Packit 8480eb
			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
			fprintf(stderr, "setsid: %s", estr);
Packit 8480eb
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit 8480eb
			close(start_pipefd[1]);
Packit 8480eb
			exit(*pst_stat);
Packit 8480eb
		}
Packit Service 42268b
		log_to_syslog();
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Write pid file if requested */
Packit 8480eb
	if (pid_file) {
Packit 8480eb
		if ((pidfp = fopen(pid_file, "wt"))) {
Packit 8480eb
			fprintf(pidfp, "%lu\n", (unsigned long) getpid());
Packit 8480eb
			fclose(pidfp);
Packit 8480eb
		} else {
Packit 8480eb
			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
			logerr("failed to write pid file %s: %s",
Packit 8480eb
			       pid_file, estr);
Packit 8480eb
			pid_file = NULL;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static unsigned long getnumopt(char *str, char option)
Packit 8480eb
{
Packit 8480eb
	unsigned long val;
Packit 8480eb
	char *end;
Packit 8480eb
Packit 8480eb
	val = strtoul(str, &end, 0);
Packit 8480eb
	if (!*str || *end) {
Packit 8480eb
		fprintf(stderr,
Packit 8480eb
			"%s: option -%c requires a numeric argument, got %s\n",
Packit 8480eb
			program, option, str);
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
	return val;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void do_master_cleanup_unlock(void *arg)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void *do_notify_state(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct master *master;
Packit 8480eb
	int sig;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	sig = *(int *) arg;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	master = mrc.master;
Packit 8480eb
Packit 8480eb
	debug(master->logopt, "signal %d", sig);
Packit 8480eb
Packit 8480eb
	mrc.signaled = 1;
Packit 8480eb
	status = pthread_cond_signal(&mrc.cond);
Packit 8480eb
	if (status) {
Packit 8480eb
		error(master->logopt,
Packit 8480eb
		      "failed to signal state notify condition");
Packit 8480eb
		status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		pthread_exit(NULL);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	master_notify_state_change(master, sig);
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static pthread_t do_signals(struct master *master, int sig)
Packit 8480eb
{
Packit 8480eb
	pthread_t thid;
Packit 8480eb
	int r_sig = sig;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_create(&thid, &th_attr_detached, do_notify_state, &r_sig);
Packit 8480eb
	if (status) {
Packit 8480eb
		error(master->logopt,
Packit 8480eb
		      "mount state notify thread create failed");
Packit 8480eb
		status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mrc.thid = thid;
Packit 8480eb
	mrc.master = master;
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(do_master_cleanup_unlock, NULL);
Packit 8480eb
Packit 8480eb
	mrc.signaled = 0;
Packit 8480eb
	while (!mrc.signaled) {
Packit 8480eb
		status = pthread_cond_wait(&mrc.cond, &mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return thid;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void *do_read_master(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct master *master;
Packit 8480eb
	unsigned int logopt;
Packit 8480eb
	time_t age;
Packit 8480eb
	int readall = 1;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	master = mrc.master;
Packit 8480eb
	age = mrc.age;
Packit 8480eb
	logopt = master->logopt;
Packit 8480eb
Packit 8480eb
	mrc.signaled = 1;
Packit 8480eb
	status = pthread_cond_signal(&mrc.cond);
Packit 8480eb
	if (status) {
Packit 8480eb
		error(logopt,
Packit 8480eb
		      "failed to signal master read map condition");
Packit 8480eb
		master->reading = 0;
Packit 8480eb
		status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		pthread_exit(NULL);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	defaults_read_config(1);
Packit 8480eb
Packit 8480eb
	info(logopt, "re-reading master map %s", master->name);
Packit 8480eb
Packit 8480eb
	status = master_read_master(master, age, readall);
Packit 8480eb
Packit 8480eb
	master->reading = 0;
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_hup_signal(struct master *master)
Packit 8480eb
{
Packit 8480eb
	unsigned int logopt = master->logopt;
Packit 8480eb
	time_t age = monotonic_time(NULL);
Packit 8480eb
	pthread_t thid;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&mrc.mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
Packit 8480eb
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
	/* Already doing a map read or shutdown or no mounts */
Packit 8480eb
	if (master->reading) {
Packit 8480eb
		status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		master_mutex_unlock();
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
	master->reading = 1;
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
Packit 8480eb
	status = pthread_create(&thid, &th_attr_detached, do_read_master, NULL);
Packit 8480eb
	if (status) {
Packit 8480eb
		error(logopt,
Packit 8480eb
		      "master read map thread create failed");
Packit 8480eb
		master->reading = 0;
Packit 8480eb
		status = pthread_mutex_unlock(&mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	mrc.thid = thid;
Packit 8480eb
	mrc.master = master;
Packit 8480eb
	mrc.age = age;
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(do_master_cleanup_unlock, NULL);
Packit 8480eb
Packit 8480eb
	mrc.signaled = 0;
Packit 8480eb
	while (!mrc.signaled) {
Packit 8480eb
		status = pthread_cond_wait(&mrc.cond, &mrc.mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
/* Deal with all the signal-driven events in the state machine */
Packit 8480eb
static void *statemachine(void *arg)
Packit 8480eb
{
Packit 8480eb
	sigset_t signalset;
Packit 8480eb
	int sig;
Packit 8480eb
Packit 8480eb
	memcpy(&signalset, &block_sigs, sizeof(signalset));
Packit 8480eb
	sigdelset(&signalset, SIGCHLD);
Packit 8480eb
	sigdelset(&signalset, SIGCONT);
Packit 8480eb
Packit 8480eb
	while (1) {
Packit 8480eb
		sigwait(&signalset, &sig);
Packit 8480eb
Packit 8480eb
		switch (sig) {
Packit 8480eb
		case SIGTERM:
Packit 8480eb
		case SIGINT:
Packit 8480eb
		case SIGUSR2:
Packit 8480eb
			master_mutex_lock();
Packit 8480eb
			if (list_empty(&master_list->completed)) {
Packit 8480eb
				if (list_empty(&master_list->mounts)) {
Packit 8480eb
					master_mutex_unlock();
Packit 8480eb
					return NULL;
Packit 8480eb
				}
Packit 8480eb
			} else {
Packit 8480eb
				if (master_done(master_list)) {
Packit 8480eb
					master_mutex_unlock();
Packit 8480eb
					return NULL;
Packit 8480eb
				}
Packit 8480eb
				master_mutex_unlock();
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
			master_mutex_unlock();
Packit 8480eb
Packit 8480eb
		case SIGUSR1:
Packit 8480eb
			do_signals(master_list, sig);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case SIGHUP:
Packit 8480eb
			do_hup_signal(master_list);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		default:
Packit 8480eb
			logerr("got unexpected signal %d!", sig);
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void return_start_status(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct startup_cond *sc;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	sc = (struct startup_cond *) arg;
Packit 8480eb
Packit 8480eb
	sc->done = 1;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * Startup condition mutex must be locked during 
Packit 8480eb
	 * the startup process.
Packit 8480eb
	 */
Packit 8480eb
	status = pthread_cond_signal(&sc->cond);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&sc->mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int handle_mounts_startup_cond_init(struct startup_cond *suc)
Packit 8480eb
{
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_init(&suc->mutex, NULL);
Packit 8480eb
	if (status)
Packit 8480eb
		return status;
Packit 8480eb
Packit 8480eb
	status = pthread_cond_init(&suc->cond, NULL);
Packit 8480eb
	if (status) {
Packit 8480eb
		status = pthread_mutex_destroy(&suc->mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		return status;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&suc->mutex);
Packit 8480eb
	if (status) {
Packit 8480eb
		status = pthread_mutex_destroy(&suc->mutex);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
		status = pthread_cond_destroy(&suc->cond);
Packit 8480eb
		if (status)
Packit 8480eb
			fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void handle_mounts_startup_cond_destroy(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct startup_cond *suc = (struct startup_cond *) arg;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_unlock(&suc->mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_destroy(&suc->mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	status = pthread_cond_destroy(&suc->cond);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void handle_mounts_cleanup(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	char path[PATH_MAX + 1];
Packit 8480eb
	char buf[MAX_ERR_BUF];
Packit 8480eb
	unsigned int clean = 0, submount, logopt;
Packit 8480eb
	unsigned int pending = 0;
Packit 8480eb
Packit 8480eb
	ap = (struct autofs_point *) arg;
Packit 8480eb
Packit 8480eb
	logopt = ap->logopt;
Packit 8480eb
	submount = ap->submount;
Packit 8480eb
Packit 8480eb
	strcpy(path, ap->path);
Packit 8480eb
	if (!submount && strcmp(ap->path, "/-") &&
Packit 8480eb
	    ap->flags & MOUNT_FLAG_DIR_CREATED)
Packit 8480eb
		clean = 1;
Packit 8480eb
Packit 8480eb
	if (submount) {
Packit 8480eb
		struct amd_entry *am;
Packit 8480eb
		/* We are finishing up */
Packit 8480eb
		ap->parent->submnt_count--;
Packit 8480eb
		list_del_init(&ap->mounts);
Packit 8480eb
		am = __master_find_amdmount(ap->parent, ap->path);
Packit 8480eb
		if (am) {
Packit 8480eb
			list_del_init(&am->entries);
Packit 8480eb
			free_amd_entry(am);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Don't signal the handler if we have already done so */
Packit 8480eb
	if (!list_empty(&master_list->completed))
Packit 8480eb
		pending = 1;
Packit 8480eb
	master_remove_mapent(ap->entry);
Packit 8480eb
	master_source_unlock(ap->entry);
Packit 8480eb
Packit 8480eb
	destroy_logpri_fifo(ap);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * Submounts are detached threads and don't belong to the
Packit 8480eb
	 * master map entry list so we need to free their resources
Packit 8480eb
	 * here.
Packit 8480eb
	 */
Packit 8480eb
	if (submount) {
Packit 8480eb
		mounts_mutex_unlock(ap->parent);
Packit 8480eb
		master_source_unlock(ap->parent->entry);
Packit 8480eb
		master_free_mapent_sources(ap->entry, 1);
Packit 8480eb
		master_free_mapent(ap->entry);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (clean) {
Packit 8480eb
		if (rmdir(path) == -1) {
Packit 8480eb
			char *estr = strerror_r(errno, buf, MAX_ERR_BUF);
Packit 8480eb
			warn(logopt, "failed to remove dir %s: %s",
Packit 8480eb
			     path, estr);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	info(logopt, "shut down path %s", path);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * If we are not a submount send a signal to the signal handler
Packit 8480eb
	 * so it can join with any completed handle_mounts() threads and
Packit 8480eb
	 * perform final cleanup.
Packit 8480eb
	 */
Packit 8480eb
	if (!submount && !pending)
Packit 8480eb
		pthread_kill(state_mach_thid, SIGTERM);
Packit 8480eb
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int submount_source_writelock_nested(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	struct autofs_point *parent = ap->parent;
Packit 8480eb
	int status;
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_trywrlock(&parent->entry->source_lock);
Packit 8480eb
	if (status)
Packit 8480eb
		goto done;
Packit 8480eb
Packit 8480eb
	mounts_mutex_lock(parent);
Packit 8480eb
Packit 8480eb
	status = pthread_rwlock_trywrlock(&ap->entry->source_lock);
Packit 8480eb
	if (status) {
Packit 8480eb
		mounts_mutex_unlock(parent);
Packit 8480eb
		master_source_unlock(parent->entry);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
done:
Packit 8480eb
	if (status && status != EBUSY) {
Packit 8480eb
		logmsg("submount nested master_mapent source write lock failed");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return status;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void submount_source_unlock_nested(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	struct autofs_point *parent = ap->parent;
Packit 8480eb
Packit 8480eb
	master_source_unlock(ap->entry);
Packit 8480eb
	mounts_mutex_unlock(parent);
Packit 8480eb
	master_source_unlock(parent->entry);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int handle_mounts_exit(struct autofs_point *ap)
Packit 8480eb
{
Packit 8480eb
	int ret, cur_state;
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * If we're a submount we need to ensure our parent
Packit 8480eb
	 * doesn't try to mount us again until our shutdown
Packit 8480eb
	 * is complete and that any outstanding mounts are
Packit 8480eb
	 * completed before we try to shutdown.
Packit 8480eb
	 */
Packit 8480eb
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
Packit 8480eb
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
Packit 8480eb
	if (!ap->submount)
Packit 8480eb
		master_source_writelock(ap->entry);
Packit 8480eb
	else {
Packit 8480eb
		/*
Packit 8480eb
		 * If a mount request arrives before the locks are
Packit 8480eb
		 * aquired just return to ready state.
Packit 8480eb
		 */
Packit 8480eb
		ret = submount_source_writelock_nested(ap);
Packit 8480eb
		if (ret) {
Packit 8480eb
			warn(ap->logopt,
Packit 8480eb
			     "can't shutdown submount: mount in progress");
Packit 8480eb
			/* Return to ST_READY is done immediately */
Packit 8480eb
			st_add_task(ap, ST_READY);
Packit 8480eb
			master_mutex_unlock();
Packit 8480eb
			pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (ap->state != ST_SHUTDOWN) {
Packit 8480eb
		if (!ap->submount)
Packit 8480eb
			alarm_add(ap, ap->exp_runfreq);
Packit 8480eb
		/* Return to ST_READY is done immediately */
Packit 8480eb
		st_add_task(ap, ST_READY);
Packit 8480eb
		if (ap->submount)
Packit 8480eb
			submount_source_unlock_nested(ap);
Packit 8480eb
		else
Packit 8480eb
			master_source_unlock(ap->entry);
Packit 8480eb
		master_mutex_unlock();
Packit 8480eb
Packit 8480eb
		pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	alarm_delete(ap);
Packit 8480eb
	st_remove_tasks(ap);
Packit 8480eb
	st_wait_task(ap, ST_ANY, 0);
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * For a direct mount map all mounts have already gone
Packit 8480eb
	 * by the time we get here and since we only ever
Packit 8480eb
	 * umount direct mounts at shutdown there is no need
Packit 8480eb
	 * to check for possible recovery.
Packit 8480eb
	 */
Packit 8480eb
	if (ap->type == LKP_DIRECT) {
Packit 8480eb
		umount_autofs(ap, NULL, 1);
Packit 8480eb
		handle_mounts_cleanup(ap);
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/*
Packit 8480eb
	 * If umount_autofs returns non-zero it wasn't able
Packit 8480eb
	 * to complete the umount and has left the mount intact
Packit 8480eb
	 * so we can continue. This can happen if a lookup
Packit 8480eb
	 * occurs while we're trying to umount.
Packit 8480eb
	 */
Packit 8480eb
	ret = umount_autofs(ap, NULL, 1);
Packit 8480eb
	if (!ret) {
Packit 8480eb
		set_indirect_mount_tree_catatonic(ap);
Packit 8480eb
		handle_mounts_cleanup(ap);
Packit 8480eb
		return 1;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Failed shutdown returns to ready */
Packit 8480eb
	warn(ap->logopt, "can't shutdown: filesystem %s still busy", ap->path);
Packit 8480eb
	if (!ap->submount)
Packit 8480eb
		alarm_add(ap, ap->exp_runfreq);
Packit 8480eb
	/* Return to ST_READY is done immediately */
Packit 8480eb
	st_add_task(ap, ST_READY);
Packit 8480eb
	if (ap->submount)
Packit 8480eb
		submount_source_unlock_nested(ap);
Packit 8480eb
	else
Packit 8480eb
		master_source_unlock(ap->entry);
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
Packit 8480eb
	pthread_setcancelstate(cur_state, NULL);
Packit 8480eb
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void *handle_mounts(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct startup_cond *suc;
Packit 8480eb
	struct autofs_point *ap;
Packit 8480eb
	int cancel_state, status = 0;
Packit 8480eb
	char *root;
Packit 8480eb
Packit 8480eb
	suc = (struct startup_cond *) arg;
Packit 8480eb
Packit 8480eb
	ap = suc->ap;
Packit 8480eb
	root = strdup(suc->root);
Packit 8480eb
Packit 8480eb
	pthread_cleanup_push(return_start_status, suc);
Packit 8480eb
	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
Packit 8480eb
Packit 8480eb
	status = pthread_mutex_lock(&suc->mutex);
Packit 8480eb
	if (status) {
Packit 8480eb
		logerr("failed to lock startup condition mutex!");
Packit 8480eb
		fatal(status);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!root) {
Packit 8480eb
		crit(ap->logopt, "failed to alloc string root");
Packit 8480eb
		suc->status = 1;
Packit 8480eb
		pthread_setcancelstate(cancel_state, NULL);
Packit 8480eb
		pthread_exit(NULL);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (mount_autofs(ap, root) < 0) {
Packit Service 42268b
		crit(ap->logopt, "mount of %s failed!", ap->path);
Packit 8480eb
		suc->status = 1;
Packit 8480eb
		umount_autofs(ap, root, 1);
Packit 8480eb
		free(root);
Packit 8480eb
		pthread_setcancelstate(cancel_state, NULL);
Packit 8480eb
		pthread_exit(NULL);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	free(root);
Packit 8480eb
Packit 8480eb
	if (ap->flags & MOUNT_FLAG_NOBIND)
Packit 8480eb
		info(ap->logopt, "bind mounts disabled");
Packit 8480eb
Packit 8480eb
	if (ap->flags & MOUNT_FLAG_GHOST && ap->type != LKP_DIRECT)
Packit 8480eb
		info(ap->logopt, "ghosting enabled");
Packit 8480eb
Packit 8480eb
	suc->status = 0;
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
Packit 8480eb
	/* We often start several automounters at the same time.  Add some
Packit 8480eb
	   randomness so we don't all expire at the same time. */
Packit 8480eb
	if (!ap->submount && ap->exp_runfreq)
Packit 8480eb
		alarm_add(ap, ap->exp_runfreq + rand() % ap->exp_runfreq);
Packit 8480eb
Packit 8480eb
	pthread_setcancelstate(cancel_state, NULL);
Packit 8480eb
Packit 8480eb
	while (1) {
Packit 8480eb
		if (handle_packet(ap)) {
Packit 8480eb
			if (handle_mounts_exit(ap))
Packit 8480eb
				break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* If we get here a packet has been received and handled
Packit 8480eb
		 * and the autofs mount point has not been shutdown. But
Packit 8480eb
		 * if the autofs mount point has been set to ST_SHUTDOWN
Packit 8480eb
		 * we should attempt to perform the shutdown cleanup and
Packit 8480eb
		 * exit if successful.
Packit 8480eb
		 */
Packit 8480eb
		if (ap->state == ST_SHUTDOWN) {
Packit 8480eb
			if (handle_mounts_exit(ap))
Packit 8480eb
				break;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return NULL;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void key_thread_stdenv_vars_destroy(void *arg)
Packit 8480eb
{
Packit 8480eb
	struct thread_stdenv_vars *tsv;
Packit 8480eb
Packit 8480eb
	tsv = (struct thread_stdenv_vars *) arg;
Packit 8480eb
	if (tsv->user)
Packit 8480eb
		free(tsv->user);
Packit 8480eb
	if (tsv->group)
Packit 8480eb
		free(tsv->group);
Packit 8480eb
	if (tsv->home)
Packit 8480eb
		free(tsv->home);
Packit 8480eb
	free(tsv);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void usage(void)
Packit 8480eb
{
Packit 8480eb
	fprintf(stderr,
Packit 8480eb
		"Usage: %s [options] [master_map_name]\n"
Packit 8480eb
		"	-h --help	this text\n"
Packit 8480eb
		"	-p --pid-file f write process id to file f\n"
Packit 8480eb
		"	-t --timeout n	auto-unmount in n seconds (0-disable)\n"
Packit 8480eb
		"	-v --verbose	be verbose\n"
Packit 8480eb
		"	-d --debug	log debuging info\n"
Packit Service 42268b
		"	-D --define	define global macro variable\n"
Packit 8480eb
		"	-f --foreground do not fork into background\n"
Packit 8480eb
		"	-r --random-multimount-selection\n"
Packit 8480eb
		"			use ramdom replicated server selection\n"
Packit 8480eb
		"	-m --dumpmaps [<map type> <map name>]\n"
Packit 8480eb
		"			dump automounter maps and exit\n"
Packit 8480eb
		"	-n --negative-timeout n\n"
Packit 8480eb
		"			set the timeout for failed key lookups.\n"
Packit 8480eb
		"	-O --global-options\n"
Packit 8480eb
		"			specify global mount options\n"
Packit 8480eb
		"	-l --set-log-priority priority path [path,...]\n"
Packit 8480eb
		"			set daemon log verbosity\n"
Packit 8480eb
		"	-C --dont-check-daemon\n"
Packit 8480eb
		"			don't check if daemon is already running\n"
Packit 8480eb
		"	-F --force	forceably clean up known automounts at start\n"
Packit 8480eb
		"	-V --version	print version, build config and exit\n"
Packit 8480eb
		, program);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void show_build_info(void)
Packit 8480eb
{
Packit 8480eb
	int count = 0;
Packit 8480eb
Packit 8480eb
	printf("\nLinux automount version %s\n", version);
Packit 8480eb
Packit 8480eb
	printf("\nDirectories:\n");
Packit 8480eb
	printf("\tconfig dir:\t%s\n", confdir);
Packit 8480eb
	printf("\tmaps dir:\t%s\n", mapdir);
Packit 8480eb
	printf("\tmodules dir:\t%s\n", libdir);
Packit 8480eb
Packit 8480eb
	printf("\nCompile options:\n  ");
Packit 8480eb
Packit 8480eb
#ifndef ENABLE_MOUNT_LOCKING
Packit 8480eb
	printf("DISABLE_MOUNT_LOCKING ");
Packit 8480eb
	count = 22;
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef ENABLE_FORCED_SHUTDOWN
Packit 8480eb
	printf("ENABLE_FORCED_SHUTDOWN ");
Packit 8480eb
	count = count + 23;
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef ENABLE_IGNORE_BUSY_MOUNTS
Packit 8480eb
	printf("ENABLE_IGNORE_BUSY_MOUNTS ");
Packit 8480eb
	count = count + 26;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
Packit 8480eb
#ifdef WITH_HESIOD
Packit 8480eb
	printf("WITH_HESIOD ");
Packit 8480eb
	count = count + 12;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef WITH_LDAP
Packit 8480eb
	printf("WITH_LDAP ");
Packit 8480eb
	count = count + 10;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef WITH_SASL
Packit 8480eb
	printf("WITH_SASL ");
Packit 8480eb
	count = count + 10;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef WITH_DMALLOC
Packit 8480eb
	printf("WITH_DMALLOC ");
Packit 8480eb
	count = count + 13;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef LIBXML2_WORKAROUND
Packit 8480eb
	printf("LIBXML2_WORKAROUND ");
Packit 8480eb
	count = count + 19;
Packit 8480eb
Packit 8480eb
	if (count > 60) {
Packit 8480eb
		printf("\n  ");
Packit 8480eb
		count = 0;
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#ifdef WITH_LIBTIRPC
Packit 8480eb
	printf("WITH_LIBTIRPC ");
Packit 8480eb
	count = count + 14;
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
	printf("\n\n");
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
typedef struct _code {
Packit 8480eb
	char	*c_name;
Packit 8480eb
	int	c_val;
Packit 8480eb
} CODE;
Packit 8480eb
Packit 8480eb
CODE prioritynames[] = {
Packit 8480eb
	{ "alert",	LOG_ALERT },
Packit 8480eb
	{ "crit",	LOG_CRIT },
Packit 8480eb
	{ "debug",	LOG_DEBUG },
Packit 8480eb
	{ "emerg",	LOG_EMERG },
Packit 8480eb
	{ "err",	LOG_ERR },
Packit 8480eb
	{ "error",	LOG_ERR },		/* DEPRECATED */
Packit 8480eb
	{ "info",	LOG_INFO },
Packit 8480eb
	{ "notice",	LOG_NOTICE },
Packit 8480eb
	{ "panic", 	LOG_EMERG },		/* DEPRECATED */
Packit 8480eb
	{ "warn",	LOG_WARNING },		/* DEPRECATED */
Packit 8480eb
	{ "warning",	LOG_WARNING },
Packit 8480eb
	{ NULL,		-1 },
Packit 8480eb
};
Packit 8480eb
Packit 8480eb
static int convert_log_priority(char *priority_name)
Packit 8480eb
{
Packit 8480eb
	CODE *priority_mapping;
Packit 8480eb
Packit 8480eb
	for (priority_mapping = prioritynames;
Packit 8480eb
	     priority_mapping->c_name != NULL;
Packit 8480eb
	     priority_mapping++) {
Packit 8480eb
Packit 8480eb
		if (!strcasecmp(priority_name, priority_mapping->c_name))
Packit 8480eb
			return priority_mapping->c_val;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return -1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void remove_empty_args(char **argv, int *argc)
Packit 8480eb
{
Packit 8480eb
	int next_to_last = *argc - 1;
Packit 8480eb
	int i, j;
Packit 8480eb
Packit 8480eb
	for (i = j = 1; i < *argc; i++) {
Packit 8480eb
		if (*argv[i]) {
Packit 8480eb
			j++;
Packit 8480eb
			continue;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		while (i < *argc && argv[i] && !*argv[i]) i++;
Packit 8480eb
Packit 8480eb
		if (i == *argc)
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		if (i == next_to_last) {
Packit 8480eb
			if (*argv[i])
Packit 8480eb
				argv[j++] = argv[i];
Packit 8480eb
			break;
Packit 8480eb
		} else {
Packit 8480eb
			argv[j++] = argv[i];
Packit 8480eb
			argv[i--] = "";
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	*argc = j;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void do_master_list_reset(struct master *master)
Packit 8480eb
{
Packit Service bd6ddb
	struct list_head *head, *p, *n;
Packit 8480eb
Packit 8480eb
	master_mutex_lock();
Packit 8480eb
Packit 8480eb
	head = &master->mounts;
Packit Service bd6ddb
	n = head->next;
Packit Service bd6ddb
	while (n != head) {
Packit 8480eb
		struct master_mapent *entry;
Packit 8480eb
Packit Service bd6ddb
		p = n;
Packit Service bd6ddb
		n = p->next;
Packit Service bd6ddb
Packit 8480eb
		entry = list_entry(p, struct master_mapent, list);
Packit 8480eb
Packit 8480eb
		if (!list_empty(&entry->list))
Packit 8480eb
			list_del(&entry->list);
Packit 8480eb
		master_free_mapent_sources(entry, 1);
Packit 8480eb
		master_free_mapent(entry);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	master_mutex_unlock();
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int do_master_read_master(struct master *master, int wait)
Packit 8480eb
{
Packit 8480eb
	sigset_t signalset;
Packit 8480eb
	/* Wait must be at least 1 second */
Packit 8480eb
	unsigned int retry_wait = 2;
Packit 8480eb
	unsigned int elapsed = 0;
Packit 8480eb
	int max_wait = wait;
Packit 8480eb
	int ret = 0;
Packit 8480eb
	time_t age;
Packit 8480eb
Packit 8480eb
	sigemptyset(&signalset);
Packit 8480eb
	sigaddset(&signalset, SIGTERM);
Packit 8480eb
	sigaddset(&signalset, SIGINT);
Packit 8480eb
	sigaddset(&signalset, SIGHUP);
Packit 8480eb
	sigprocmask(SIG_UNBLOCK, &signalset, NULL);
Packit 8480eb
Packit 8480eb
	while (1) {
Packit 8480eb
		struct timespec t = { retry_wait, 0 };
Packit 8480eb
Packit 8480eb
		do_master_list_reset(master);
Packit 8480eb
Packit 8480eb
		age = monotonic_time(NULL);
Packit 8480eb
		if (master_read_master(master, age, 0)) {
Packit 8480eb
			ret = 1;
Packit 8480eb
			break;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (nanosleep(&t, NULL) == -1)
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		if (max_wait > 0) {
Packit 8480eb
			elapsed += retry_wait;
Packit 8480eb
			if (elapsed >= max_wait) {
Packit 8480eb
				logmsg("problem reading master map, "
Packit 8480eb
					"maximum wait exceeded");
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	sigprocmask(SIG_BLOCK, &signalset, NULL);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int main(int argc, char *argv[])
Packit 8480eb
{
Packit 8480eb
	int res, opt, status;
Packit 8480eb
	int logpri = -1;
Packit Service 42268b
	unsigned ghost, logging, daemon_check;
Packit Service 42268b
	unsigned dumpmaps, foreground, have_global_options;
Packit 8480eb
	unsigned master_read;
Packit 8480eb
	int master_wait;
Packit 8480eb
	time_t timeout;
Packit 8480eb
	time_t age = monotonic_time(NULL);
Packit 8480eb
	struct rlimit rlim;
Packit Service 42268b
	const char *options = "+hp:t:vmdD:fVrO:l:n:CFM";
Packit 8480eb
	static const struct option long_options[] = {
Packit 8480eb
		{"help", 0, 0, 'h'},
Packit 8480eb
		{"pid-file", 1, 0, 'p'},
Packit 8480eb
		{"timeout", 1, 0, 't'},
Packit 8480eb
		{"verbose", 0, 0, 'v'},
Packit 8480eb
		{"debug", 0, 0, 'd'},
Packit 8480eb
		{"define", 1, 0, 'D'},
Packit 8480eb
		{"foreground", 0, 0, 'f'},
Packit 8480eb
		{"random-multimount-selection", 0, 0, 'r'},
Packit 8480eb
		{"negative-timeout", 1, 0, 'n'},
Packit 8480eb
		{"dumpmaps", 0, 0, 'm'},
Packit 8480eb
		{"global-options", 1, 0, 'O'},
Packit 8480eb
		{"version", 0, 0, 'V'},
Packit 8480eb
		{"set-log-priority", 1, 0, 'l'},
Packit 8480eb
		{"dont-check-daemon", 0, 0, 'C'},
Packit 8480eb
		{"force", 0, 0, 'F'},
Packit 8480eb
		{"master-wait", 1, 0, 'M'},
Packit 8480eb
		{0, 0, 0, 0}
Packit 8480eb
	};
Packit 8480eb
Packit 8480eb
	sigfillset(&block_sigs);
Packit 8480eb
	/* allow for the dropping of core files */
Packit 8480eb
	sigdelset(&block_sigs, SIGABRT);
Packit 8480eb
	sigdelset(&block_sigs, SIGBUS);
Packit 8480eb
	sigdelset(&block_sigs, SIGSEGV);
Packit 8480eb
	sigdelset(&block_sigs, SIGILL);
Packit 8480eb
	sigdelset(&block_sigs, SIGFPE);
Packit 8480eb
	sigdelset(&block_sigs, SIGTRAP);
Packit 8480eb
	sigprocmask(SIG_BLOCK, &block_sigs, NULL);
Packit 8480eb
Packit 8480eb
	program = argv[0];
Packit 8480eb
Packit 8480eb
	defaults_read_config(0);
Packit 8480eb
Packit 8480eb
	nfs_mount_uses_string_options = check_nfs_mount_version(&vers, &check);
Packit 8480eb
Packit 8480eb
	kpkt_len = get_kpkt_len();
Packit 8480eb
	master_wait = defaults_get_master_wait();
Packit 8480eb
	timeout = defaults_get_timeout();
Packit Service 42268b
	ghost = defaults_get_browse_mode();
Packit 8480eb
	logging = defaults_get_logging();
Packit 8480eb
	global_selection_options = 0;
Packit 8480eb
	global_options = NULL;
Packit Service 42268b
	have_global_options = 0;
Packit Service 42268b
	foreground = 0;
Packit Service 42268b
	dumpmaps = 0;
Packit Service 42268b
	daemon_check = 1;
Packit 8480eb
Packit 8480eb
	remove_empty_args(argv, &argc);
Packit 8480eb
Packit 8480eb
	opterr = 0;
Packit 8480eb
	while ((opt = getopt_long(argc, argv, options, long_options, NULL)) != EOF) {
Packit 8480eb
		switch (opt) {
Packit 8480eb
		case 'h':
Packit 8480eb
			usage();
Packit 8480eb
			exit(0);
Packit 8480eb
Packit 8480eb
		case 'p':
Packit 8480eb
			pid_file = optarg;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 't':
Packit 8480eb
			timeout = getnumopt(optarg, opt);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'v':
Packit 8480eb
			logging |= LOGOPT_VERBOSE;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'd':
Packit 8480eb
			logging |= LOGOPT_DEBUG;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'D':
Packit 8480eb
			macro_parse_globalvar(optarg);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'f':
Packit Service 42268b
			foreground = 1;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'V':
Packit 8480eb
			show_build_info();
Packit 8480eb
			exit(0);
Packit 8480eb
Packit 8480eb
		case 'r':
Packit 8480eb
			global_selection_options |= MOUNT_FLAG_RANDOM_SELECT;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'n':
Packit 8480eb
			global_negative_timeout = getnumopt(optarg, opt);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'm':
Packit Service 42268b
			dumpmaps = 1;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'M':
Packit 8480eb
			master_wait = getnumopt(optarg, opt);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'O':
Packit Service 42268b
			if (!have_global_options) {
Packit 8480eb
				global_options = strdup(optarg);
Packit Service 42268b
				have_global_options = 1;
Packit 8480eb
				break;
Packit 8480eb
			}
Packit 8480eb
			printf("%s: global options already specified.\n",
Packit 8480eb
				program);
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'l':
Packit 8480eb
			if (isalpha(*optarg)) {
Packit 8480eb
				logpri = convert_log_priority(optarg);
Packit 8480eb
				if (logpri < 0) {
Packit 8480eb
					fprintf(stderr, "Invalid log priority:"
Packit 8480eb
						" %s\n", optarg);
Packit 8480eb
					exit(1);
Packit 8480eb
				}
Packit 8480eb
			} else if (isdigit(*optarg)) {
Packit 8480eb
				logpri = getnumopt(optarg, opt);
Packit 8480eb
			} else {
Packit 8480eb
				fprintf(stderr, "non-alphanumeric character "
Packit 8480eb
					"found in log priority.  Aborting.\n");
Packit 8480eb
				exit(1);
Packit 8480eb
			}
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'C':
Packit Service 42268b
			daemon_check = 0;
Packit 8480eb
			break;
Packit 8480eb
Packit 8480eb
		case 'F':
Packit Service 42268b
			do_force_unlink = 1;
Packit Service 076792
			break;
Packit Service 076792
Packit 8480eb
		case '?':
Packit 8480eb
		case ':':
Packit 8480eb
			printf("%s: Ambiguous or unknown options\n", program);
Packit 8480eb
			exit(1);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (logging & LOGOPT_VERBOSE)
Packit 8480eb
		set_log_verbose();
Packit 8480eb
Packit 8480eb
	if (logging & LOGOPT_DEBUG)
Packit 8480eb
		set_log_debug();
Packit 8480eb
Packit 8480eb
	if (geteuid() != 0) {
Packit 8480eb
		fprintf(stderr, "%s: this program must be run by root.\n",
Packit 8480eb
			program);
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	/* Remove the options */
Packit 8480eb
	argv += optind;
Packit 8480eb
	argc -= optind;
Packit 8480eb
Packit 8480eb
	if (logpri >= 0) {
Packit 8480eb
		int exit_code = 0;
Packit 8480eb
		int i;
Packit 8480eb
Packit 8480eb
		/*
Packit 8480eb
		 * The remaining argv elements are the paths for which
Packit 8480eb
		 * log priorities must be changed.
Packit 8480eb
		 */
Packit 8480eb
		for (i = 0; i < argc; i++) {
Packit 8480eb
			if (set_log_priority(argv[i], logpri) < 0)
Packit 8480eb
				exit_code = 1;
Packit 8480eb
		}
Packit 8480eb
		if (argc < 1) {
Packit 8480eb
			fprintf(stderr,
Packit 8480eb
				"--set-log-priority requires a path.\n");
Packit 8480eb
			exit_code = 1;
Packit 8480eb
		}
Packit 8480eb
		exit(exit_code);
Packit 8480eb
	}
Packit 8480eb
Packit Service 42268b
#if 0
Packit Service 42268b
	if (!load_autofs4_module()) {
Packit Service 42268b
		fprintf(stderr, "%s: can't load %s filesystem module.\n",
Packit Service 42268b
			program, FS_MODULE_NAME);
Packit Service 42268b
		exit(1);
Packit Service 42268b
	}
Packit Service 42268b
#endif
Packit Service 42268b
Packit 8480eb
	/* Don't need the kernel module just to look at the configured maps */
Packit Service 42268b
	if (!dumpmaps && (!query_kproto_ver() || get_kver_major() < 5)) {
Packit 8480eb
		fprintf(stderr,
Packit 8480eb
			"%s: test mount forbidden or "
Packit 8480eb
			"incorrect kernel protocol version, "
Packit 8480eb
			"kernel protocol version 5.00 or above required.\n",
Packit 8480eb
			program);
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	res = getrlimit(RLIMIT_NOFILE, &rlim);
Packit 8480eb
	if (res == -1 || rlim.rlim_max <= MAX_OPEN_FILES)  {
Packit 8480eb
		rlim.rlim_cur = MAX_OPEN_FILES;
Packit 8480eb
		rlim.rlim_max = MAX_OPEN_FILES;
Packit 8480eb
	}
Packit 8480eb
	res = setrlimit(RLIMIT_NOFILE, &rlim);
Packit 8480eb
	if (res)
Packit 8480eb
		printf("%s: can't increase open file limit - continuing",
Packit 8480eb
			program);
Packit 8480eb
Packit 8480eb
#if ENABLE_CORES
Packit 8480eb
	rlim.rlim_cur = RLIM_INFINITY;
Packit 8480eb
	rlim.rlim_max = RLIM_INFINITY;
Packit 8480eb
	res = setrlimit(RLIMIT_CORE, &rlim);
Packit 8480eb
	if (res)
Packit 8480eb
		printf("%s: can't increase core file limit - continuing",
Packit 8480eb
			program);
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
	/* Get processor information for predefined escapes */
Packit 8480eb
	macro_init();
Packit 8480eb
Packit Service 42268b
	if (dumpmaps) {
Packit 8480eb
		struct master_mapent *entry;
Packit 8480eb
		struct list_head *head, *p;
Packit 8480eb
		struct mapent_cache *nc;
Packit 8480eb
		const char *type = NULL;
Packit 8480eb
		const char *name = NULL;
Packit 8480eb
		const char *master = NULL;
Packit 8480eb
Packit 8480eb
		if (argc > 0) {
Packit 8480eb
			if (argc >= 2) {
Packit 8480eb
				type = argv[0];
Packit 8480eb
				name = argv[1];
Packit 8480eb
			}
Packit 8480eb
			if (argc == 3)
Packit 8480eb
				master = argv[2];
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (master)
Packit Service 42268b
			master_list = master_new(NULL, timeout, ghost);
Packit 8480eb
		else
Packit Service 42268b
			master_list = master_new(master, timeout, ghost);
Packit 8480eb
		if (!master_list) {
Packit 8480eb
			printf("%s: can't create master map", program);
Packit 8480eb
			macro_free_global_table();
Packit 8480eb
			exit(1);
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		log_to_stderr();
Packit 8480eb
Packit 8480eb
		master_init_scan();
Packit 8480eb
Packit 8480eb
		nc = cache_init_null_cache(master_list);
Packit 8480eb
		if (!nc) {
Packit 8480eb
			printf("%s: failed to init null map cache for %s",
Packit 8480eb
				program, master_list->name);
Packit 8480eb
			macro_free_global_table();
Packit 8480eb
			exit(1);
Packit 8480eb
		}
Packit 8480eb
		master_list->nc = nc;
Packit 8480eb
Packit 8480eb
		lookup_nss_read_master(master_list, 0);
Packit 8480eb
		if (type) {
Packit 8480eb
			const char *map = basename(name);
Packit 8480eb
			if (!map)
Packit 8480eb
				printf("%s: invalid map name %s\n",
Packit 8480eb
					program, name);
Packit 8480eb
			else
Packit 8480eb
				dump_map(master_list, type, map);
Packit 8480eb
		} else
Packit 8480eb
			master_show_mounts(master_list);
Packit 8480eb
Packit 8480eb
		head = &master_list->mounts;
Packit 8480eb
		p = head->next;
Packit 8480eb
		while (p != head) {
Packit 8480eb
			entry = list_entry(p, struct master_mapent, list);
Packit 8480eb
			p = p->next;
Packit 8480eb
			master_free_mapent_sources(entry, 1);
Packit 8480eb
			master_free_mapent(entry);
Packit 8480eb
		}
Packit 8480eb
		master_kill(master_list);
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
Packit 8480eb
		exit(0);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (argc == 0)
Packit Service 42268b
		master_list = master_new(NULL, timeout, ghost);
Packit 8480eb
	else
Packit Service 42268b
		master_list = master_new(argv[0], timeout, ghost);
Packit 8480eb
Packit 8480eb
	if (!master_list) {
Packit 8480eb
		printf("%s: can't create master map %s", program, argv[0]);
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit Service 42268b
	become_daemon(foreground, daemon_check);
Packit 8480eb
Packit 8480eb
	if (pthread_attr_init(&th_attr)) {
Packit 8480eb
		logerr("%s: failed to init thread attribute struct!",
Packit 8480eb
		     program);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (pthread_attr_init(&th_attr_detached)) {
Packit 8480eb
		logerr("%s: failed to init thread attribute struct!",
Packit 8480eb
		     program);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (pthread_attr_setdetachstate(
Packit 8480eb
			&th_attr_detached, PTHREAD_CREATE_DETACHED)) {
Packit 8480eb
		logerr("%s: failed to set detached thread attribute!",
Packit 8480eb
		     program);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
#ifdef _POSIX_THREAD_ATTR_STACKSIZE
Packit 8480eb
	if (pthread_attr_setstacksize(
Packit 8480eb
			&th_attr_detached, detached_thread_stack_size)) {
Packit 8480eb
		logerr("%s: failed to set stack size thread attribute!",
Packit 8480eb
		       program);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
	if (pthread_attr_getstacksize(
Packit 8480eb
			&th_attr_detached, &detached_thread_stack_size)) {
Packit 8480eb
		logerr("%s: failed to get detached thread stack size!",
Packit 8480eb
		       program);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	info(logging, "Starting automounter version %s, master map %s",
Packit 8480eb
		version, master_list->name);
Packit 8480eb
	info(logging, "using kernel protocol version %d.%02d",
Packit 8480eb
		get_kver_major(), get_kver_minor());
Packit 8480eb
Packit 8480eb
	status = pthread_key_create(&key_thread_stdenv_vars,
Packit 8480eb
				key_thread_stdenv_vars_destroy);
Packit 8480eb
	if (status) {
Packit 8480eb
		logerr("%s: failed to create thread data key for std env vars!",
Packit 8480eb
		       program);
Packit 8480eb
		master_kill(master_list);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	status = pthread_key_create(&key_thread_attempt_id, free);
Packit 8480eb
	if (status) {
Packit 8480eb
		logerr("%s: failed to create thread data key for attempt ID!",
Packit 8480eb
		       program);
Packit 8480eb
		master_kill(master_list);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	init_ioctl_ctl();
Packit 8480eb
Packit 8480eb
	if (!alarm_start_handler()) {
Packit 8480eb
		logerr("%s: failed to create alarm handler thread!", program);
Packit 8480eb
		master_kill(master_list);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!st_start_handler()) {
Packit 8480eb
		logerr("%s: failed to create FSM handler thread!", program);
Packit 8480eb
		master_kill(master_list);
Packit Service b3e495
		if (start_pipefd[1] != -1) {
Packit Service b3e495
			res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
			close(start_pipefd[1]);
Packit Service b3e495
		}
Packit 8480eb
		release_flag_file();
Packit 8480eb
		macro_free_global_table();
Packit 8480eb
		exit(1);
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
#if defined(WITH_LDAP) && defined(LIBXML2_WORKAROUND)
Packit 8480eb
	void *dh_xml2 = dlopen("libxml2.so", RTLD_NOW);
Packit 8480eb
	if (!dh_xml2)
Packit 8480eb
		dh_xml2 = dlopen("libxml2.so.2", RTLD_NOW);
Packit 8480eb
	if (dh_xml2)
Packit 8480eb
		xmlInitParser();
Packit 8480eb
#endif
Packit 8480eb
#ifdef TIRPC_WORKAROUND
Packit 8480eb
	void *dh_tirpc = dlopen("libtirpc.so", RTLD_NOW);
Packit 8480eb
	if (!dh_tirpc)
Packit 8480eb
		dh_tirpc = dlopen("libtirpc.so.1", RTLD_NOW);
Packit 8480eb
	if (!dh_tirpc)
Packit 8480eb
		dh_tirpc = dlopen("libtirpc.so.3", RTLD_NOW);
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
	master_read = master_read_master(master_list, age, 0);
Packit 8480eb
	if (!master_read) {
Packit 8480eb
		/*
Packit 8480eb
		 * Read master map, waiting until it is available, unless
Packit 8480eb
		 * a signal is received, in which case exit returning an
Packit 8480eb
		 * error.
Packit 8480eb
		 */
Packit 8480eb
		if (!do_master_read_master(master_list, master_wait)) {
Packit 8480eb
			logmsg("%s: warning: could not read at least one "
Packit 8480eb
				"map source after waiting, continuing ...",
Packit 8480eb
				 program);
Packit 8480eb
			/*
Packit 8480eb
			 * Failed to read master map, continue with what
Packit 8480eb
			 * we have anyway.
Packit 8480eb
			 */
Packit 8480eb
			do_master_list_reset(master_list);
Packit Service 42268b
			age = time(NULL);
Packit 8480eb
			master_read_master(master_list, age, 1);
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
Packit Service 42268b
	/*
Packit Service 42268b
	 * Mmm ... reset force unlink umount so we don't also do this
Packit Service 42268b
	 * in future when we receive a HUP signal.
Packit Service 25eead
	 */
Packit Service 42268b
	do_force_unlink = 0;
Packit 8480eb
Packit Service b3e495
	if (start_pipefd[1] != -1) {
Packit Service b3e495
		st_stat = 0;
Packit Service b3e495
		res = write(start_pipefd[1], pst_stat, sizeof(*pst_stat));
Packit Service b3e495
		close(start_pipefd[1]);
Packit Service b3e495
	}
Packit Service b3e495
Packit Service b3e495
#ifdef WITH_SYSTEMD
Packit Service b3e495
	sd_notify(1, "READY=1");
Packit Service b3e495
#endif
Packit Service 85fdcd
Packit Service 42268b
	state_mach_thid = pthread_self();
Packit Service 42268b
	statemachine(NULL);
Packit 8480eb
Packit 8480eb
	master_kill(master_list);
Packit 8480eb
Packit 8480eb
	if (pid_file) {
Packit 8480eb
		unlink(pid_file);
Packit 8480eb
		pid_file = NULL;
Packit 8480eb
	}
Packit 8480eb
	defaults_conf_release();
Packit 8480eb
	closelog();
Packit 8480eb
	release_flag_file();
Packit 8480eb
	macro_free_global_table();
Packit 8480eb
Packit 8480eb
#ifdef TIRPC_WORKAROUND
Packit 8480eb
	if (dh_tirpc)
Packit 8480eb
		dlclose(dh_tirpc);
Packit 8480eb
#endif
Packit 8480eb
#if defined(WITH_LDAP) && defined( LIBXML2_WORKAROUND)
Packit 8480eb
	if (dh_xml2) {
Packit 8480eb
		xmlCleanupParser();
Packit 8480eb
		dlclose(dh_xml2);
Packit 8480eb
	}
Packit 8480eb
#endif
Packit 8480eb
	close_ioctl_ctl();
Packit 8480eb
Packit 8480eb
	info(logging, "autofs stopped");
Packit 8480eb
Packit 8480eb
	exit(0);
Packit 8480eb
}