13914ddf8SEdward Tomasz Napierala /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
3abdd3945SEdward Tomasz Napierala *
43914ddf8SEdward Tomasz Napierala * Copyright (c) 2014 The FreeBSD Foundation
53914ddf8SEdward Tomasz Napierala *
63914ddf8SEdward Tomasz Napierala * This software was developed by Edward Tomasz Napierala under sponsorship
73914ddf8SEdward Tomasz Napierala * from the FreeBSD Foundation.
83914ddf8SEdward Tomasz Napierala *
93914ddf8SEdward Tomasz Napierala * Redistribution and use in source and binary forms, with or without
103914ddf8SEdward Tomasz Napierala * modification, are permitted provided that the following conditions
113914ddf8SEdward Tomasz Napierala * are met:
123914ddf8SEdward Tomasz Napierala * 1. Redistributions of source code must retain the above copyright
133914ddf8SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer.
143914ddf8SEdward Tomasz Napierala * 2. Redistributions in binary form must reproduce the above copyright
153914ddf8SEdward Tomasz Napierala * notice, this list of conditions and the following disclaimer in the
163914ddf8SEdward Tomasz Napierala * documentation and/or other materials provided with the distribution.
173914ddf8SEdward Tomasz Napierala *
183914ddf8SEdward Tomasz Napierala * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
193914ddf8SEdward Tomasz Napierala * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203914ddf8SEdward Tomasz Napierala * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213914ddf8SEdward Tomasz Napierala * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
223914ddf8SEdward Tomasz Napierala * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
233914ddf8SEdward Tomasz Napierala * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243914ddf8SEdward Tomasz Napierala * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253914ddf8SEdward Tomasz Napierala * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263914ddf8SEdward Tomasz Napierala * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273914ddf8SEdward Tomasz Napierala * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
283914ddf8SEdward Tomasz Napierala * SUCH DAMAGE.
293914ddf8SEdward Tomasz Napierala *
303914ddf8SEdward Tomasz Napierala */
313914ddf8SEdward Tomasz Napierala
323914ddf8SEdward Tomasz Napierala #include <sys/types.h>
333914ddf8SEdward Tomasz Napierala #include <sys/time.h>
343914ddf8SEdward Tomasz Napierala #include <sys/ioctl.h>
353914ddf8SEdward Tomasz Napierala #include <sys/param.h>
363914ddf8SEdward Tomasz Napierala #include <sys/linker.h>
373914ddf8SEdward Tomasz Napierala #include <sys/mount.h>
383914ddf8SEdward Tomasz Napierala #include <sys/socket.h>
393914ddf8SEdward Tomasz Napierala #include <sys/stat.h>
403914ddf8SEdward Tomasz Napierala #include <sys/wait.h>
413914ddf8SEdward Tomasz Napierala #include <sys/utsname.h>
423914ddf8SEdward Tomasz Napierala #include <assert.h>
433914ddf8SEdward Tomasz Napierala #include <ctype.h>
443914ddf8SEdward Tomasz Napierala #include <err.h>
453914ddf8SEdward Tomasz Napierala #include <errno.h>
463914ddf8SEdward Tomasz Napierala #include <fcntl.h>
473914ddf8SEdward Tomasz Napierala #include <libgen.h>
48592d6e85SEdward Tomasz Napierala #include <libutil.h>
493914ddf8SEdward Tomasz Napierala #include <netdb.h>
503914ddf8SEdward Tomasz Napierala #include <paths.h>
513914ddf8SEdward Tomasz Napierala #include <signal.h>
523914ddf8SEdward Tomasz Napierala #include <stdbool.h>
533914ddf8SEdward Tomasz Napierala #include <stdint.h>
543914ddf8SEdward Tomasz Napierala #include <stdio.h>
553914ddf8SEdward Tomasz Napierala #include <stdlib.h>
563914ddf8SEdward Tomasz Napierala #include <string.h>
573914ddf8SEdward Tomasz Napierala #include <unistd.h>
583914ddf8SEdward Tomasz Napierala
593914ddf8SEdward Tomasz Napierala #include "autofs_ioctl.h"
603914ddf8SEdward Tomasz Napierala
613914ddf8SEdward Tomasz Napierala #include "common.h"
623914ddf8SEdward Tomasz Napierala
633914ddf8SEdward Tomasz Napierala extern FILE *yyin;
643914ddf8SEdward Tomasz Napierala extern char *yytext;
653914ddf8SEdward Tomasz Napierala extern int yylex(void);
663914ddf8SEdward Tomasz Napierala
673914ddf8SEdward Tomasz Napierala static void parse_master_yyin(struct node *root, const char *master);
683914ddf8SEdward Tomasz Napierala static void parse_map_yyin(struct node *parent, const char *map,
693914ddf8SEdward Tomasz Napierala const char *executable_key);
703914ddf8SEdward Tomasz Napierala
713914ddf8SEdward Tomasz Napierala char *
checked_strdup(const char * s)723914ddf8SEdward Tomasz Napierala checked_strdup(const char *s)
733914ddf8SEdward Tomasz Napierala {
743914ddf8SEdward Tomasz Napierala char *c;
753914ddf8SEdward Tomasz Napierala
763914ddf8SEdward Tomasz Napierala assert(s != NULL);
773914ddf8SEdward Tomasz Napierala
783914ddf8SEdward Tomasz Napierala c = strdup(s);
793914ddf8SEdward Tomasz Napierala if (c == NULL)
803914ddf8SEdward Tomasz Napierala log_err(1, "strdup");
813914ddf8SEdward Tomasz Napierala return (c);
823914ddf8SEdward Tomasz Napierala }
833914ddf8SEdward Tomasz Napierala
843914ddf8SEdward Tomasz Napierala /*
853914ddf8SEdward Tomasz Napierala * Concatenate two strings, inserting separator between them, unless not needed.
863914ddf8SEdward Tomasz Napierala */
873914ddf8SEdward Tomasz Napierala char *
concat(const char * s1,char separator,const char * s2)886d8e60c3SEdward Tomasz Napierala concat(const char *s1, char separator, const char *s2)
893914ddf8SEdward Tomasz Napierala {
903914ddf8SEdward Tomasz Napierala char *result;
91cd3772d0SEdward Tomasz Napierala char s1last, s2first;
923914ddf8SEdward Tomasz Napierala int ret;
933914ddf8SEdward Tomasz Napierala
944d58da13SEdward Tomasz Napierala if (s1 == NULL)
954d58da13SEdward Tomasz Napierala s1 = "";
964d58da13SEdward Tomasz Napierala if (s2 == NULL)
974d58da13SEdward Tomasz Napierala s2 = "";
983914ddf8SEdward Tomasz Napierala
99cd3772d0SEdward Tomasz Napierala if (s1[0] == '\0')
100cd3772d0SEdward Tomasz Napierala s1last = '\0';
101cd3772d0SEdward Tomasz Napierala else
102cd3772d0SEdward Tomasz Napierala s1last = s1[strlen(s1) - 1];
1035585582dSEdward Tomasz Napierala
104cd3772d0SEdward Tomasz Napierala s2first = s2[0];
105cd3772d0SEdward Tomasz Napierala
106cd3772d0SEdward Tomasz Napierala if (s1last == separator && s2first == separator) {
107cd3772d0SEdward Tomasz Napierala /*
108cd3772d0SEdward Tomasz Napierala * If s1 ends with the separator and s2 begins with
109cd3772d0SEdward Tomasz Napierala * it - skip the latter; otherwise concatenating "/"
110cd3772d0SEdward Tomasz Napierala * and "/foo" would end up returning "//foo".
111cd3772d0SEdward Tomasz Napierala */
112cd3772d0SEdward Tomasz Napierala ret = asprintf(&result, "%s%s", s1, s2 + 1);
113cd3772d0SEdward Tomasz Napierala } else if (s1last == separator || s2first == separator ||
114cd3772d0SEdward Tomasz Napierala s1[0] == '\0' || s2[0] == '\0') {
1153914ddf8SEdward Tomasz Napierala ret = asprintf(&result, "%s%s", s1, s2);
1163914ddf8SEdward Tomasz Napierala } else {
1173914ddf8SEdward Tomasz Napierala ret = asprintf(&result, "%s%c%s", s1, separator, s2);
1183914ddf8SEdward Tomasz Napierala }
1193914ddf8SEdward Tomasz Napierala if (ret < 0)
1203914ddf8SEdward Tomasz Napierala log_err(1, "asprintf");
1213914ddf8SEdward Tomasz Napierala
122ef4b8dfaSEdward Tomasz Napierala //log_debugx("%s: got %s and %s, returning %s", __func__, s1, s2, result);
1233914ddf8SEdward Tomasz Napierala
1243914ddf8SEdward Tomasz Napierala return (result);
1253914ddf8SEdward Tomasz Napierala }
1263914ddf8SEdward Tomasz Napierala
1273914ddf8SEdward Tomasz Napierala void
create_directory(const char * path)1283914ddf8SEdward Tomasz Napierala create_directory(const char *path)
1293914ddf8SEdward Tomasz Napierala {
130ef4b8dfaSEdward Tomasz Napierala char *component, *copy, *tofree, *partial, *tmp;
1313914ddf8SEdward Tomasz Napierala int error;
1323914ddf8SEdward Tomasz Napierala
1333914ddf8SEdward Tomasz Napierala assert(path[0] == '/');
1343914ddf8SEdward Tomasz Napierala
1353914ddf8SEdward Tomasz Napierala /*
1363914ddf8SEdward Tomasz Napierala * +1 to skip the leading slash.
1373914ddf8SEdward Tomasz Napierala */
1383914ddf8SEdward Tomasz Napierala copy = tofree = checked_strdup(path + 1);
1393914ddf8SEdward Tomasz Napierala
14063640b2fSRobert Wing partial = checked_strdup("/");
1413914ddf8SEdward Tomasz Napierala for (;;) {
1423914ddf8SEdward Tomasz Napierala component = strsep(©, "/");
1433914ddf8SEdward Tomasz Napierala if (component == NULL)
1443914ddf8SEdward Tomasz Napierala break;
1456d8e60c3SEdward Tomasz Napierala tmp = concat(partial, '/', component);
146ef4b8dfaSEdward Tomasz Napierala free(partial);
147ef4b8dfaSEdward Tomasz Napierala partial = tmp;
1487ebeea9aSEdward Tomasz Napierala //log_debugx("creating \"%s\"", partial);
1493914ddf8SEdward Tomasz Napierala error = mkdir(partial, 0755);
1507ebeea9aSEdward Tomasz Napierala if (error != 0 && errno != EEXIST) {
1517ebeea9aSEdward Tomasz Napierala log_warn("cannot create %s", partial);
1527ebeea9aSEdward Tomasz Napierala return;
1537ebeea9aSEdward Tomasz Napierala }
1543914ddf8SEdward Tomasz Napierala }
1553914ddf8SEdward Tomasz Napierala
1563914ddf8SEdward Tomasz Napierala free(tofree);
1573914ddf8SEdward Tomasz Napierala }
1583914ddf8SEdward Tomasz Napierala
1593914ddf8SEdward Tomasz Napierala struct node *
node_new_root(void)1603914ddf8SEdward Tomasz Napierala node_new_root(void)
1613914ddf8SEdward Tomasz Napierala {
1623914ddf8SEdward Tomasz Napierala struct node *n;
1633914ddf8SEdward Tomasz Napierala
1643914ddf8SEdward Tomasz Napierala n = calloc(1, sizeof(*n));
1653914ddf8SEdward Tomasz Napierala if (n == NULL)
1663914ddf8SEdward Tomasz Napierala log_err(1, "calloc");
1673914ddf8SEdward Tomasz Napierala // XXX
1683914ddf8SEdward Tomasz Napierala n->n_key = checked_strdup("/");
1693914ddf8SEdward Tomasz Napierala n->n_options = checked_strdup("");
1703914ddf8SEdward Tomasz Napierala
1713914ddf8SEdward Tomasz Napierala TAILQ_INIT(&n->n_children);
1723914ddf8SEdward Tomasz Napierala
1733914ddf8SEdward Tomasz Napierala return (n);
1743914ddf8SEdward Tomasz Napierala }
1753914ddf8SEdward Tomasz Napierala
1763914ddf8SEdward Tomasz Napierala struct node *
node_new(struct node * parent,char * key,char * options,char * location,const char * config_file,int config_line)1773914ddf8SEdward Tomasz Napierala node_new(struct node *parent, char *key, char *options, char *location,
1783914ddf8SEdward Tomasz Napierala const char *config_file, int config_line)
1793914ddf8SEdward Tomasz Napierala {
1803914ddf8SEdward Tomasz Napierala struct node *n;
1813914ddf8SEdward Tomasz Napierala
1823914ddf8SEdward Tomasz Napierala n = calloc(1, sizeof(*n));
1833914ddf8SEdward Tomasz Napierala if (n == NULL)
1843914ddf8SEdward Tomasz Napierala log_err(1, "calloc");
1853914ddf8SEdward Tomasz Napierala
1863914ddf8SEdward Tomasz Napierala TAILQ_INIT(&n->n_children);
1873914ddf8SEdward Tomasz Napierala assert(key != NULL);
1883dd80c05SEdward Tomasz Napierala assert(key[0] != '\0');
1893914ddf8SEdward Tomasz Napierala n->n_key = key;
1903914ddf8SEdward Tomasz Napierala if (options != NULL)
1913914ddf8SEdward Tomasz Napierala n->n_options = options;
1923914ddf8SEdward Tomasz Napierala else
1933914ddf8SEdward Tomasz Napierala n->n_options = strdup("");
1943914ddf8SEdward Tomasz Napierala n->n_location = location;
1953914ddf8SEdward Tomasz Napierala assert(config_file != NULL);
1963914ddf8SEdward Tomasz Napierala n->n_config_file = config_file;
1973914ddf8SEdward Tomasz Napierala assert(config_line >= 0);
1983914ddf8SEdward Tomasz Napierala n->n_config_line = config_line;
1993914ddf8SEdward Tomasz Napierala
2003914ddf8SEdward Tomasz Napierala assert(parent != NULL);
2013914ddf8SEdward Tomasz Napierala n->n_parent = parent;
2023914ddf8SEdward Tomasz Napierala TAILQ_INSERT_TAIL(&parent->n_children, n, n_next);
2033914ddf8SEdward Tomasz Napierala
2043914ddf8SEdward Tomasz Napierala return (n);
2053914ddf8SEdward Tomasz Napierala }
2063914ddf8SEdward Tomasz Napierala
2073914ddf8SEdward Tomasz Napierala struct node *
node_new_map(struct node * parent,char * key,char * options,char * map,const char * config_file,int config_line)2083914ddf8SEdward Tomasz Napierala node_new_map(struct node *parent, char *key, char *options, char *map,
2093914ddf8SEdward Tomasz Napierala const char *config_file, int config_line)
2103914ddf8SEdward Tomasz Napierala {
2113914ddf8SEdward Tomasz Napierala struct node *n;
2123914ddf8SEdward Tomasz Napierala
2133914ddf8SEdward Tomasz Napierala n = calloc(1, sizeof(*n));
2143914ddf8SEdward Tomasz Napierala if (n == NULL)
2153914ddf8SEdward Tomasz Napierala log_err(1, "calloc");
2163914ddf8SEdward Tomasz Napierala
2173914ddf8SEdward Tomasz Napierala TAILQ_INIT(&n->n_children);
2183914ddf8SEdward Tomasz Napierala assert(key != NULL);
2193dd80c05SEdward Tomasz Napierala assert(key[0] != '\0');
2203914ddf8SEdward Tomasz Napierala n->n_key = key;
2213914ddf8SEdward Tomasz Napierala if (options != NULL)
2223914ddf8SEdward Tomasz Napierala n->n_options = options;
2233914ddf8SEdward Tomasz Napierala else
2243914ddf8SEdward Tomasz Napierala n->n_options = strdup("");
2253914ddf8SEdward Tomasz Napierala n->n_map = map;
2263914ddf8SEdward Tomasz Napierala assert(config_file != NULL);
2273914ddf8SEdward Tomasz Napierala n->n_config_file = config_file;
2283914ddf8SEdward Tomasz Napierala assert(config_line >= 0);
2293914ddf8SEdward Tomasz Napierala n->n_config_line = config_line;
2303914ddf8SEdward Tomasz Napierala
2313914ddf8SEdward Tomasz Napierala assert(parent != NULL);
2323914ddf8SEdward Tomasz Napierala n->n_parent = parent;
2333914ddf8SEdward Tomasz Napierala TAILQ_INSERT_TAIL(&parent->n_children, n, n_next);
2343914ddf8SEdward Tomasz Napierala
2353914ddf8SEdward Tomasz Napierala return (n);
2363914ddf8SEdward Tomasz Napierala }
2373914ddf8SEdward Tomasz Napierala
2383914ddf8SEdward Tomasz Napierala static struct node *
node_duplicate(const struct node * o,struct node * parent)2393914ddf8SEdward Tomasz Napierala node_duplicate(const struct node *o, struct node *parent)
2403914ddf8SEdward Tomasz Napierala {
2413914ddf8SEdward Tomasz Napierala const struct node *child;
2423914ddf8SEdward Tomasz Napierala struct node *n;
2433914ddf8SEdward Tomasz Napierala
2443914ddf8SEdward Tomasz Napierala if (parent == NULL)
2453914ddf8SEdward Tomasz Napierala parent = o->n_parent;
2463914ddf8SEdward Tomasz Napierala
2473914ddf8SEdward Tomasz Napierala n = node_new(parent, o->n_key, o->n_options, o->n_location,
2483914ddf8SEdward Tomasz Napierala o->n_config_file, o->n_config_line);
2493914ddf8SEdward Tomasz Napierala
2503914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &o->n_children, n_next)
2513914ddf8SEdward Tomasz Napierala node_duplicate(child, n);
2523914ddf8SEdward Tomasz Napierala
2533914ddf8SEdward Tomasz Napierala return (n);
2543914ddf8SEdward Tomasz Napierala }
2553914ddf8SEdward Tomasz Napierala
2563914ddf8SEdward Tomasz Napierala static void
node_delete(struct node * n)2573914ddf8SEdward Tomasz Napierala node_delete(struct node *n)
2583914ddf8SEdward Tomasz Napierala {
2593914ddf8SEdward Tomasz Napierala struct node *child, *tmp;
2603914ddf8SEdward Tomasz Napierala
2613914ddf8SEdward Tomasz Napierala assert (n != NULL);
2623914ddf8SEdward Tomasz Napierala
2633914ddf8SEdward Tomasz Napierala TAILQ_FOREACH_SAFE(child, &n->n_children, n_next, tmp)
2643914ddf8SEdward Tomasz Napierala node_delete(child);
2653914ddf8SEdward Tomasz Napierala
2663914ddf8SEdward Tomasz Napierala if (n->n_parent != NULL)
2673914ddf8SEdward Tomasz Napierala TAILQ_REMOVE(&n->n_parent->n_children, n, n_next);
2683914ddf8SEdward Tomasz Napierala
2693914ddf8SEdward Tomasz Napierala free(n);
2703914ddf8SEdward Tomasz Napierala }
2713914ddf8SEdward Tomasz Napierala
2723914ddf8SEdward Tomasz Napierala /*
2733914ddf8SEdward Tomasz Napierala * Move (reparent) node 'n' to make it sibling of 'previous', placed
2743914ddf8SEdward Tomasz Napierala * just after it.
2753914ddf8SEdward Tomasz Napierala */
2763914ddf8SEdward Tomasz Napierala static void
node_move_after(struct node * n,struct node * previous)2773914ddf8SEdward Tomasz Napierala node_move_after(struct node *n, struct node *previous)
2783914ddf8SEdward Tomasz Napierala {
2793914ddf8SEdward Tomasz Napierala
2803914ddf8SEdward Tomasz Napierala TAILQ_REMOVE(&n->n_parent->n_children, n, n_next);
2813914ddf8SEdward Tomasz Napierala n->n_parent = previous->n_parent;
2823914ddf8SEdward Tomasz Napierala TAILQ_INSERT_AFTER(&previous->n_parent->n_children, previous, n, n_next);
2833914ddf8SEdward Tomasz Napierala }
2843914ddf8SEdward Tomasz Napierala
2853914ddf8SEdward Tomasz Napierala static void
node_expand_includes(struct node * root,bool is_master)2863914ddf8SEdward Tomasz Napierala node_expand_includes(struct node *root, bool is_master)
2873914ddf8SEdward Tomasz Napierala {
2883914ddf8SEdward Tomasz Napierala struct node *n, *n2, *tmp, *tmp2, *tmproot;
2893914ddf8SEdward Tomasz Napierala int error;
2903914ddf8SEdward Tomasz Napierala
2913914ddf8SEdward Tomasz Napierala TAILQ_FOREACH_SAFE(n, &root->n_children, n_next, tmp) {
2923914ddf8SEdward Tomasz Napierala if (n->n_key[0] != '+')
2933914ddf8SEdward Tomasz Napierala continue;
2943914ddf8SEdward Tomasz Napierala
2953914ddf8SEdward Tomasz Napierala error = access(AUTO_INCLUDE_PATH, F_OK);
2963914ddf8SEdward Tomasz Napierala if (error != 0) {
2973914ddf8SEdward Tomasz Napierala log_errx(1, "directory services not configured; "
2983914ddf8SEdward Tomasz Napierala "%s does not exist", AUTO_INCLUDE_PATH);
2993914ddf8SEdward Tomasz Napierala }
3003914ddf8SEdward Tomasz Napierala
3013914ddf8SEdward Tomasz Napierala /*
3023914ddf8SEdward Tomasz Napierala * "+1" to skip leading "+".
3033914ddf8SEdward Tomasz Napierala */
3043914ddf8SEdward Tomasz Napierala yyin = auto_popen(AUTO_INCLUDE_PATH, n->n_key + 1, NULL);
3053914ddf8SEdward Tomasz Napierala assert(yyin != NULL);
3063914ddf8SEdward Tomasz Napierala
3073914ddf8SEdward Tomasz Napierala tmproot = node_new_root();
3083914ddf8SEdward Tomasz Napierala if (is_master)
3093914ddf8SEdward Tomasz Napierala parse_master_yyin(tmproot, n->n_key);
3103914ddf8SEdward Tomasz Napierala else
3113914ddf8SEdward Tomasz Napierala parse_map_yyin(tmproot, n->n_key, NULL);
3123914ddf8SEdward Tomasz Napierala
3133914ddf8SEdward Tomasz Napierala error = auto_pclose(yyin);
3143914ddf8SEdward Tomasz Napierala yyin = NULL;
3153914ddf8SEdward Tomasz Napierala if (error != 0) {
3163914ddf8SEdward Tomasz Napierala log_errx(1, "failed to handle include \"%s\"",
3173914ddf8SEdward Tomasz Napierala n->n_key);
3183914ddf8SEdward Tomasz Napierala }
3193914ddf8SEdward Tomasz Napierala
3203914ddf8SEdward Tomasz Napierala /*
3213914ddf8SEdward Tomasz Napierala * Entries to be included are now in tmproot. We need to merge
3223914ddf8SEdward Tomasz Napierala * them with the rest, preserving their place and ordering.
3233914ddf8SEdward Tomasz Napierala */
3243914ddf8SEdward Tomasz Napierala TAILQ_FOREACH_REVERSE_SAFE(n2,
3253914ddf8SEdward Tomasz Napierala &tmproot->n_children, nodehead, n_next, tmp2) {
3263914ddf8SEdward Tomasz Napierala node_move_after(n2, n);
3273914ddf8SEdward Tomasz Napierala }
3283914ddf8SEdward Tomasz Napierala
3293914ddf8SEdward Tomasz Napierala node_delete(n);
3303914ddf8SEdward Tomasz Napierala node_delete(tmproot);
3313914ddf8SEdward Tomasz Napierala }
3323914ddf8SEdward Tomasz Napierala }
3333914ddf8SEdward Tomasz Napierala
3343914ddf8SEdward Tomasz Napierala static char *
expand_ampersand(char * string,const char * key)3353914ddf8SEdward Tomasz Napierala expand_ampersand(char *string, const char *key)
3363914ddf8SEdward Tomasz Napierala {
3373914ddf8SEdward Tomasz Napierala char c, *expanded;
3383914ddf8SEdward Tomasz Napierala int i, ret, before_len = 0;
3393914ddf8SEdward Tomasz Napierala bool backslashed = false;
3403914ddf8SEdward Tomasz Napierala
3413914ddf8SEdward Tomasz Napierala assert(key[0] != '\0');
3423914ddf8SEdward Tomasz Napierala
3433914ddf8SEdward Tomasz Napierala expanded = checked_strdup(string);
3443914ddf8SEdward Tomasz Napierala
3453914ddf8SEdward Tomasz Napierala for (i = 0; string[i] != '\0'; i++) {
3463914ddf8SEdward Tomasz Napierala c = string[i];
3473914ddf8SEdward Tomasz Napierala if (c == '\\' && backslashed == false) {
3483914ddf8SEdward Tomasz Napierala backslashed = true;
3493914ddf8SEdward Tomasz Napierala continue;
3503914ddf8SEdward Tomasz Napierala }
3513914ddf8SEdward Tomasz Napierala if (backslashed) {
3523914ddf8SEdward Tomasz Napierala backslashed = false;
3533914ddf8SEdward Tomasz Napierala continue;
3543914ddf8SEdward Tomasz Napierala }
3553914ddf8SEdward Tomasz Napierala backslashed = false;
3563914ddf8SEdward Tomasz Napierala if (c != '&')
3573914ddf8SEdward Tomasz Napierala continue;
3583914ddf8SEdward Tomasz Napierala
3593914ddf8SEdward Tomasz Napierala /*
3603914ddf8SEdward Tomasz Napierala * The 'before_len' variable contains the number
3613914ddf8SEdward Tomasz Napierala * of characters before the '&'.
3623914ddf8SEdward Tomasz Napierala */
3633914ddf8SEdward Tomasz Napierala before_len = i;
3641383afcbSEdward Tomasz Napierala //assert(i < (int)strlen(string));
3653914ddf8SEdward Tomasz Napierala
3663914ddf8SEdward Tomasz Napierala ret = asprintf(&expanded, "%.*s%s%s",
3673914ddf8SEdward Tomasz Napierala before_len, string, key, string + before_len + 1);
3683914ddf8SEdward Tomasz Napierala if (ret < 0)
3693914ddf8SEdward Tomasz Napierala log_err(1, "asprintf");
3703914ddf8SEdward Tomasz Napierala
3713914ddf8SEdward Tomasz Napierala //log_debugx("\"%s\" expanded with key \"%s\" to \"%s\"",
3723914ddf8SEdward Tomasz Napierala // string, key, expanded);
3733914ddf8SEdward Tomasz Napierala
3743914ddf8SEdward Tomasz Napierala /*
3753914ddf8SEdward Tomasz Napierala * Figure out where to start searching for next variable.
3763914ddf8SEdward Tomasz Napierala */
3773914ddf8SEdward Tomasz Napierala string = expanded;
3783914ddf8SEdward Tomasz Napierala i = before_len + strlen(key);
3791383afcbSEdward Tomasz Napierala if (i == (int)strlen(string))
3801383afcbSEdward Tomasz Napierala break;
3813914ddf8SEdward Tomasz Napierala backslashed = false;
3823914ddf8SEdward Tomasz Napierala //assert(i < (int)strlen(string));
3833914ddf8SEdward Tomasz Napierala }
3843914ddf8SEdward Tomasz Napierala
3853914ddf8SEdward Tomasz Napierala return (expanded);
3863914ddf8SEdward Tomasz Napierala }
3873914ddf8SEdward Tomasz Napierala
3883914ddf8SEdward Tomasz Napierala /*
3893914ddf8SEdward Tomasz Napierala * Expand "&" in n_location. If the key is NULL, try to use
3903914ddf8SEdward Tomasz Napierala * key from map entries themselves. Keep in mind that maps
3913914ddf8SEdward Tomasz Napierala * consist of tho levels of node structures, the key is one
3923914ddf8SEdward Tomasz Napierala * level up.
3933914ddf8SEdward Tomasz Napierala *
3943914ddf8SEdward Tomasz Napierala * Variant with NULL key is for "automount -LL".
3953914ddf8SEdward Tomasz Napierala */
3963914ddf8SEdward Tomasz Napierala void
node_expand_ampersand(struct node * n,const char * key)3973914ddf8SEdward Tomasz Napierala node_expand_ampersand(struct node *n, const char *key)
3983914ddf8SEdward Tomasz Napierala {
3993914ddf8SEdward Tomasz Napierala struct node *child;
4003914ddf8SEdward Tomasz Napierala
4013914ddf8SEdward Tomasz Napierala if (n->n_location != NULL) {
4023914ddf8SEdward Tomasz Napierala if (key == NULL) {
4033914ddf8SEdward Tomasz Napierala if (n->n_parent != NULL &&
4043914ddf8SEdward Tomasz Napierala strcmp(n->n_parent->n_key, "*") != 0) {
4053914ddf8SEdward Tomasz Napierala n->n_location = expand_ampersand(n->n_location,
4063914ddf8SEdward Tomasz Napierala n->n_parent->n_key);
4073914ddf8SEdward Tomasz Napierala }
4083914ddf8SEdward Tomasz Napierala } else {
4093914ddf8SEdward Tomasz Napierala n->n_location = expand_ampersand(n->n_location, key);
4103914ddf8SEdward Tomasz Napierala }
4113914ddf8SEdward Tomasz Napierala }
4123914ddf8SEdward Tomasz Napierala
4133914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next)
4143914ddf8SEdward Tomasz Napierala node_expand_ampersand(child, key);
4153914ddf8SEdward Tomasz Napierala }
4163914ddf8SEdward Tomasz Napierala
4173914ddf8SEdward Tomasz Napierala /*
4183914ddf8SEdward Tomasz Napierala * Expand "*" in n_key.
4193914ddf8SEdward Tomasz Napierala */
4203914ddf8SEdward Tomasz Napierala void
node_expand_wildcard(struct node * n,const char * key)4213914ddf8SEdward Tomasz Napierala node_expand_wildcard(struct node *n, const char *key)
4223914ddf8SEdward Tomasz Napierala {
4233914ddf8SEdward Tomasz Napierala struct node *child, *expanded;
4243914ddf8SEdward Tomasz Napierala
4253914ddf8SEdward Tomasz Napierala assert(key != NULL);
4263914ddf8SEdward Tomasz Napierala
4273914ddf8SEdward Tomasz Napierala if (strcmp(n->n_key, "*") == 0) {
4283914ddf8SEdward Tomasz Napierala expanded = node_duplicate(n, NULL);
4293914ddf8SEdward Tomasz Napierala expanded->n_key = checked_strdup(key);
4303914ddf8SEdward Tomasz Napierala node_move_after(expanded, n);
4313914ddf8SEdward Tomasz Napierala }
4323914ddf8SEdward Tomasz Napierala
4333914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next)
4343914ddf8SEdward Tomasz Napierala node_expand_wildcard(child, key);
4353914ddf8SEdward Tomasz Napierala }
4363914ddf8SEdward Tomasz Napierala
4373914ddf8SEdward Tomasz Napierala int
node_expand_defined(struct node * n)4383914ddf8SEdward Tomasz Napierala node_expand_defined(struct node *n)
4393914ddf8SEdward Tomasz Napierala {
4403914ddf8SEdward Tomasz Napierala struct node *child;
4413914ddf8SEdward Tomasz Napierala int error, cumulated_error = 0;
4423914ddf8SEdward Tomasz Napierala
4433914ddf8SEdward Tomasz Napierala if (n->n_location != NULL) {
4443914ddf8SEdward Tomasz Napierala n->n_location = defined_expand(n->n_location);
4453914ddf8SEdward Tomasz Napierala if (n->n_location == NULL) {
4463914ddf8SEdward Tomasz Napierala log_warnx("failed to expand location for %s",
4473914ddf8SEdward Tomasz Napierala node_path(n));
4483914ddf8SEdward Tomasz Napierala return (EINVAL);
4493914ddf8SEdward Tomasz Napierala }
4503914ddf8SEdward Tomasz Napierala }
4513914ddf8SEdward Tomasz Napierala
4523914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next) {
4533914ddf8SEdward Tomasz Napierala error = node_expand_defined(child);
4543914ddf8SEdward Tomasz Napierala if (error != 0 && cumulated_error == 0)
4553914ddf8SEdward Tomasz Napierala cumulated_error = error;
4563914ddf8SEdward Tomasz Napierala }
4573914ddf8SEdward Tomasz Napierala
4583914ddf8SEdward Tomasz Napierala return (cumulated_error);
4593914ddf8SEdward Tomasz Napierala }
4603914ddf8SEdward Tomasz Napierala
4617a20e479SEdward Tomasz Napierala static bool
node_is_direct_key(const struct node * n)4627a20e479SEdward Tomasz Napierala node_is_direct_key(const struct node *n)
4637a20e479SEdward Tomasz Napierala {
4647a20e479SEdward Tomasz Napierala
4657a20e479SEdward Tomasz Napierala if (n->n_parent != NULL && n->n_parent->n_parent == NULL &&
4667a20e479SEdward Tomasz Napierala strcmp(n->n_key, "/-") == 0) {
4677a20e479SEdward Tomasz Napierala return (true);
4687a20e479SEdward Tomasz Napierala }
4697a20e479SEdward Tomasz Napierala
4707a20e479SEdward Tomasz Napierala return (false);
4717a20e479SEdward Tomasz Napierala }
4727a20e479SEdward Tomasz Napierala
4733914ddf8SEdward Tomasz Napierala bool
node_is_direct_map(const struct node * n)4743914ddf8SEdward Tomasz Napierala node_is_direct_map(const struct node *n)
4753914ddf8SEdward Tomasz Napierala {
4763914ddf8SEdward Tomasz Napierala
4773914ddf8SEdward Tomasz Napierala for (;;) {
4783914ddf8SEdward Tomasz Napierala assert(n->n_parent != NULL);
4793914ddf8SEdward Tomasz Napierala if (n->n_parent->n_parent == NULL)
4803914ddf8SEdward Tomasz Napierala break;
4813914ddf8SEdward Tomasz Napierala n = n->n_parent;
4823914ddf8SEdward Tomasz Napierala }
4833914ddf8SEdward Tomasz Napierala
4847a20e479SEdward Tomasz Napierala return (node_is_direct_key(n));
4853914ddf8SEdward Tomasz Napierala }
4863914ddf8SEdward Tomasz Napierala
4874cdc52bdSEdward Tomasz Napierala bool
node_has_wildcards(const struct node * n)4884cdc52bdSEdward Tomasz Napierala node_has_wildcards(const struct node *n)
4894cdc52bdSEdward Tomasz Napierala {
4904cdc52bdSEdward Tomasz Napierala const struct node *child;
4914cdc52bdSEdward Tomasz Napierala
4924cdc52bdSEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next) {
4934cdc52bdSEdward Tomasz Napierala if (strcmp(child->n_key, "*") == 0)
4944cdc52bdSEdward Tomasz Napierala return (true);
4954cdc52bdSEdward Tomasz Napierala }
4964cdc52bdSEdward Tomasz Napierala
4974cdc52bdSEdward Tomasz Napierala return (false);
4984cdc52bdSEdward Tomasz Napierala }
4994cdc52bdSEdward Tomasz Napierala
5003914ddf8SEdward Tomasz Napierala static void
node_expand_maps(struct node * n,bool indirect)5013914ddf8SEdward Tomasz Napierala node_expand_maps(struct node *n, bool indirect)
5023914ddf8SEdward Tomasz Napierala {
5033914ddf8SEdward Tomasz Napierala struct node *child, *tmp;
5043914ddf8SEdward Tomasz Napierala
5053914ddf8SEdward Tomasz Napierala TAILQ_FOREACH_SAFE(child, &n->n_children, n_next, tmp) {
5063914ddf8SEdward Tomasz Napierala if (node_is_direct_map(child)) {
5073914ddf8SEdward Tomasz Napierala if (indirect)
5083914ddf8SEdward Tomasz Napierala continue;
5093914ddf8SEdward Tomasz Napierala } else {
5103914ddf8SEdward Tomasz Napierala if (indirect == false)
5113914ddf8SEdward Tomasz Napierala continue;
5123914ddf8SEdward Tomasz Napierala }
5133914ddf8SEdward Tomasz Napierala
5143914ddf8SEdward Tomasz Napierala /*
5153914ddf8SEdward Tomasz Napierala * This is the first-level map node; the one that contains
5163914ddf8SEdward Tomasz Napierala * the key and subnodes with mountpoints and actual map names.
5173914ddf8SEdward Tomasz Napierala */
5183914ddf8SEdward Tomasz Napierala if (child->n_map == NULL)
5193914ddf8SEdward Tomasz Napierala continue;
5203914ddf8SEdward Tomasz Napierala
5213914ddf8SEdward Tomasz Napierala if (indirect) {
5223914ddf8SEdward Tomasz Napierala log_debugx("map \"%s\" is an indirect map, parsing",
5233914ddf8SEdward Tomasz Napierala child->n_map);
5243914ddf8SEdward Tomasz Napierala } else {
5253914ddf8SEdward Tomasz Napierala log_debugx("map \"%s\" is a direct map, parsing",
5263914ddf8SEdward Tomasz Napierala child->n_map);
5273914ddf8SEdward Tomasz Napierala }
5284cdc52bdSEdward Tomasz Napierala parse_map(child, child->n_map, NULL, NULL);
5293914ddf8SEdward Tomasz Napierala }
5303914ddf8SEdward Tomasz Napierala }
5313914ddf8SEdward Tomasz Napierala
5323914ddf8SEdward Tomasz Napierala static void
node_expand_direct_maps(struct node * n)5333914ddf8SEdward Tomasz Napierala node_expand_direct_maps(struct node *n)
5343914ddf8SEdward Tomasz Napierala {
5353914ddf8SEdward Tomasz Napierala
5363914ddf8SEdward Tomasz Napierala node_expand_maps(n, false);
5373914ddf8SEdward Tomasz Napierala }
5383914ddf8SEdward Tomasz Napierala
5393914ddf8SEdward Tomasz Napierala void
node_expand_indirect_maps(struct node * n)5403914ddf8SEdward Tomasz Napierala node_expand_indirect_maps(struct node *n)
5413914ddf8SEdward Tomasz Napierala {
5423914ddf8SEdward Tomasz Napierala
5433914ddf8SEdward Tomasz Napierala node_expand_maps(n, true);
5443914ddf8SEdward Tomasz Napierala }
5453914ddf8SEdward Tomasz Napierala
5463914ddf8SEdward Tomasz Napierala static char *
node_path_x(const struct node * n,char * x)5473914ddf8SEdward Tomasz Napierala node_path_x(const struct node *n, char *x)
5483914ddf8SEdward Tomasz Napierala {
5493914ddf8SEdward Tomasz Napierala char *path;
5503914ddf8SEdward Tomasz Napierala
5513914ddf8SEdward Tomasz Napierala if (n->n_parent == NULL)
5523914ddf8SEdward Tomasz Napierala return (x);
5533914ddf8SEdward Tomasz Napierala
5543914ddf8SEdward Tomasz Napierala /*
5553914ddf8SEdward Tomasz Napierala * Return "/-" for direct maps only if we were asked for path
5563914ddf8SEdward Tomasz Napierala * to the "/-" node itself, not to any of its subnodes.
5573914ddf8SEdward Tomasz Napierala */
5587a20e479SEdward Tomasz Napierala if (node_is_direct_key(n) && x[0] != '\0')
5593914ddf8SEdward Tomasz Napierala return (x);
5603914ddf8SEdward Tomasz Napierala
5613dd80c05SEdward Tomasz Napierala assert(n->n_key[0] != '\0');
5626d8e60c3SEdward Tomasz Napierala path = concat(n->n_key, '/', x);
5633914ddf8SEdward Tomasz Napierala free(x);
5643914ddf8SEdward Tomasz Napierala
5653914ddf8SEdward Tomasz Napierala return (node_path_x(n->n_parent, path));
5663914ddf8SEdward Tomasz Napierala }
5673914ddf8SEdward Tomasz Napierala
5683914ddf8SEdward Tomasz Napierala /*
5693914ddf8SEdward Tomasz Napierala * Return full path for node, consisting of concatenated
5703914ddf8SEdward Tomasz Napierala * paths of node itself and all its parents, up to the root.
5713914ddf8SEdward Tomasz Napierala */
5723914ddf8SEdward Tomasz Napierala char *
node_path(const struct node * n)5733914ddf8SEdward Tomasz Napierala node_path(const struct node *n)
5743914ddf8SEdward Tomasz Napierala {
5751bc6f464SEdward Tomasz Napierala char *path;
5761bc6f464SEdward Tomasz Napierala size_t len;
5773914ddf8SEdward Tomasz Napierala
5781bc6f464SEdward Tomasz Napierala path = node_path_x(n, checked_strdup(""));
5791bc6f464SEdward Tomasz Napierala
5801bc6f464SEdward Tomasz Napierala /*
5811bc6f464SEdward Tomasz Napierala * Strip trailing slash, unless the whole path is "/".
5821bc6f464SEdward Tomasz Napierala */
5831bc6f464SEdward Tomasz Napierala len = strlen(path);
5841bc6f464SEdward Tomasz Napierala if (len > 1 && path[len - 1] == '/')
5851bc6f464SEdward Tomasz Napierala path[len - 1] = '\0';
5861bc6f464SEdward Tomasz Napierala
5871bc6f464SEdward Tomasz Napierala return (path);
5883914ddf8SEdward Tomasz Napierala }
5893914ddf8SEdward Tomasz Napierala
5903914ddf8SEdward Tomasz Napierala static char *
node_options_x(const struct node * n,char * x)5913914ddf8SEdward Tomasz Napierala node_options_x(const struct node *n, char *x)
5923914ddf8SEdward Tomasz Napierala {
5933914ddf8SEdward Tomasz Napierala char *options;
5943914ddf8SEdward Tomasz Napierala
5958f0eba67SEdward Tomasz Napierala if (n == NULL)
5968f0eba67SEdward Tomasz Napierala return (x);
5978f0eba67SEdward Tomasz Napierala
5986d8e60c3SEdward Tomasz Napierala options = concat(x, ',', n->n_options);
5998f0eba67SEdward Tomasz Napierala free(x);
6003914ddf8SEdward Tomasz Napierala
6013914ddf8SEdward Tomasz Napierala return (node_options_x(n->n_parent, options));
6023914ddf8SEdward Tomasz Napierala }
6033914ddf8SEdward Tomasz Napierala
6043914ddf8SEdward Tomasz Napierala /*
6053914ddf8SEdward Tomasz Napierala * Return options for node, consisting of concatenated
6063914ddf8SEdward Tomasz Napierala * options from the node itself and all its parents,
6073914ddf8SEdward Tomasz Napierala * up to the root.
6083914ddf8SEdward Tomasz Napierala */
6093914ddf8SEdward Tomasz Napierala char *
node_options(const struct node * n)6103914ddf8SEdward Tomasz Napierala node_options(const struct node *n)
6113914ddf8SEdward Tomasz Napierala {
6123914ddf8SEdward Tomasz Napierala
6133914ddf8SEdward Tomasz Napierala return (node_options_x(n, checked_strdup("")));
6143914ddf8SEdward Tomasz Napierala }
6153914ddf8SEdward Tomasz Napierala
6163914ddf8SEdward Tomasz Napierala static void
node_print_indent(const struct node * n,const char * cmdline_options,int indent)6178ee4f5efSEdward Tomasz Napierala node_print_indent(const struct node *n, const char *cmdline_options,
6188ee4f5efSEdward Tomasz Napierala int indent)
6193914ddf8SEdward Tomasz Napierala {
6203914ddf8SEdward Tomasz Napierala const struct node *child, *first_child;
6218ee4f5efSEdward Tomasz Napierala char *path, *options, *tmp;
6223914ddf8SEdward Tomasz Napierala
6233914ddf8SEdward Tomasz Napierala path = node_path(n);
6248ee4f5efSEdward Tomasz Napierala tmp = node_options(n);
6258ee4f5efSEdward Tomasz Napierala options = concat(cmdline_options, ',', tmp);
6268ee4f5efSEdward Tomasz Napierala free(tmp);
6273914ddf8SEdward Tomasz Napierala
6283914ddf8SEdward Tomasz Napierala /*
6293914ddf8SEdward Tomasz Napierala * Do not show both parent and child node if they have the same
6303914ddf8SEdward Tomasz Napierala * mountpoint; only show the child node. This means the typical,
6313914ddf8SEdward Tomasz Napierala * "key location", map entries are shown in a single line;
6323914ddf8SEdward Tomasz Napierala * the "key mountpoint1 location2 mountpoint2 location2" entries
6333914ddf8SEdward Tomasz Napierala * take multiple lines.
6343914ddf8SEdward Tomasz Napierala */
6353914ddf8SEdward Tomasz Napierala first_child = TAILQ_FIRST(&n->n_children);
6363914ddf8SEdward Tomasz Napierala if (first_child == NULL || TAILQ_NEXT(first_child, n_next) != NULL ||
6373914ddf8SEdward Tomasz Napierala strcmp(path, node_path(first_child)) != 0) {
6383914ddf8SEdward Tomasz Napierala assert(n->n_location == NULL || n->n_map == NULL);
6393914ddf8SEdward Tomasz Napierala printf("%*.s%-*s %s%-*s %-*s # %s map %s at %s:%d\n",
6403914ddf8SEdward Tomasz Napierala indent, "",
6413914ddf8SEdward Tomasz Napierala 25 - indent,
6423914ddf8SEdward Tomasz Napierala path,
6433914ddf8SEdward Tomasz Napierala options[0] != '\0' ? "-" : " ",
6443914ddf8SEdward Tomasz Napierala 20,
6453914ddf8SEdward Tomasz Napierala options[0] != '\0' ? options : "",
6463914ddf8SEdward Tomasz Napierala 20,
6473914ddf8SEdward Tomasz Napierala n->n_location != NULL ? n->n_location : n->n_map != NULL ? n->n_map : "",
6483914ddf8SEdward Tomasz Napierala node_is_direct_map(n) ? "direct" : "indirect",
6493914ddf8SEdward Tomasz Napierala indent == 0 ? "referenced" : "defined",
6503914ddf8SEdward Tomasz Napierala n->n_config_file, n->n_config_line);
6513914ddf8SEdward Tomasz Napierala }
6523914ddf8SEdward Tomasz Napierala
6533914ddf8SEdward Tomasz Napierala free(path);
6543914ddf8SEdward Tomasz Napierala free(options);
6553914ddf8SEdward Tomasz Napierala
6563914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next)
6578ee4f5efSEdward Tomasz Napierala node_print_indent(child, cmdline_options, indent + 2);
6583914ddf8SEdward Tomasz Napierala }
6593914ddf8SEdward Tomasz Napierala
6608ee4f5efSEdward Tomasz Napierala /*
6618ee4f5efSEdward Tomasz Napierala * Recursively print node with all its children. The cmdline_options
6628ee4f5efSEdward Tomasz Napierala * argument is used for additional options to be prepended to all the
6638ee4f5efSEdward Tomasz Napierala * others - usually those are the options passed by command line.
6648ee4f5efSEdward Tomasz Napierala */
6653914ddf8SEdward Tomasz Napierala void
node_print(const struct node * n,const char * cmdline_options)6668ee4f5efSEdward Tomasz Napierala node_print(const struct node *n, const char *cmdline_options)
6673914ddf8SEdward Tomasz Napierala {
6683914ddf8SEdward Tomasz Napierala const struct node *child;
6693914ddf8SEdward Tomasz Napierala
6703914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &n->n_children, n_next)
6718ee4f5efSEdward Tomasz Napierala node_print_indent(child, cmdline_options, 0);
6723914ddf8SEdward Tomasz Napierala }
6733914ddf8SEdward Tomasz Napierala
674cc4026a4SEdward Tomasz Napierala static struct node *
node_find_x(struct node * node,const char * path)675cc4026a4SEdward Tomasz Napierala node_find_x(struct node *node, const char *path)
6763914ddf8SEdward Tomasz Napierala {
6773914ddf8SEdward Tomasz Napierala struct node *child, *found;
6783914ddf8SEdward Tomasz Napierala char *tmp;
679c37463b3SEdward Tomasz Napierala size_t tmplen;
6803914ddf8SEdward Tomasz Napierala
68112f1f00cSEdward Tomasz Napierala //log_debugx("looking up %s in %s", path, node_path(node));
6823914ddf8SEdward Tomasz Napierala
68312f1f00cSEdward Tomasz Napierala if (!node_is_direct_key(node)) {
6843914ddf8SEdward Tomasz Napierala tmp = node_path(node);
685c37463b3SEdward Tomasz Napierala tmplen = strlen(tmp);
686c37463b3SEdward Tomasz Napierala if (strncmp(tmp, path, tmplen) != 0) {
687c37463b3SEdward Tomasz Napierala free(tmp);
688c37463b3SEdward Tomasz Napierala return (NULL);
689c37463b3SEdward Tomasz Napierala }
690c37463b3SEdward Tomasz Napierala if (path[tmplen] != '/' && path[tmplen] != '\0') {
691c37463b3SEdward Tomasz Napierala /*
692c37463b3SEdward Tomasz Napierala * If we have two map entries like 'foo' and 'foobar', make
693c37463b3SEdward Tomasz Napierala * sure the search for 'foobar' won't match 'foo' instead.
694c37463b3SEdward Tomasz Napierala */
6953914ddf8SEdward Tomasz Napierala free(tmp);
6963914ddf8SEdward Tomasz Napierala return (NULL);
6973914ddf8SEdward Tomasz Napierala }
6983914ddf8SEdward Tomasz Napierala free(tmp);
69912f1f00cSEdward Tomasz Napierala }
7003914ddf8SEdward Tomasz Napierala
7013914ddf8SEdward Tomasz Napierala TAILQ_FOREACH(child, &node->n_children, n_next) {
702cc4026a4SEdward Tomasz Napierala found = node_find_x(child, path);
7033914ddf8SEdward Tomasz Napierala if (found != NULL)
7043914ddf8SEdward Tomasz Napierala return (found);
7053914ddf8SEdward Tomasz Napierala }
7063914ddf8SEdward Tomasz Napierala
70712f1f00cSEdward Tomasz Napierala if (node->n_parent == NULL || node_is_direct_key(node))
70812f1f00cSEdward Tomasz Napierala return (NULL);
70912f1f00cSEdward Tomasz Napierala
7103914ddf8SEdward Tomasz Napierala return (node);
7113914ddf8SEdward Tomasz Napierala }
7123914ddf8SEdward Tomasz Napierala
713cc4026a4SEdward Tomasz Napierala struct node *
node_find(struct node * root,const char * path)714cc4026a4SEdward Tomasz Napierala node_find(struct node *root, const char *path)
715cc4026a4SEdward Tomasz Napierala {
716cc4026a4SEdward Tomasz Napierala struct node *node;
717cc4026a4SEdward Tomasz Napierala
71812f1f00cSEdward Tomasz Napierala assert(root->n_parent == NULL);
71912f1f00cSEdward Tomasz Napierala
720cc4026a4SEdward Tomasz Napierala node = node_find_x(root, path);
72112f1f00cSEdward Tomasz Napierala if (node != NULL)
72212f1f00cSEdward Tomasz Napierala assert(node != root);
72312f1f00cSEdward Tomasz Napierala
724cc4026a4SEdward Tomasz Napierala return (node);
725cc4026a4SEdward Tomasz Napierala }
726cc4026a4SEdward Tomasz Napierala
7273914ddf8SEdward Tomasz Napierala /*
7283914ddf8SEdward Tomasz Napierala * Canonical form of a map entry looks like this:
7293914ddf8SEdward Tomasz Napierala *
7303914ddf8SEdward Tomasz Napierala * key [-options] [ [/mountpoint] [-options2] location ... ]
7313914ddf8SEdward Tomasz Napierala *
7323914ddf8SEdward Tomasz Napierala * Entries for executable maps are slightly different, as they
7333914ddf8SEdward Tomasz Napierala * lack the 'key' field and are always single-line; the key field
7343914ddf8SEdward Tomasz Napierala * for those maps is taken from 'executable_key' argument.
7353914ddf8SEdward Tomasz Napierala *
7363914ddf8SEdward Tomasz Napierala * We parse it in such a way that a map always has two levels - first
7373914ddf8SEdward Tomasz Napierala * for key, and the second, for the mountpoint.
7383914ddf8SEdward Tomasz Napierala */
7393914ddf8SEdward Tomasz Napierala static void
parse_map_yyin(struct node * parent,const char * map,const char * executable_key)7403914ddf8SEdward Tomasz Napierala parse_map_yyin(struct node *parent, const char *map, const char *executable_key)
7413914ddf8SEdward Tomasz Napierala {
7423914ddf8SEdward Tomasz Napierala char *key = NULL, *options = NULL, *mountpoint = NULL,
7433914ddf8SEdward Tomasz Napierala *options2 = NULL, *location = NULL;
7443914ddf8SEdward Tomasz Napierala int ret;
7453914ddf8SEdward Tomasz Napierala struct node *node;
7463914ddf8SEdward Tomasz Napierala
7473914ddf8SEdward Tomasz Napierala lineno = 1;
7483914ddf8SEdward Tomasz Napierala
7493914ddf8SEdward Tomasz Napierala if (executable_key != NULL)
7503914ddf8SEdward Tomasz Napierala key = checked_strdup(executable_key);
7513914ddf8SEdward Tomasz Napierala
7523914ddf8SEdward Tomasz Napierala for (;;) {
7533914ddf8SEdward Tomasz Napierala ret = yylex();
7543914ddf8SEdward Tomasz Napierala if (ret == 0 || ret == NEWLINE) {
75530ae6e00SEdward Tomasz Napierala /*
75630ae6e00SEdward Tomasz Napierala * In case of executable map, the key is always
75730ae6e00SEdward Tomasz Napierala * non-NULL, even if the map is empty. So, make sure
75830ae6e00SEdward Tomasz Napierala * we don't fail empty maps here.
75930ae6e00SEdward Tomasz Napierala */
76030ae6e00SEdward Tomasz Napierala if ((key != NULL && executable_key == NULL) ||
76130ae6e00SEdward Tomasz Napierala options != NULL) {
7623914ddf8SEdward Tomasz Napierala log_errx(1, "truncated entry at %s, line %d",
7633914ddf8SEdward Tomasz Napierala map, lineno);
7643914ddf8SEdward Tomasz Napierala }
7653914ddf8SEdward Tomasz Napierala if (ret == 0 || executable_key != NULL) {
7663914ddf8SEdward Tomasz Napierala /*
7673914ddf8SEdward Tomasz Napierala * End of file.
7683914ddf8SEdward Tomasz Napierala */
7693914ddf8SEdward Tomasz Napierala break;
7703914ddf8SEdward Tomasz Napierala } else {
7713914ddf8SEdward Tomasz Napierala key = options = NULL;
7723914ddf8SEdward Tomasz Napierala continue;
7733914ddf8SEdward Tomasz Napierala }
7743914ddf8SEdward Tomasz Napierala }
7753914ddf8SEdward Tomasz Napierala if (key == NULL) {
7763914ddf8SEdward Tomasz Napierala key = checked_strdup(yytext);
7773914ddf8SEdward Tomasz Napierala if (key[0] == '+') {
7783914ddf8SEdward Tomasz Napierala node_new(parent, key, NULL, NULL, map, lineno);
7793914ddf8SEdward Tomasz Napierala key = options = NULL;
7803914ddf8SEdward Tomasz Napierala continue;
7813914ddf8SEdward Tomasz Napierala }
7823914ddf8SEdward Tomasz Napierala continue;
7833914ddf8SEdward Tomasz Napierala } else if (yytext[0] == '-') {
7843914ddf8SEdward Tomasz Napierala if (options != NULL) {
7853914ddf8SEdward Tomasz Napierala log_errx(1, "duplicated options at %s, line %d",
7863914ddf8SEdward Tomasz Napierala map, lineno);
7873914ddf8SEdward Tomasz Napierala }
7883914ddf8SEdward Tomasz Napierala /*
7893914ddf8SEdward Tomasz Napierala * +1 to skip leading "-".
7903914ddf8SEdward Tomasz Napierala */
7913914ddf8SEdward Tomasz Napierala options = checked_strdup(yytext + 1);
7923914ddf8SEdward Tomasz Napierala continue;
7933914ddf8SEdward Tomasz Napierala }
7943914ddf8SEdward Tomasz Napierala
7953914ddf8SEdward Tomasz Napierala /*
7963914ddf8SEdward Tomasz Napierala * We cannot properly handle a situation where the map key
7973914ddf8SEdward Tomasz Napierala * is "/". Ignore such entries.
7983914ddf8SEdward Tomasz Napierala *
7993914ddf8SEdward Tomasz Napierala * XXX: According to Piete Brooks, Linux automounter uses
8003914ddf8SEdward Tomasz Napierala * "/" as a wildcard character in LDAP maps. Perhaps
8013914ddf8SEdward Tomasz Napierala * we should work around this braindamage by substituting
8023914ddf8SEdward Tomasz Napierala * "*" for "/"?
8033914ddf8SEdward Tomasz Napierala */
8043914ddf8SEdward Tomasz Napierala if (strcmp(key, "/") == 0) {
8053914ddf8SEdward Tomasz Napierala log_warnx("nonsensical map key \"/\" at %s, line %d; "
8063914ddf8SEdward Tomasz Napierala "ignoring map entry ", map, lineno);
8073914ddf8SEdward Tomasz Napierala
8083914ddf8SEdward Tomasz Napierala /*
8093914ddf8SEdward Tomasz Napierala * Skip the rest of the entry.
8103914ddf8SEdward Tomasz Napierala */
8113914ddf8SEdward Tomasz Napierala do {
8123914ddf8SEdward Tomasz Napierala ret = yylex();
8133914ddf8SEdward Tomasz Napierala } while (ret != 0 && ret != NEWLINE);
8143914ddf8SEdward Tomasz Napierala
8153914ddf8SEdward Tomasz Napierala key = options = NULL;
8163914ddf8SEdward Tomasz Napierala continue;
8173914ddf8SEdward Tomasz Napierala }
8183914ddf8SEdward Tomasz Napierala
8193914ddf8SEdward Tomasz Napierala //log_debugx("adding map node, %s", key);
8203914ddf8SEdward Tomasz Napierala node = node_new(parent, key, options, NULL, map, lineno);
8213914ddf8SEdward Tomasz Napierala key = options = NULL;
8223914ddf8SEdward Tomasz Napierala
8233914ddf8SEdward Tomasz Napierala for (;;) {
8243914ddf8SEdward Tomasz Napierala if (yytext[0] == '/') {
8253914ddf8SEdward Tomasz Napierala if (mountpoint != NULL) {
8263914ddf8SEdward Tomasz Napierala log_errx(1, "duplicated mountpoint "
8273914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8283914ddf8SEdward Tomasz Napierala }
8293914ddf8SEdward Tomasz Napierala if (options2 != NULL || location != NULL) {
8303914ddf8SEdward Tomasz Napierala log_errx(1, "mountpoint out of order "
8313914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8323914ddf8SEdward Tomasz Napierala }
8333914ddf8SEdward Tomasz Napierala mountpoint = checked_strdup(yytext);
8343914ddf8SEdward Tomasz Napierala goto again;
8353914ddf8SEdward Tomasz Napierala }
8363914ddf8SEdward Tomasz Napierala
8373914ddf8SEdward Tomasz Napierala if (yytext[0] == '-') {
8383914ddf8SEdward Tomasz Napierala if (options2 != NULL) {
8393914ddf8SEdward Tomasz Napierala log_errx(1, "duplicated options "
8403914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8413914ddf8SEdward Tomasz Napierala }
8423914ddf8SEdward Tomasz Napierala if (location != NULL) {
8433914ddf8SEdward Tomasz Napierala log_errx(1, "options out of order "
8443914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8453914ddf8SEdward Tomasz Napierala }
8463914ddf8SEdward Tomasz Napierala options2 = checked_strdup(yytext + 1);
8473914ddf8SEdward Tomasz Napierala goto again;
8483914ddf8SEdward Tomasz Napierala }
8493914ddf8SEdward Tomasz Napierala
8503914ddf8SEdward Tomasz Napierala if (location != NULL) {
8513914ddf8SEdward Tomasz Napierala log_errx(1, "too many arguments "
8523914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8533914ddf8SEdward Tomasz Napierala }
8543914ddf8SEdward Tomasz Napierala
8553914ddf8SEdward Tomasz Napierala /*
8563914ddf8SEdward Tomasz Napierala * If location field starts with colon, e.g. ":/dev/cd0",
8573914ddf8SEdward Tomasz Napierala * then strip it.
8583914ddf8SEdward Tomasz Napierala */
8593914ddf8SEdward Tomasz Napierala if (yytext[0] == ':') {
8603914ddf8SEdward Tomasz Napierala location = checked_strdup(yytext + 1);
8613914ddf8SEdward Tomasz Napierala if (location[0] == '\0') {
8623914ddf8SEdward Tomasz Napierala log_errx(1, "empty location in %s, "
8633914ddf8SEdward Tomasz Napierala "line %d", map, lineno);
8643914ddf8SEdward Tomasz Napierala }
8653914ddf8SEdward Tomasz Napierala } else {
8663914ddf8SEdward Tomasz Napierala location = checked_strdup(yytext);
8673914ddf8SEdward Tomasz Napierala }
8683914ddf8SEdward Tomasz Napierala
8693914ddf8SEdward Tomasz Napierala if (mountpoint == NULL)
8703914ddf8SEdward Tomasz Napierala mountpoint = checked_strdup("/");
8713914ddf8SEdward Tomasz Napierala if (options2 == NULL)
8723914ddf8SEdward Tomasz Napierala options2 = checked_strdup("");
8733914ddf8SEdward Tomasz Napierala
8743914ddf8SEdward Tomasz Napierala #if 0
8753914ddf8SEdward Tomasz Napierala log_debugx("adding map node, %s %s %s",
8763914ddf8SEdward Tomasz Napierala mountpoint, options2, location);
8773914ddf8SEdward Tomasz Napierala #endif
8783914ddf8SEdward Tomasz Napierala node_new(node, mountpoint, options2, location,
8793914ddf8SEdward Tomasz Napierala map, lineno);
8803914ddf8SEdward Tomasz Napierala mountpoint = options2 = location = NULL;
8813914ddf8SEdward Tomasz Napierala again:
8823914ddf8SEdward Tomasz Napierala ret = yylex();
8833914ddf8SEdward Tomasz Napierala if (ret == 0 || ret == NEWLINE) {
8843914ddf8SEdward Tomasz Napierala if (mountpoint != NULL || options2 != NULL ||
8853914ddf8SEdward Tomasz Napierala location != NULL) {
8863914ddf8SEdward Tomasz Napierala log_errx(1, "truncated entry "
8873914ddf8SEdward Tomasz Napierala "in %s, line %d", map, lineno);
8883914ddf8SEdward Tomasz Napierala }
8893914ddf8SEdward Tomasz Napierala break;
8903914ddf8SEdward Tomasz Napierala }
8913914ddf8SEdward Tomasz Napierala }
8923914ddf8SEdward Tomasz Napierala }
8933914ddf8SEdward Tomasz Napierala }
8943914ddf8SEdward Tomasz Napierala
895f7ae8307SEdward Tomasz Napierala /*
8963dd80c05SEdward Tomasz Napierala * Parse output of a special map called without argument. It is a list
8973dd80c05SEdward Tomasz Napierala * of keys, separated by newlines. They can contain whitespace, so use
8983dd80c05SEdward Tomasz Napierala * getline(3) instead of lexer used for maps.
899f7ae8307SEdward Tomasz Napierala */
900f7ae8307SEdward Tomasz Napierala static void
parse_map_keys_yyin(struct node * parent,const char * map)901f7ae8307SEdward Tomasz Napierala parse_map_keys_yyin(struct node *parent, const char *map)
902f7ae8307SEdward Tomasz Napierala {
9033dd80c05SEdward Tomasz Napierala char *line = NULL, *key;
9043dd80c05SEdward Tomasz Napierala size_t linecap = 0;
9053dd80c05SEdward Tomasz Napierala ssize_t linelen;
906f7ae8307SEdward Tomasz Napierala
907f7ae8307SEdward Tomasz Napierala lineno = 1;
908f7ae8307SEdward Tomasz Napierala
909f7ae8307SEdward Tomasz Napierala for (;;) {
9103dd80c05SEdward Tomasz Napierala linelen = getline(&line, &linecap, yyin);
9113dd80c05SEdward Tomasz Napierala if (linelen < 0) {
912f7ae8307SEdward Tomasz Napierala /*
913f7ae8307SEdward Tomasz Napierala * End of file.
914f7ae8307SEdward Tomasz Napierala */
915f7ae8307SEdward Tomasz Napierala break;
916f7ae8307SEdward Tomasz Napierala }
9173dd80c05SEdward Tomasz Napierala if (linelen <= 1) {
9183dd80c05SEdward Tomasz Napierala /*
9193dd80c05SEdward Tomasz Napierala * Empty line, consisting of just the newline.
9203dd80c05SEdward Tomasz Napierala */
9213dd80c05SEdward Tomasz Napierala continue;
922f7ae8307SEdward Tomasz Napierala }
9233dd80c05SEdward Tomasz Napierala
9243dd80c05SEdward Tomasz Napierala /*
9253dd80c05SEdward Tomasz Napierala * "-1" to strip the trailing newline.
9263dd80c05SEdward Tomasz Napierala */
9273dd80c05SEdward Tomasz Napierala key = strndup(line, linelen - 1);
9283dd80c05SEdward Tomasz Napierala
9293dd80c05SEdward Tomasz Napierala log_debugx("adding key \"%s\"", key);
9303dd80c05SEdward Tomasz Napierala node_new(parent, key, NULL, NULL, map, lineno);
9313dd80c05SEdward Tomasz Napierala lineno++;
9323dd80c05SEdward Tomasz Napierala }
9333dd80c05SEdward Tomasz Napierala free(line);
934f7ae8307SEdward Tomasz Napierala }
935f7ae8307SEdward Tomasz Napierala
9363914ddf8SEdward Tomasz Napierala static bool
file_is_executable(const char * path)9373914ddf8SEdward Tomasz Napierala file_is_executable(const char *path)
9383914ddf8SEdward Tomasz Napierala {
9393914ddf8SEdward Tomasz Napierala struct stat sb;
9403914ddf8SEdward Tomasz Napierala int error;
9413914ddf8SEdward Tomasz Napierala
9423914ddf8SEdward Tomasz Napierala error = stat(path, &sb);
9433914ddf8SEdward Tomasz Napierala if (error != 0)
9443914ddf8SEdward Tomasz Napierala log_err(1, "cannot stat %s", path);
9453914ddf8SEdward Tomasz Napierala if ((sb.st_mode & S_IXUSR) || (sb.st_mode & S_IXGRP) ||
9463914ddf8SEdward Tomasz Napierala (sb.st_mode & S_IXOTH))
9473914ddf8SEdward Tomasz Napierala return (true);
9483914ddf8SEdward Tomasz Napierala return (false);
9493914ddf8SEdward Tomasz Napierala }
9503914ddf8SEdward Tomasz Napierala
9513914ddf8SEdward Tomasz Napierala /*
9523914ddf8SEdward Tomasz Napierala * Parse a special map, e.g. "-hosts".
9533914ddf8SEdward Tomasz Napierala */
9543914ddf8SEdward Tomasz Napierala static void
parse_special_map(struct node * parent,const char * map,const char * key)9553914ddf8SEdward Tomasz Napierala parse_special_map(struct node *parent, const char *map, const char *key)
9563914ddf8SEdward Tomasz Napierala {
9573914ddf8SEdward Tomasz Napierala char *path;
9583914ddf8SEdward Tomasz Napierala int error, ret;
9593914ddf8SEdward Tomasz Napierala
9603914ddf8SEdward Tomasz Napierala assert(map[0] == '-');
9613914ddf8SEdward Tomasz Napierala
9623914ddf8SEdward Tomasz Napierala /*
9633914ddf8SEdward Tomasz Napierala * +1 to skip leading "-" in map name.
9643914ddf8SEdward Tomasz Napierala */
9653914ddf8SEdward Tomasz Napierala ret = asprintf(&path, "%s/special_%s", AUTO_SPECIAL_PREFIX, map + 1);
9663914ddf8SEdward Tomasz Napierala if (ret < 0)
9673914ddf8SEdward Tomasz Napierala log_err(1, "asprintf");
9683914ddf8SEdward Tomasz Napierala
9693914ddf8SEdward Tomasz Napierala yyin = auto_popen(path, key, NULL);
9703914ddf8SEdward Tomasz Napierala assert(yyin != NULL);
9713914ddf8SEdward Tomasz Napierala
972f7ae8307SEdward Tomasz Napierala if (key == NULL) {
973f7ae8307SEdward Tomasz Napierala parse_map_keys_yyin(parent, map);
974f7ae8307SEdward Tomasz Napierala } else {
9753914ddf8SEdward Tomasz Napierala parse_map_yyin(parent, map, key);
976f7ae8307SEdward Tomasz Napierala }
9773914ddf8SEdward Tomasz Napierala
9783914ddf8SEdward Tomasz Napierala error = auto_pclose(yyin);
9793914ddf8SEdward Tomasz Napierala yyin = NULL;
9803914ddf8SEdward Tomasz Napierala if (error != 0)
9813914ddf8SEdward Tomasz Napierala log_errx(1, "failed to handle special map \"%s\"", map);
9823914ddf8SEdward Tomasz Napierala
9833914ddf8SEdward Tomasz Napierala node_expand_includes(parent, false);
9843914ddf8SEdward Tomasz Napierala node_expand_direct_maps(parent);
9853914ddf8SEdward Tomasz Napierala
9863914ddf8SEdward Tomasz Napierala free(path);
9873914ddf8SEdward Tomasz Napierala }
9883914ddf8SEdward Tomasz Napierala
9893914ddf8SEdward Tomasz Napierala /*
9903914ddf8SEdward Tomasz Napierala * Retrieve and parse map from directory services, e.g. LDAP.
9913914ddf8SEdward Tomasz Napierala * Note that it is different from executable maps, in that
9923914ddf8SEdward Tomasz Napierala * the include script outputs the whole map to standard output
9933914ddf8SEdward Tomasz Napierala * (as opposed to executable maps that only output a single
9943914ddf8SEdward Tomasz Napierala * entry, without the key), and it takes the map name as an
9953914ddf8SEdward Tomasz Napierala * argument, instead of key.
9963914ddf8SEdward Tomasz Napierala */
9973914ddf8SEdward Tomasz Napierala static void
parse_included_map(struct node * parent,const char * map)9983914ddf8SEdward Tomasz Napierala parse_included_map(struct node *parent, const char *map)
9993914ddf8SEdward Tomasz Napierala {
10003914ddf8SEdward Tomasz Napierala int error;
10013914ddf8SEdward Tomasz Napierala
10023914ddf8SEdward Tomasz Napierala assert(map[0] != '-');
10033914ddf8SEdward Tomasz Napierala assert(map[0] != '/');
10043914ddf8SEdward Tomasz Napierala
10053914ddf8SEdward Tomasz Napierala error = access(AUTO_INCLUDE_PATH, F_OK);
10063914ddf8SEdward Tomasz Napierala if (error != 0) {
10073914ddf8SEdward Tomasz Napierala log_errx(1, "directory services not configured;"
10083914ddf8SEdward Tomasz Napierala " %s does not exist", AUTO_INCLUDE_PATH);
10093914ddf8SEdward Tomasz Napierala }
10103914ddf8SEdward Tomasz Napierala
10113914ddf8SEdward Tomasz Napierala yyin = auto_popen(AUTO_INCLUDE_PATH, map, NULL);
10123914ddf8SEdward Tomasz Napierala assert(yyin != NULL);
10133914ddf8SEdward Tomasz Napierala
10143914ddf8SEdward Tomasz Napierala parse_map_yyin(parent, map, NULL);
10153914ddf8SEdward Tomasz Napierala
10163914ddf8SEdward Tomasz Napierala error = auto_pclose(yyin);
10173914ddf8SEdward Tomasz Napierala yyin = NULL;
10183914ddf8SEdward Tomasz Napierala if (error != 0)
10193914ddf8SEdward Tomasz Napierala log_errx(1, "failed to handle remote map \"%s\"", map);
10203914ddf8SEdward Tomasz Napierala
10213914ddf8SEdward Tomasz Napierala node_expand_includes(parent, false);
10223914ddf8SEdward Tomasz Napierala node_expand_direct_maps(parent);
10233914ddf8SEdward Tomasz Napierala }
10243914ddf8SEdward Tomasz Napierala
10253914ddf8SEdward Tomasz Napierala void
parse_map(struct node * parent,const char * map,const char * key,bool * wildcards)10264cdc52bdSEdward Tomasz Napierala parse_map(struct node *parent, const char *map, const char *key,
10274cdc52bdSEdward Tomasz Napierala bool *wildcards)
10283914ddf8SEdward Tomasz Napierala {
10293914ddf8SEdward Tomasz Napierala char *path = NULL;
10303914ddf8SEdward Tomasz Napierala int error, ret;
10313914ddf8SEdward Tomasz Napierala bool executable;
10323914ddf8SEdward Tomasz Napierala
10333914ddf8SEdward Tomasz Napierala assert(map != NULL);
10343914ddf8SEdward Tomasz Napierala assert(map[0] != '\0');
10353914ddf8SEdward Tomasz Napierala
10363914ddf8SEdward Tomasz Napierala log_debugx("parsing map \"%s\"", map);
10373914ddf8SEdward Tomasz Napierala
10384cdc52bdSEdward Tomasz Napierala if (wildcards != NULL)
10394cdc52bdSEdward Tomasz Napierala *wildcards = false;
10404cdc52bdSEdward Tomasz Napierala
10414cdc52bdSEdward Tomasz Napierala if (map[0] == '-') {
10424cdc52bdSEdward Tomasz Napierala if (wildcards != NULL)
10434cdc52bdSEdward Tomasz Napierala *wildcards = true;
10443914ddf8SEdward Tomasz Napierala return (parse_special_map(parent, map, key));
10454cdc52bdSEdward Tomasz Napierala }
10463914ddf8SEdward Tomasz Napierala
10473914ddf8SEdward Tomasz Napierala if (map[0] == '/') {
10483914ddf8SEdward Tomasz Napierala path = checked_strdup(map);
10493914ddf8SEdward Tomasz Napierala } else {
10503914ddf8SEdward Tomasz Napierala ret = asprintf(&path, "%s/%s", AUTO_MAP_PREFIX, map);
10513914ddf8SEdward Tomasz Napierala if (ret < 0)
10523914ddf8SEdward Tomasz Napierala log_err(1, "asprintf");
10533914ddf8SEdward Tomasz Napierala log_debugx("map \"%s\" maps to \"%s\"", map, path);
10543914ddf8SEdward Tomasz Napierala
10553914ddf8SEdward Tomasz Napierala /*
10563914ddf8SEdward Tomasz Napierala * See if the file exists. If not, try to obtain the map
10573914ddf8SEdward Tomasz Napierala * from directory services.
10583914ddf8SEdward Tomasz Napierala */
10593914ddf8SEdward Tomasz Napierala error = access(path, F_OK);
10603914ddf8SEdward Tomasz Napierala if (error != 0) {
10613914ddf8SEdward Tomasz Napierala log_debugx("map file \"%s\" does not exist; falling "
10623914ddf8SEdward Tomasz Napierala "back to directory services", path);
10633914ddf8SEdward Tomasz Napierala return (parse_included_map(parent, map));
10643914ddf8SEdward Tomasz Napierala }
10653914ddf8SEdward Tomasz Napierala }
10663914ddf8SEdward Tomasz Napierala
10673914ddf8SEdward Tomasz Napierala executable = file_is_executable(path);
10683914ddf8SEdward Tomasz Napierala
10693914ddf8SEdward Tomasz Napierala if (executable) {
10703914ddf8SEdward Tomasz Napierala log_debugx("map \"%s\" is executable", map);
10713914ddf8SEdward Tomasz Napierala
10724cdc52bdSEdward Tomasz Napierala if (wildcards != NULL)
10734cdc52bdSEdward Tomasz Napierala *wildcards = true;
10744cdc52bdSEdward Tomasz Napierala
10753914ddf8SEdward Tomasz Napierala if (key != NULL) {
10763914ddf8SEdward Tomasz Napierala yyin = auto_popen(path, key, NULL);
10773914ddf8SEdward Tomasz Napierala } else {
10783914ddf8SEdward Tomasz Napierala yyin = auto_popen(path, NULL);
10793914ddf8SEdward Tomasz Napierala }
10803914ddf8SEdward Tomasz Napierala assert(yyin != NULL);
10813914ddf8SEdward Tomasz Napierala } else {
10823914ddf8SEdward Tomasz Napierala yyin = fopen(path, "r");
10833914ddf8SEdward Tomasz Napierala if (yyin == NULL)
10843914ddf8SEdward Tomasz Napierala log_err(1, "unable to open \"%s\"", path);
10853914ddf8SEdward Tomasz Napierala }
10863914ddf8SEdward Tomasz Napierala
10873914ddf8SEdward Tomasz Napierala free(path);
10883914ddf8SEdward Tomasz Napierala path = NULL;
10893914ddf8SEdward Tomasz Napierala
10903914ddf8SEdward Tomasz Napierala parse_map_yyin(parent, map, executable ? key : NULL);
10913914ddf8SEdward Tomasz Napierala
10923914ddf8SEdward Tomasz Napierala if (executable) {
10933914ddf8SEdward Tomasz Napierala error = auto_pclose(yyin);
10943914ddf8SEdward Tomasz Napierala yyin = NULL;
10953914ddf8SEdward Tomasz Napierala if (error != 0) {
10963914ddf8SEdward Tomasz Napierala log_errx(1, "failed to handle executable map \"%s\"",
10973914ddf8SEdward Tomasz Napierala map);
10983914ddf8SEdward Tomasz Napierala }
10993914ddf8SEdward Tomasz Napierala } else {
11003914ddf8SEdward Tomasz Napierala fclose(yyin);
11013914ddf8SEdward Tomasz Napierala }
11023914ddf8SEdward Tomasz Napierala yyin = NULL;
11033914ddf8SEdward Tomasz Napierala
11043914ddf8SEdward Tomasz Napierala log_debugx("done parsing map \"%s\"", map);
11053914ddf8SEdward Tomasz Napierala
11063914ddf8SEdward Tomasz Napierala node_expand_includes(parent, false);
11073914ddf8SEdward Tomasz Napierala node_expand_direct_maps(parent);
11083914ddf8SEdward Tomasz Napierala }
11093914ddf8SEdward Tomasz Napierala
11103914ddf8SEdward Tomasz Napierala static void
parse_master_yyin(struct node * root,const char * master)11113914ddf8SEdward Tomasz Napierala parse_master_yyin(struct node *root, const char *master)
11123914ddf8SEdward Tomasz Napierala {
11133914ddf8SEdward Tomasz Napierala char *mountpoint = NULL, *map = NULL, *options = NULL;
11143914ddf8SEdward Tomasz Napierala int ret;
11153914ddf8SEdward Tomasz Napierala
11163914ddf8SEdward Tomasz Napierala /*
11173914ddf8SEdward Tomasz Napierala * XXX: 1 gives incorrect values; wtf?
11183914ddf8SEdward Tomasz Napierala */
11193914ddf8SEdward Tomasz Napierala lineno = 0;
11203914ddf8SEdward Tomasz Napierala
11213914ddf8SEdward Tomasz Napierala for (;;) {
11223914ddf8SEdward Tomasz Napierala ret = yylex();
11233914ddf8SEdward Tomasz Napierala if (ret == 0 || ret == NEWLINE) {
11243914ddf8SEdward Tomasz Napierala if (mountpoint != NULL) {
11253914ddf8SEdward Tomasz Napierala //log_debugx("adding map for %s", mountpoint);
11263914ddf8SEdward Tomasz Napierala node_new_map(root, mountpoint, options, map,
11273914ddf8SEdward Tomasz Napierala master, lineno);
11283914ddf8SEdward Tomasz Napierala }
11293914ddf8SEdward Tomasz Napierala if (ret == 0) {
11303914ddf8SEdward Tomasz Napierala break;
11313914ddf8SEdward Tomasz Napierala } else {
11323914ddf8SEdward Tomasz Napierala mountpoint = map = options = NULL;
11333914ddf8SEdward Tomasz Napierala continue;
11343914ddf8SEdward Tomasz Napierala }
11353914ddf8SEdward Tomasz Napierala }
11363914ddf8SEdward Tomasz Napierala if (mountpoint == NULL) {
11373914ddf8SEdward Tomasz Napierala mountpoint = checked_strdup(yytext);
11383914ddf8SEdward Tomasz Napierala } else if (map == NULL) {
11393914ddf8SEdward Tomasz Napierala map = checked_strdup(yytext);
11403914ddf8SEdward Tomasz Napierala } else if (options == NULL) {
11413914ddf8SEdward Tomasz Napierala /*
11423914ddf8SEdward Tomasz Napierala * +1 to skip leading "-".
11433914ddf8SEdward Tomasz Napierala */
11443914ddf8SEdward Tomasz Napierala options = checked_strdup(yytext + 1);
11453914ddf8SEdward Tomasz Napierala } else {
11463914ddf8SEdward Tomasz Napierala log_errx(1, "too many arguments at %s, line %d",
11473914ddf8SEdward Tomasz Napierala master, lineno);
11483914ddf8SEdward Tomasz Napierala }
11493914ddf8SEdward Tomasz Napierala }
11503914ddf8SEdward Tomasz Napierala }
11513914ddf8SEdward Tomasz Napierala
11523914ddf8SEdward Tomasz Napierala void
parse_master(struct node * root,const char * master)11533914ddf8SEdward Tomasz Napierala parse_master(struct node *root, const char *master)
11543914ddf8SEdward Tomasz Napierala {
11553914ddf8SEdward Tomasz Napierala
11563914ddf8SEdward Tomasz Napierala log_debugx("parsing auto_master file at \"%s\"", master);
11573914ddf8SEdward Tomasz Napierala
11583914ddf8SEdward Tomasz Napierala yyin = fopen(master, "r");
11593914ddf8SEdward Tomasz Napierala if (yyin == NULL)
11603914ddf8SEdward Tomasz Napierala err(1, "unable to open %s", master);
11613914ddf8SEdward Tomasz Napierala
11623914ddf8SEdward Tomasz Napierala parse_master_yyin(root, master);
11633914ddf8SEdward Tomasz Napierala
11643914ddf8SEdward Tomasz Napierala fclose(yyin);
11653914ddf8SEdward Tomasz Napierala yyin = NULL;
11663914ddf8SEdward Tomasz Napierala
11673914ddf8SEdward Tomasz Napierala log_debugx("done parsing \"%s\"", master);
11683914ddf8SEdward Tomasz Napierala
11693914ddf8SEdward Tomasz Napierala node_expand_includes(root, true);
11703914ddf8SEdward Tomasz Napierala node_expand_direct_maps(root);
11713914ddf8SEdward Tomasz Napierala }
11723914ddf8SEdward Tomasz Napierala
11733914ddf8SEdward Tomasz Napierala /*
11743914ddf8SEdward Tomasz Napierala * Two things daemon(3) does, that we actually also want to do
11753914ddf8SEdward Tomasz Napierala * when running in foreground, is closing the stdin and chdiring
11763914ddf8SEdward Tomasz Napierala * to "/". This is what we do here.
11773914ddf8SEdward Tomasz Napierala */
11783914ddf8SEdward Tomasz Napierala void
lesser_daemon(void)11793914ddf8SEdward Tomasz Napierala lesser_daemon(void)
11803914ddf8SEdward Tomasz Napierala {
11813914ddf8SEdward Tomasz Napierala int error, fd;
11823914ddf8SEdward Tomasz Napierala
11833914ddf8SEdward Tomasz Napierala error = chdir("/");
11843914ddf8SEdward Tomasz Napierala if (error != 0)
11853914ddf8SEdward Tomasz Napierala log_warn("chdir");
11863914ddf8SEdward Tomasz Napierala
11873914ddf8SEdward Tomasz Napierala fd = open(_PATH_DEVNULL, O_RDWR, 0);
11883914ddf8SEdward Tomasz Napierala if (fd < 0) {
11893914ddf8SEdward Tomasz Napierala log_warn("cannot open %s", _PATH_DEVNULL);
11903914ddf8SEdward Tomasz Napierala return;
11913914ddf8SEdward Tomasz Napierala }
11923914ddf8SEdward Tomasz Napierala
11933914ddf8SEdward Tomasz Napierala error = dup2(fd, STDIN_FILENO);
11943914ddf8SEdward Tomasz Napierala if (error != 0)
11953914ddf8SEdward Tomasz Napierala log_warn("dup2");
11963914ddf8SEdward Tomasz Napierala
11973914ddf8SEdward Tomasz Napierala error = close(fd);
11983914ddf8SEdward Tomasz Napierala if (error != 0) {
11993914ddf8SEdward Tomasz Napierala /* Bloody hell. */
12003914ddf8SEdward Tomasz Napierala log_warn("close");
12013914ddf8SEdward Tomasz Napierala }
12023914ddf8SEdward Tomasz Napierala }
12033914ddf8SEdward Tomasz Napierala
120488e531f3SRobert Wing /*
120588e531f3SRobert Wing * Applicable to NFSv3 only, see rpc.umntall(8).
120688e531f3SRobert Wing */
120788e531f3SRobert Wing void
rpc_umntall(void)120888e531f3SRobert Wing rpc_umntall(void)
120988e531f3SRobert Wing {
121088e531f3SRobert Wing FILE *f;
121188e531f3SRobert Wing
121288e531f3SRobert Wing f = auto_popen("rpc.umntall", "-k", NULL);
121388e531f3SRobert Wing assert(f != NULL);
121488e531f3SRobert Wing auto_pclose(f);
121588e531f3SRobert Wing }
121688e531f3SRobert Wing
12173914ddf8SEdward Tomasz Napierala int
main(int argc,char ** argv)12183914ddf8SEdward Tomasz Napierala main(int argc, char **argv)
12193914ddf8SEdward Tomasz Napierala {
12203914ddf8SEdward Tomasz Napierala char *cmdname;
12213914ddf8SEdward Tomasz Napierala
12223914ddf8SEdward Tomasz Napierala if (argv[0] == NULL)
12233914ddf8SEdward Tomasz Napierala log_errx(1, "NULL command name");
12243914ddf8SEdward Tomasz Napierala
12253914ddf8SEdward Tomasz Napierala cmdname = basename(argv[0]);
12263914ddf8SEdward Tomasz Napierala
12273914ddf8SEdward Tomasz Napierala if (strcmp(cmdname, "automount") == 0)
12283914ddf8SEdward Tomasz Napierala return (main_automount(argc, argv));
12293914ddf8SEdward Tomasz Napierala else if (strcmp(cmdname, "automountd") == 0)
12303914ddf8SEdward Tomasz Napierala return (main_automountd(argc, argv));
12313914ddf8SEdward Tomasz Napierala else if (strcmp(cmdname, "autounmountd") == 0)
12323914ddf8SEdward Tomasz Napierala return (main_autounmountd(argc, argv));
12333914ddf8SEdward Tomasz Napierala else
12343914ddf8SEdward Tomasz Napierala log_errx(1, "binary name should be either \"automount\", "
12353914ddf8SEdward Tomasz Napierala "\"automountd\", or \"autounmountd\"");
12363914ddf8SEdward Tomasz Napierala }
1237