%{
/* ----------------------------------------------------------------------- *
*
* nss_parser.y - nsswitch parser.
*
* Copyright 2006 Ian Kent <raven@themaw.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
* USA; either version 2 of the License, or (at your option) any later
* version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ----------------------------------------------------------------------- */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <limits.h>
#include "automount.h"
#include "nsswitch.h"
#include "nss_parse.tab.h"
static pthread_mutex_t parse_mutex = PTHREAD_MUTEX_INITIALIZER;
static struct list_head *nss_list;
static struct nss_source *src;
struct nss_action act[NSS_STATUS_MAX];
#define YYDEBUG 0
#ifndef YYENABLE_NLS
#define YYENABLE_NLS 0
#endif
#ifndef YYLTYPE_IS_TRIVIAL
#define YYLTYPE_IS_TRIVIAL 0
#endif
unsigned int nss_automount_found;
extern int nss_lineno;
extern int nss_lex(void);
extern FILE *nss_in;
static int nss_ignore(const char *s);
static int nss_error(const char *s);
%}
%union {
char strval[128];
}
%token LBRACKET RBRACKET EQUAL BANG NL
%token <strval> SOURCE
%token <strval> STATUS
%token <strval> ACTION
%start file
%%
file: {
#if YYDEBUG != 0
nss_debug = YYDEBUG;
#endif
} sources NL
| /* empty */
;
sources: nss_source
| nss_source sources
;
nss_source: SOURCE
{
if (!strcmp($1, "files") || !strcmp($1, "yp") ||
!strcmp($1, "nis") || !strcmp($1, "ldap") ||
!strcmp($1, "nisplus") || !strcmp($1, "hesiod") ||
!strcmp($1, "sss"))
src = add_source(nss_list, $1);
else
nss_ignore($1);
} | SOURCE LBRACKET status_exp_list RBRACKET
{
enum nsswitch_status a;
if (!strcmp($1, "files") || !strcmp($1, "yp") ||
!strcmp($1, "nis") || !strcmp($1, "ldap") ||
!strcmp($1, "nisplus") || !strcmp($1, "hesiod") ||
!strcmp($1, "sss")) {
src = add_source(nss_list, $1);
for (a = 0; a < NSS_STATUS_MAX; a++) {
if (act[a].action != NSS_ACTION_UNKNOWN) {
src->action[a].action = act[a].action;
src->action[a].negated = act[a].negated;
}
}
} else
nss_ignore($1);
} | SOURCE LBRACKET status_exp_list SOURCE { nss_error("missing close bracket"); YYABORT; }
| SOURCE LBRACKET status_exp_list NL { nss_error("missing close bracket"); YYABORT; }
| SOURCE LBRACKET SOURCE { nss_error($3); YYABORT; }
| error SOURCE { nss_error($2); YYABORT; };
status_exp_list: status_exp
| status_exp status_exp_list
status_exp: STATUS EQUAL ACTION
{
set_action(act, $1, $3, 0);
} | BANG STATUS EQUAL ACTION
{
set_action(act, $2, $4, 1);
} | STATUS EQUAL SOURCE {nss_error($3); YYABORT; }
| STATUS SOURCE {nss_error($2); YYABORT; }
| BANG STATUS EQUAL SOURCE {nss_error($4); YYABORT; }
| BANG STATUS SOURCE {nss_error($3); YYABORT; }
| BANG SOURCE {nss_error($2); YYABORT; };
%%
static int nss_ignore(const char *s)
{
logmsg("ignored unsupported autofs nsswitch source \"%s\"", s);
return(0);
}
static int nss_error(const char *s)
{
logmsg("syntax error in nsswitch config near [ %s ]\n", s);
return(0);
}
static void parse_mutex_lock(void)
{
int status = pthread_mutex_lock(&parse_mutex);
if (status)
fatal(status);
return;
}
static void parse_mutex_unlock(void *arg)
{
int status = pthread_mutex_unlock(&parse_mutex);
if (status)
fatal(status);
return;
}
static void parse_close_nsswitch(void *arg)
{
FILE *nsswitch = (FILE *) arg;
fclose(nsswitch);
return;
}
int nsswitch_parse(struct list_head *list)
{
FILE *nsswitch;
int status;
nsswitch = open_fopen_r(NSSWITCH_FILE);
if (!nsswitch) {
logerr("couldn't open %s", NSSWITCH_FILE);
return 1;
}
pthread_cleanup_push(parse_close_nsswitch, nsswitch);
parse_mutex_lock();
pthread_cleanup_push(parse_mutex_unlock, NULL);
nss_in = nsswitch;
nss_automount_found = 0;
nss_list = list;
status = nss_parse();
nss_list = NULL;
/* No "automount" nsswitch entry, use "files" */
if (!nss_automount_found)
if (add_source(list, "files"))
status = 0;
pthread_cleanup_pop(1);
pthread_cleanup_pop(1);
if (status)
return 1;
return 0;
}