Blame modules/amd_parse.y

Packit 8480eb
%{
Packit 8480eb
/* ----------------------------------------------------------------------- *
Packit 8480eb
 *
Packit 8480eb
 *  Copyright 2013 Ian Kent <raven@themaw.net>
Packit 8480eb
 *  Copyright 2013 Red Hat, Inc.
Packit 8480eb
 *  All rights reserved.
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 <stdio.h>
Packit 8480eb
#include <string.h>
Packit 8480eb
#include <stdlib.h>
Packit 8480eb
#include <stdarg.h>
Packit 8480eb
#include <ctype.h>
Packit 8480eb
#include <sys/ioctl.h>
Packit 8480eb
#include <syslog.h>
Packit 8480eb
Packit 8480eb
#include "automount.h"
Packit 8480eb
#include "parse_amd.h"
Packit 8480eb
#include "log.h"
Packit 8480eb
Packit 8480eb
#define MAX_OPTS_LEN	1024
Packit 8480eb
#define MAX_ERR_LEN	3096
Packit 8480eb
Packit 8480eb
static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER;
Packit 8480eb
Packit 8480eb
extern FILE *amd_in;
Packit 8480eb
extern char *amd_text;
Packit 8480eb
extern int amd_lex(void);
Packit 8480eb
extern void amd_set_scan_buffer(const char *);
Packit 8480eb
Packit 8480eb
static char *amd_strdup(char *);
Packit 8480eb
static void amd_set_value(char **, char *);
Packit 8480eb
static void local_init_vars(void);
Packit 8480eb
static void local_free_vars(void);
Packit 8480eb
Packit 8480eb
static int amd_error(const char *s);
Packit 8480eb
static int amd_notify(const char *s);
Packit 8480eb
static int amd_info(const char *s);
Packit 8480eb
static int amd_msg(const char *s);
Packit 8480eb
Packit 8480eb
static int add_location(void);
Packit 8480eb
static int make_selector(char *name,
Packit 8480eb
			 char *value1, char *value2,
Packit 8480eb
			 unsigned int compare);
Packit 8480eb
static void add_selector(struct selector *selector);
Packit 8480eb
Packit 8480eb
static int match_map_option_fs_type(char *map_option, char *type);
Packit 8480eb
static int match_map_option_map_type(char *map_option, char *type);
Packit 8480eb
static int match_map_option_cache_option(char *type);
Packit 8480eb
static int match_mnt_option_options(char *mnt_option, char *options);
Packit 8480eb
Packit 8480eb
static struct amd_entry entry;
Packit 8480eb
static struct list_head *entries;
Packit 8480eb
static struct autofs_point *pap;
Packit 8480eb
struct substvar *psv;
Packit 8480eb
static char opts[MAX_OPTS_LEN];
Packit 8480eb
static void prepend_opt(char *, char *);
Packit 8480eb
static char msg_buf[MAX_ERR_LEN];
Packit 8480eb
Packit 8480eb
#define YYDEBUG 0
Packit 8480eb
Packit 8480eb
#ifndef YYENABLE_NLS
Packit 8480eb
#define YYENABLE_NLS 0
Packit 8480eb
#endif
Packit 8480eb
#ifndef YYLTYPE_IS_TRIVIAL
Packit 8480eb
#define YYLTYPE_IS_TRIVIAL 0
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
#if YYDEBUG
Packit 8480eb
static int amd_fprintf(FILE *, char *, ...);
Packit 8480eb
#undef YYFPRINTF
Packit 8480eb
#define YYFPRINTF amd_fprintf
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
%}
Packit 8480eb
Packit 8480eb
%union {
Packit 8480eb
	char strtype[2048];
Packit 8480eb
	int inttype;
Packit 8480eb
	long longtype;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
%token COMMENT
Packit 8480eb
%token SEPERATOR
Packit 8480eb
%token SPACE
Packit 8480eb
%token HYPHEN
Packit 8480eb
%token IS_EQUAL
Packit 8480eb
%token CUT
Packit 8480eb
%token NOT_EQUAL
Packit 8480eb
%token COMMA
Packit 8480eb
%token QUOTE
Packit 8480eb
%token OPTION_ASSIGN
Packit 8480eb
%token LBRACKET
Packit 8480eb
%token RBRACKET
Packit 8480eb
%token NOT
Packit 8480eb
%token NILL
Packit 8480eb
Packit 8480eb
%token <strtype> MAP_OPTION
Packit 8480eb
%token <strtype> MAP_TYPE
Packit 8480eb
%token <strtype> CACHE_OPTION
Packit 8480eb
%token <strtype> FS_TYPE
Packit 8480eb
%token <strtype> FS_OPTION
Packit 8480eb
%token <strtype> FS_OPT_VALUE
Packit 8480eb
%token <strtype> MNT_OPTION
Packit 8480eb
%token <strtype> SELECTOR
Packit 8480eb
%token <strtype> SELECTOR_VALUE
Packit 8480eb
%token <strtype> SEL_ARG_VALUE
Packit 8480eb
%token <strtype> OPTION
Packit 8480eb
%token <strtype> MACRO
Packit 8480eb
%token <strtype> OTHER
Packit 8480eb
Packit 8480eb
%type <strtype> options
Packit 8480eb
Packit 8480eb
%start file
Packit 8480eb
Packit 8480eb
%%
Packit 8480eb
Packit 8480eb
file: {
Packit 8480eb
#if YYDEBUG != 0
Packit 8480eb
		amd_debug = YYDEBUG;
Packit 8480eb
#endif
Packit 8480eb
		memset(opts, 0, sizeof(opts));
Packit 8480eb
	} line
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
line:
Packit 8480eb
	| location_selection_list
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
location_selection_list: location
Packit 8480eb
	{
Packit 8480eb
		if (!add_location()) {
Packit 8480eb
			amd_msg("failed to allocate new location");
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| location_selection_list SPACE location
Packit 8480eb
	{
Packit 8480eb
		if (!add_location()) {
Packit 8480eb
			amd_msg("failed to allocate new location");
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| location_selection_list SPACE CUT SPACE location
Packit 8480eb
	{
Packit 8480eb
		entry.flags |= AMD_ENTRY_CUT;
Packit 8480eb
		if (!add_location()) {
Packit 8480eb
			amd_msg("failed to allocate new location");
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
location: location_entry
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	| HYPHEN location_entry
Packit 8480eb
	{
Packit 8480eb
		entry.flags |= AMD_DEFAULTS_MERGE;
Packit 8480eb
	}
Packit 8480eb
	| HYPHEN
Packit 8480eb
	{
Packit 8480eb
		entry.flags |= AMD_DEFAULTS_RESET;
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
location_entry: selector_or_option
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	| location_entry SEPERATOR selector_or_option
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	| location_entry SEPERATOR
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
selector_or_option: selection
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	| option_assignment
Packit 8480eb
	{
Packit 8480eb
	}
Packit 8480eb
	| OTHER
Packit 8480eb
	{
Packit 8480eb
		amd_notify($1);
Packit 8480eb
		YYABORT;
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
selection: SELECTOR IS_EQUAL SELECTOR_VALUE
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, $3, NULL, SEL_COMP_EQUAL)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| SELECTOR IS_EQUAL
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, "", NULL, SEL_COMP_EQUAL)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| SELECTOR NOT_EQUAL SELECTOR_VALUE
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, $3, NULL, SEL_COMP_NOTEQUAL)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| SELECTOR NOT_EQUAL
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, "", NULL, SEL_COMP_EQUAL)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, $3, NULL, SEL_COMP_NONE)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($1, $3, $5, SEL_COMP_NONE)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| NOT SELECTOR LBRACKET SEL_ARG_VALUE RBRACKET
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($2, $4, NULL, SEL_COMP_NOT)) {
Packit 8480eb
			amd_notify($2);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| NOT SELECTOR LBRACKET SEL_ARG_VALUE COMMA SEL_ARG_VALUE RBRACKET
Packit 8480eb
	{
Packit 8480eb
		if (!make_selector($2, $4, $6, SEL_COMP_NOT)) {
Packit 8480eb
			amd_notify($2);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
option_assignment: MAP_OPTION OPTION_ASSIGN FS_TYPE
Packit 8480eb
	{
Packit 8480eb
		if (!match_map_option_fs_type($1, $3))
Packit 8480eb
			YYABORT;
Packit 8480eb
	}
Packit 8480eb
	| MAP_OPTION OPTION_ASSIGN MAP_TYPE
Packit 8480eb
	{
Packit 8480eb
		if (!match_map_option_map_type($1, $3))
Packit 8480eb
			YYABORT;
Packit 8480eb
	}
Packit 8480eb
	| MAP_OPTION OPTION_ASSIGN FS_OPT_VALUE
Packit 8480eb
	{
Packit 8480eb
		/* Quoted value for type, maptype or cache assign */
Packit 8480eb
		if (!strcmp($1, "type")) {
Packit 8480eb
			if (!match_map_option_fs_type($1, $3))
Packit 8480eb
				YYABORT;
Packit 8480eb
		} else if (!strcmp($1, "maptype")) {
Packit 8480eb
			if (!match_map_option_map_type($1, $3))
Packit 8480eb
				YYABORT;
Packit 8480eb
		} else if (!strcmp($1, "cache")) {
Packit 8480eb
			if (!match_map_option_cache_option($3))
Packit 8480eb
				YYABORT;
Packit 8480eb
		} else {
Packit 8480eb
			char *fs_opt_val;
Packit 8480eb
Packit 8480eb
			fs_opt_val = amd_strdup($3);
Packit 8480eb
			if (!fs_opt_val) {
Packit 8480eb
				amd_notify($3);
Packit 8480eb
				YYABORT;
Packit 8480eb
			}
Packit 8480eb
Packit 8480eb
			if (!strcmp($1, "fs"))
Packit 8480eb
				amd_set_value(&entry.fs, fs_opt_val);
Packit 8480eb
			else if (!strcmp($1, "sublink")) {
Packit 8480eb
				amd_set_value(&entry.sublink, fs_opt_val);
Packit 8480eb
			} else if (!strcmp($1, "pref")) {
Packit 8480eb
				if (strcmp(fs_opt_val, "null"))
Packit 8480eb
					amd_set_value(&entry.pref, fs_opt_val);
Packit 8480eb
				else {
Packit 8480eb
					char *empty;
Packit 8480eb
Packit 8480eb
					empty = amd_strdup("");
Packit 8480eb
					if (!empty) {
Packit 8480eb
						amd_notify($3);
Packit 8480eb
						free(fs_opt_val);
Packit 8480eb
						YYABORT;
Packit 8480eb
					}
Packit 8480eb
					amd_set_value(&entry.pref, empty);
Packit 8480eb
					free(fs_opt_val);
Packit 8480eb
				}
Packit 8480eb
			} else {
Packit 8480eb
				amd_notify($1);
Packit 8480eb
				free(fs_opt_val);
Packit 8480eb
				YYABORT;
Packit 8480eb
			}
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| MAP_OPTION OPTION_ASSIGN
Packit 8480eb
	{
Packit 8480eb
		if (!strcmp($1, "fs")) {
Packit 8480eb
			char *empty;
Packit 8480eb
Packit 8480eb
			empty = amd_strdup("");
Packit 8480eb
			if (!empty) {
Packit 8480eb
				amd_notify($1);
Packit 8480eb
				YYABORT;
Packit 8480eb
			}
Packit 8480eb
			amd_set_value(&entry.fs, empty);
Packit 8480eb
		} else {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| FS_OPTION OPTION_ASSIGN FS_OPT_VALUE
Packit 8480eb
	{
Packit 8480eb
		char *fs_opt_val;
Packit 8480eb
Packit 8480eb
		fs_opt_val = amd_strdup($3);
Packit 8480eb
		if (!fs_opt_val) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (!strcmp($1, "rhost"))
Packit 8480eb
			amd_set_value(&entry.rhost, fs_opt_val);
Packit 8480eb
		else if (!strcmp($1, "rfs"))
Packit 8480eb
			amd_set_value(&entry.rfs, fs_opt_val);
Packit 8480eb
		else if (!strcmp($1, "dev"))
Packit 8480eb
			amd_set_value(&entry.dev, fs_opt_val);
Packit 8480eb
		else if (!strcmp($1, "mount"))
Packit 8480eb
			amd_set_value(&entry.mount, fs_opt_val);
Packit 8480eb
		else if (!strcmp($1, "unmount") ||
Packit 8480eb
			 !strcmp($1, "umount")) {
Packit 8480eb
			if (entry.umount) {
Packit 8480eb
				sprintf(msg_buf,
Packit 8480eb
				    "unmount or umount may only be used once");
Packit 8480eb
				amd_info(msg_buf);
Packit 8480eb
				free(fs_opt_val);
Packit 8480eb
				YYABORT;
Packit 8480eb
			}
Packit 8480eb
			entry.umount = fs_opt_val;
Packit 8480eb
		} else if (!strcmp($1, "delay") ||
Packit 8480eb
			   !strcmp($1, "cachedir")) {
Packit 8480eb
			sprintf(msg_buf, "option %s is not used by autofs", $1);
Packit 8480eb
			amd_info(msg_buf);
Packit 8480eb
			free(fs_opt_val);
Packit 8480eb
		} else {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			free(fs_opt_val);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| FS_OPTION OPTION_ASSIGN
Packit 8480eb
	{
Packit 8480eb
		char *empty;
Packit 8480eb
Packit 8480eb
		empty = amd_strdup("");
Packit 8480eb
		if (!empty) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		if (!strcmp($1, "rhost"))
Packit 8480eb
			amd_set_value(&entry.rhost, empty);
Packit 8480eb
		else if (!strcmp($1, "rfs"))
Packit 8480eb
			amd_set_value(&entry.rfs, empty);
Packit 8480eb
		else if (!strcmp($1, "dev"))
Packit 8480eb
			amd_set_value(&entry.dev, empty);
Packit 8480eb
		else if (!strcmp($1, "mount")) {
Packit 8480eb
			amd_set_value(&entry.mount, NULL);
Packit 8480eb
			free(empty);
Packit 8480eb
		} else if (!strcmp($1, "umount") ||
Packit 8480eb
			   !strcmp($1, "unmount")) {
Packit 8480eb
			amd_set_value(&entry.umount, NULL);
Packit 8480eb
			free(empty);
Packit 8480eb
		} else {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			free(empty);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| MNT_OPTION OPTION_ASSIGN options
Packit 8480eb
	{
Packit Service 42268b
		if (!match_mnt_option_options($1, $3)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
		memset(opts, 0, sizeof(opts));
Packit 8480eb
	}
Packit 8480eb
	| MNT_OPTION OPTION_ASSIGN QUOTE options QUOTE
Packit 8480eb
	{
Packit Service 42268b
		if (!match_mnt_option_options($1, $4)) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
		memset(opts, 0, sizeof(opts));
Packit 8480eb
	}
Packit 8480eb
	| MNT_OPTION OPTION_ASSIGN
Packit 8480eb
	{
Packit 8480eb
		memset(opts, 0, sizeof(opts));
Packit 8480eb
		if (!match_mnt_option_options($1, "")) {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	| MAP_OPTION OPTION_ASSIGN CACHE_OPTION
Packit 8480eb
	{
Packit 8480eb
		if (!strcmp($1, "cache")) {
Packit 8480eb
			if (!match_map_option_cache_option($3))
Packit 8480eb
				YYABORT;
Packit 8480eb
		} else {
Packit 8480eb
			amd_notify($1);
Packit 8480eb
			YYABORT;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
options: OPTION
Packit 8480eb
	{
Packit 8480eb
		if (!strcmp($1, "fullybrowsable") ||
Packit 8480eb
		    !strcmp($1, "nounmount")) {
Packit 8480eb
			sprintf(msg_buf, "option %s is not currently "
Packit 8480eb
					 "implemented, ignored", $1);
Packit 8480eb
			amd_info(msg_buf);
Packit 8480eb
		} else if (!strncmp($1, "ping=", 5) ||
Packit 8480eb
			   !strncmp($1, "retry=", 6) ||
Packit 8480eb
			   !strcmp($1, "public") ||
Packit 8480eb
			   !strcmp($1, "softlookup") ||
Packit 8480eb
			   !strcmp($1, "xlatecookie")) {
Packit 8480eb
			sprintf(msg_buf, "option %s is not used by "
Packit 8480eb
					 "autofs, ignored", $1);
Packit 8480eb
			amd_info(msg_buf);
Packit 8480eb
		} else if (!strncmp($1, "utimeout=", 9)) {
Packit 8480eb
			if (entry.flags & AMD_MOUNT_TYPE_AUTO) {
Packit 8480eb
				char *opt = $1;
Packit 8480eb
				prepend_opt(opts, ++opt);
Packit 8480eb
			} else {
Packit 8480eb
				sprintf(msg_buf, "umount timeout can't be "
Packit 8480eb
						 "used for other than type "
Packit 8480eb
						 "\"auto\" with autofs, "
Packit 8480eb
						 "ignored");
Packit 8480eb
				amd_info(msg_buf);
Packit 8480eb
			}
Packit 8480eb
		} else
Packit 8480eb
			prepend_opt(opts, $1);
Packit 8480eb
	}
Packit 8480eb
	| OPTION COMMA options
Packit 8480eb
	{
Packit 8480eb
		prepend_opt(opts, $1);
Packit 8480eb
	}
Packit 8480eb
	| OPTION COMMA
Packit 8480eb
	{
Packit 8480eb
		prepend_opt(opts, $1);
Packit 8480eb
	}
Packit 8480eb
	;
Packit 8480eb
Packit 8480eb
%%
Packit 8480eb
Packit 8480eb
static int match_map_option_fs_type(char *map_option, char *type)
Packit 8480eb
{
Packit 8480eb
	char *fs_type;
Packit 8480eb
Packit 8480eb
	fs_type = amd_strdup(type);
Packit 8480eb
	if (!fs_type) {
Packit 8480eb
		amd_notify(type);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!strcmp(fs_type, "auto"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_AUTO;
Packit 8480eb
	else if (!strcmp(fs_type, "nfs") ||
Packit 8480eb
		 !strcmp(fs_type, "nfs4"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_NFS;
Packit 8480eb
	else if (!strcmp(fs_type, "nfsl"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_NFSL;
Packit 8480eb
	else if (!strcmp(fs_type, "link"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_LINK;
Packit 8480eb
	else if (!strcmp(fs_type, "linkx"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_LINKX;
Packit 8480eb
	else if (!strcmp(fs_type, "host"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_HOST;
Packit 8480eb
	else if (!strcmp(fs_type, "lofs"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_LOFS;
Packit 8480eb
	else if (!strcmp(fs_type, "xfs"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_XFS;
Packit 8480eb
	else if (!strcmp(fs_type, "ext2") ||
Packit 8480eb
		   !strcmp(fs_type, "ext3") ||
Packit 8480eb
		   !strcmp(fs_type, "ext4"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_EXT;
Packit 8480eb
	else if (!strcmp(fs_type, "program"))
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_PROGRAM;
Packit 8480eb
	else if (!strcmp(fs_type, "ufs")) {
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_UFS;
Packit 8480eb
		entry.type = conf_amd_get_linux_ufs_mount_type();
Packit 8480eb
		if (!entry.type) {
Packit 8480eb
			amd_msg("memory allocation error");
Packit 8480eb
			amd_notify(type);
Packit 8480eb
			free(fs_type);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
		free(fs_type);
Packit 8480eb
		fs_type = NULL;
Packit 8480eb
	} else if (!strcmp(fs_type, "cdfs")) {
Packit 8480eb
		entry.flags |= AMD_MOUNT_TYPE_CDFS;
Packit 8480eb
		entry.type = amd_strdup("iso9660");
Packit 8480eb
		if (!entry.type) {
Packit 8480eb
			amd_msg("memory allocation error");
Packit 8480eb
			amd_notify(map_option);
Packit 8480eb
			free(fs_type);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
		free(fs_type);
Packit 8480eb
		fs_type = NULL;
Packit 8480eb
	} else if (!strcmp(fs_type, "jfs") ||
Packit 8480eb
		   !strcmp(fs_type, "nfsx") ||
Packit 8480eb
		   !strcmp(fs_type, "lustre") ||
Packit 8480eb
		   !strcmp(fs_type, "direct")) {
Packit 8480eb
		sprintf(msg_buf, "file system type %s is "
Packit 8480eb
				 "not yet implemented", fs_type);
Packit 8480eb
		amd_msg(msg_buf);
Packit 8480eb
		free(fs_type);
Packit 8480eb
		return 0;
Packit 8480eb
	} else if (!strcmp(fs_type, "cachefs")) {
Packit 8480eb
		sprintf(msg_buf, "file system %s is not "
Packit 8480eb
				 "supported by autofs, ignored",
Packit 8480eb
				 fs_type);
Packit 8480eb
		amd_msg(msg_buf);
Packit 8480eb
		free(fs_type);
Packit 8480eb
		fs_type = NULL;
Packit 8480eb
	} else {
Packit 8480eb
		amd_notify(fs_type);
Packit 8480eb
		free(fs_type);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (fs_type)
Packit 8480eb
		amd_set_value(&entry.type, fs_type);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_map_option_map_type(char *map_option, char *type)
Packit 8480eb
{
Packit 8480eb
	char *map_type;
Packit 8480eb
Packit 8480eb
	map_type = amd_strdup(type);
Packit 8480eb
	if (!map_type) {
Packit 8480eb
		amd_notify(type);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (!strcmp(map_type, "file") ||
Packit 8480eb
	    !strcmp(map_type, "nis") ||
Packit 8480eb
	    !strcmp(map_type, "nisplus") ||
Packit 8480eb
	    !strcmp(map_type, "ldap") ||
Packit 8480eb
	    !strcmp(map_type, "hesiod")) {
Packit 8480eb
		amd_set_value(&entry.map_type, map_type);
Packit 8480eb
	} else if (!strcmp(map_type, "exec")) {
Packit 8480eb
		/* autofs uses "program" for "exec" map type */
Packit 8480eb
		char * tmp;
Packit 8480eb
Packit 8480eb
		tmp = amd_strdup("program");
Packit 8480eb
		if (!tmp) {
Packit 8480eb
			amd_notify(type);
Packit 8480eb
			free(map_type);
Packit 8480eb
			return 0;
Packit 8480eb
		}
Packit 8480eb
		amd_set_value(&entry.map_type, tmp);
Packit 8480eb
		free(map_type);
Packit 8480eb
	} else if (!strcmp(map_type, "passwd")) {
Packit 8480eb
		sprintf(msg_buf, "map type %s is "
Packit 8480eb
				 "not yet implemented", map_type);
Packit 8480eb
		amd_msg(msg_buf);
Packit 8480eb
		free(map_type);
Packit 8480eb
		return 0;
Packit 8480eb
	} else if (!strcmp(map_type, "ndbm") ||
Packit 8480eb
		   !strcmp(map_type, "union")) {
Packit 8480eb
		sprintf(msg_buf, "map type %s is not "
Packit 8480eb
				 "supported by autofs", map_type);
Packit 8480eb
		amd_msg(msg_buf);
Packit 8480eb
		free(map_type);
Packit 8480eb
		return 0;
Packit 8480eb
	} else {
Packit 8480eb
		amd_notify(type);
Packit 8480eb
		free(map_type);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_map_option_cache_option(char *type)
Packit 8480eb
{
Packit 8480eb
	char *cache_opt;
Packit 8480eb
Packit 8480eb
	cache_opt = amd_strdup(type);
Packit 8480eb
	if (!cache_opt) {
Packit 8480eb
		amd_notify(type);
Packit 8480eb
		return 0;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	if (strncmp(cache_opt, "inc", 3))
Packit 8480eb
		entry.cache_opts = AMD_CACHE_OPTION_INC;
Packit 8480eb
	else if (strncmp(cache_opt, "all", 3))
Packit 8480eb
		entry.cache_opts = AMD_CACHE_OPTION_ALL;
Packit 8480eb
	else if (strncmp(cache_opt, "re", 2))
Packit 8480eb
		entry.cache_opts = AMD_CACHE_OPTION_REGEXP;
Packit 8480eb
	if (strstr(cache_opt, "sync"))
Packit 8480eb
		entry.cache_opts |= AMD_CACHE_OPTION_SYNC;
Packit 8480eb
	free(cache_opt);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int match_mnt_option_options(char *mnt_option, char *options)
Packit 8480eb
{
Packit 8480eb
	char *tmp;
Packit 8480eb
Packit 8480eb
	if (!strcmp(mnt_option, "opts")) {
Packit 8480eb
		tmp = amd_strdup(options);
Packit 8480eb
		if (!tmp)
Packit 8480eb
			return 0;
Packit 8480eb
		amd_set_value(&entry.opts, tmp);
Packit 8480eb
	} else if (!strcmp(mnt_option, "addopts")) {
Packit 8480eb
		tmp = amd_strdup(options);
Packit 8480eb
		if (!tmp)
Packit 8480eb
			return 0;
Packit 8480eb
		amd_set_value(&entry.addopts, tmp);
Packit 8480eb
	} else if (!strcmp(mnt_option, "remopts")) {
Packit 8480eb
		tmp = amd_strdup(options);
Packit 8480eb
		if (!tmp)
Packit 8480eb
			return 0;
Packit 8480eb
		amd_set_value(&entry.remopts, tmp);
Packit 8480eb
	} else
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void prepend_opt(char *dest, char *opt)
Packit 8480eb
{
Packit 8480eb
	char new[MAX_OPTS_LEN];
Packit 8480eb
	strcpy(new, opt);
Packit 8480eb
	if (*dest != '\0') {
Packit 8480eb
		strcat(new, ",");
Packit 8480eb
		strcat(new, dest);
Packit 8480eb
	}
Packit 8480eb
	memmove(dest, new, strlen(new));
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
#if YYDEBUG
Packit 8480eb
static int amd_fprintf(FILE *f, char *msg, ...)
Packit 8480eb
{
Packit 8480eb
	va_list ap;
Packit 8480eb
	va_start(ap, msg);
Packit 8480eb
	vsyslog(LOG_DEBUG, msg, ap);
Packit 8480eb
	va_end(ap);
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
#endif
Packit 8480eb
Packit 8480eb
static char *amd_strdup(char *str)
Packit 8480eb
{
Packit 8480eb
	unsigned int quoted, len;
Packit 8480eb
	char *tmp;
Packit 8480eb
Packit 8480eb
	len = strlen(str);
Packit 8480eb
	quoted = 0;
Packit 8480eb
Packit 8480eb
	if (*str == '"') {
Packit 8480eb
		quoted = 1;
Packit 8480eb
		len -= 2;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	tmp = strdup(str + quoted);
Packit 8480eb
	if (!tmp) {
Packit 8480eb
		amd_msg("memory allocation error");
Packit 8480eb
		return NULL;
Packit 8480eb
	} else {
Packit 8480eb
		unsigned int squote;
Packit 8480eb
		char *ptr;
Packit 8480eb
Packit 8480eb
		if (quoted) {
Packit 8480eb
			if (tmp[len] != '"') {
Packit 8480eb
				sprintf(msg_buf,
Packit 8480eb
					"unmatched double quote near: %s", str);
Packit 8480eb
				amd_info(msg_buf);
Packit 8480eb
				free(tmp);
Packit 8480eb
				return NULL;
Packit 8480eb
			}
Packit 8480eb
			tmp[len] = 0;
Packit 8480eb
		}
Packit 8480eb
Packit 8480eb
		/* Check for matching single quotes */
Packit 8480eb
		if (!strchr(tmp, 39))
Packit 8480eb
			goto done;
Packit 8480eb
Packit 8480eb
		ptr = tmp;
Packit 8480eb
		squote = 0;
Packit 8480eb
		while (*ptr) {
Packit 8480eb
			if (*ptr == 39)
Packit 8480eb
				squote = !squote;
Packit 8480eb
			ptr++;
Packit 8480eb
		}
Packit 8480eb
		if (squote) {
Packit 8480eb
			sprintf(msg_buf,
Packit 8480eb
				"unmatched single quote near: %s", str);
Packit 8480eb
			amd_info(msg_buf);
Packit 8480eb
			free(tmp);
Packit 8480eb
			return NULL;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
done:
Packit 8480eb
	return tmp;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void amd_set_value(char **field, char *value)
Packit 8480eb
{
Packit 8480eb
	if (*field)
Packit 8480eb
		free(*field);
Packit 8480eb
	*field = value;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int amd_error(const char *s)
Packit 8480eb
{
Packit 8480eb
	if (strcmp(s, "syntax"))
Packit 8480eb
		logmsg("syntax error in location near [ %s ]\n", amd_text);
Packit 8480eb
	else
Packit 8480eb
		logmsg("%s while parsing location.\n", s);
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int amd_notify(const char *s)
Packit 8480eb
{
Packit 8480eb
	logmsg("syntax error in location near [ %s ]\n", s);
Packit 8480eb
	return(0);
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int amd_info(const char *s)
Packit 8480eb
{
Packit 8480eb
	info(pap->logopt, "%s\n", s);
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int amd_msg(const char *s)
Packit 8480eb
{
Packit 8480eb
	logmsg("%s\n", s);
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void local_init_vars(void)
Packit 8480eb
{
Packit 8480eb
	memset(&entry, 0, sizeof(entry));
Packit 8480eb
	entry.cache_opts = AMD_CACHE_OPTION_NONE;
Packit 8480eb
	memset(opts, 0, sizeof(opts));
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void local_free_vars(void)
Packit 8480eb
{
Packit 8480eb
	clear_amd_entry(&entry);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void add_selector(struct selector *selector)
Packit 8480eb
{
Packit 8480eb
	struct selector *s = entry.selector;
Packit 8480eb
Packit 8480eb
	if (!s) {
Packit 8480eb
		entry.selector = selector;
Packit 8480eb
		return;
Packit 8480eb
	}
Packit 8480eb
Packit 8480eb
	while (s->next)
Packit 8480eb
		s = s->next;
Packit 8480eb
Packit 8480eb
	selector->next = s;
Packit 8480eb
	entry.selector = selector;
Packit 8480eb
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int make_selector(char *name,
Packit 8480eb
			 char *value1, char *value2,
Packit 8480eb
			 unsigned int compare)
Packit 8480eb
{
Packit 8480eb
	struct selector *s;
Packit 8480eb
	char *tmp;
Packit 8480eb
Packit 8480eb
	if (!sel_lookup(name))
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	s = get_selector(name);
Packit 8480eb
	if (!s)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	if (s->sel->flags & SEL_FLAG_MACRO) {
Packit 8480eb
		tmp = amd_strdup(value1);
Packit 8480eb
		if (!tmp)
Packit 8480eb
			goto error;
Packit 8480eb
		s->comp.value = tmp;
Packit 8480eb
	} else if (s->sel->flags & SEL_FLAG_FUNC1) {
Packit 8480eb
		if (!value1)
Packit 8480eb
			tmp = NULL;
Packit 8480eb
		else {
Packit Service 0f11ce
			tmp = amd_strdup(value1);
Packit 8480eb
			if (!tmp)
Packit 8480eb
				goto error;
Packit 8480eb
		}
Packit 8480eb
		s->func.arg1 = tmp;
Packit 8480eb
	} else if (s->sel->flags & SEL_FLAG_FUNC2) {
Packit Service 0f11ce
		tmp = amd_strdup(value1);
Packit 8480eb
		if (!tmp)
Packit 8480eb
			goto error;
Packit 8480eb
		s->func.arg1 = tmp;
Packit 8480eb
		if (value2) {
Packit 8480eb
			tmp = amd_strdup(value2);
Packit 8480eb
			if (tmp)
Packit 8480eb
				s->func.arg2 = tmp;
Packit 8480eb
		}
Packit 8480eb
	}
Packit 8480eb
	s->compare = compare;
Packit 8480eb
Packit 8480eb
	add_selector(s);
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
error:
Packit 8480eb
	free_selector(s);
Packit 8480eb
	return 0;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
void amd_init_scan(void)
Packit 8480eb
{
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void parse_mutex_lock(void)
Packit 8480eb
{
Packit 8480eb
	int status = pthread_mutex_lock(&parse_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static void parse_mutex_unlock(void *arg)
Packit 8480eb
{
Packit 8480eb
	int status = pthread_mutex_unlock(&parse_mutex);
Packit 8480eb
	if (status)
Packit 8480eb
		fatal(status);
Packit 8480eb
	return;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
static int add_location(void)
Packit 8480eb
{
Packit 8480eb
	struct amd_entry *new;
Packit 8480eb
Packit 8480eb
	new = new_amd_entry(psv);
Packit 8480eb
	if (!new)
Packit 8480eb
		return 0;
Packit 8480eb
Packit 8480eb
	if (entry.path) {
Packit 8480eb
		free(new->path);
Packit 8480eb
		new->path = entry.path;
Packit 8480eb
	}
Packit 8480eb
	new->flags = entry.flags;
Packit 8480eb
	new->type = entry.type;
Packit 8480eb
	new->map_type = entry.map_type;
Packit 8480eb
	new->pref = entry.pref;
Packit 8480eb
	new->fs = entry.fs;
Packit 8480eb
	new->rhost = entry.rhost;
Packit 8480eb
	new->rfs = entry.rfs;
Packit 8480eb
	new->dev = entry.dev;
Packit 8480eb
	new->opts = entry.opts;
Packit 8480eb
	new->addopts = entry.addopts;
Packit 8480eb
	new->remopts = entry.remopts;
Packit 8480eb
	new->sublink = entry.sublink;
Packit 8480eb
	new->mount = entry.mount;
Packit 8480eb
	new->umount = entry.umount;
Packit 8480eb
	new->selector = entry.selector;
Packit 8480eb
	list_add_tail(&new->list, entries);
Packit 8480eb
	memset(&entry, 0, sizeof(struct amd_entry));
Packit 8480eb
Packit 8480eb
	return 1;
Packit 8480eb
}
Packit 8480eb
Packit 8480eb
int amd_parse_list(struct autofs_point *ap,
Packit 8480eb
		   const char *buffer, struct list_head *list,
Packit 8480eb
		   struct substvar **sv)
Packit 8480eb
{
Packit 8480eb
	char *buf;
Packit 8480eb
	size_t len;
Packit 8480eb
	int ret;
Packit 8480eb
Packit 8480eb
	len = strlen(buffer) + 2;
Packit 8480eb
	buf = malloc(len);
Packit 8480eb
	if (!buf)
Packit 8480eb
		return 0;
Packit 8480eb
	strcpy(buf, buffer);
Packit 8480eb
Packit 8480eb
	parse_mutex_lock();
Packit 8480eb
	pthread_cleanup_push(parse_mutex_unlock, NULL);
Packit 8480eb
Packit 8480eb
	pap = ap;
Packit 8480eb
	psv = *sv;
Packit 8480eb
	entries = list;
Packit 8480eb
	amd_set_scan_buffer(buf);
Packit 8480eb
Packit 8480eb
	local_init_vars();
Packit 8480eb
	ret = amd_parse();
Packit 8480eb
	local_free_vars();
Packit 8480eb
	*sv = psv;
Packit 8480eb
Packit 8480eb
	pthread_cleanup_pop(1);
Packit 8480eb
	free(buf);
Packit 8480eb
Packit 8480eb
	return ret;
Packit 8480eb
}