19e7c127fSCraig Rodrigues /* $OpenBSD: parse.y,v 1.18 2015/01/16 06:40:22 deraadt Exp $ */
29e7c127fSCraig Rodrigues
39e7c127fSCraig Rodrigues /*
49e7c127fSCraig Rodrigues * Copyright (c) 2008 Pierre-Yves Ritschard <pyr@openbsd.org>
59e7c127fSCraig Rodrigues * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
69e7c127fSCraig Rodrigues * Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
79e7c127fSCraig Rodrigues * Copyright (c) 2004 Ryan McBride <mcbride@openbsd.org>
89e7c127fSCraig Rodrigues * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org>
99e7c127fSCraig Rodrigues * Copyright (c) 2001 Markus Friedl. All rights reserved.
109e7c127fSCraig Rodrigues * Copyright (c) 2001 Daniel Hartmeier. All rights reserved.
119e7c127fSCraig Rodrigues * Copyright (c) 2001 Theo de Raadt. All rights reserved.
129e7c127fSCraig Rodrigues *
139e7c127fSCraig Rodrigues * Permission to use, copy, modify, and distribute this software for any
149e7c127fSCraig Rodrigues * purpose with or without fee is hereby granted, provided that the above
159e7c127fSCraig Rodrigues * copyright notice and this permission notice appear in all copies.
169e7c127fSCraig Rodrigues *
179e7c127fSCraig Rodrigues * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
189e7c127fSCraig Rodrigues * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
199e7c127fSCraig Rodrigues * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
209e7c127fSCraig Rodrigues * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
219e7c127fSCraig Rodrigues * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
229e7c127fSCraig Rodrigues * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
239e7c127fSCraig Rodrigues * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
249e7c127fSCraig Rodrigues */
259e7c127fSCraig Rodrigues
269e7c127fSCraig Rodrigues %{
279e7c127fSCraig Rodrigues #include <sys/types.h>
2866b5c05dSCraig Rodrigues #include <sys/param.h>
299e7c127fSCraig Rodrigues #include <sys/time.h>
309e7c127fSCraig Rodrigues #include <sys/queue.h>
319e7c127fSCraig Rodrigues #include <sys/tree.h>
329e7c127fSCraig Rodrigues #include <sys/socket.h>
339e7c127fSCraig Rodrigues #include <sys/stat.h>
349e7c127fSCraig Rodrigues
359e7c127fSCraig Rodrigues #include <netinet/in.h>
369e7c127fSCraig Rodrigues #include <arpa/inet.h>
379e7c127fSCraig Rodrigues
389e7c127fSCraig Rodrigues #include <ctype.h>
399e7c127fSCraig Rodrigues #include <err.h>
409e7c127fSCraig Rodrigues #include <errno.h>
419e7c127fSCraig Rodrigues #include <event.h>
429e7c127fSCraig Rodrigues #include <fcntl.h>
439e7c127fSCraig Rodrigues #include <limits.h>
449e7c127fSCraig Rodrigues #include <netdb.h>
459e7c127fSCraig Rodrigues #include <pwd.h>
469e7c127fSCraig Rodrigues #include <stdarg.h>
479e7c127fSCraig Rodrigues #include <stdio.h>
489e7c127fSCraig Rodrigues #include <stdlib.h>
499e7c127fSCraig Rodrigues #include <string.h>
509e7c127fSCraig Rodrigues #include <syslog.h>
519e7c127fSCraig Rodrigues #include <unistd.h>
529e7c127fSCraig Rodrigues
539e7c127fSCraig Rodrigues #include "ypldap.h"
549e7c127fSCraig Rodrigues
559e7c127fSCraig Rodrigues TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files);
569e7c127fSCraig Rodrigues static struct file {
579e7c127fSCraig Rodrigues TAILQ_ENTRY(file) entry;
589e7c127fSCraig Rodrigues FILE *stream;
599e7c127fSCraig Rodrigues char *name;
609e7c127fSCraig Rodrigues int lineno;
619e7c127fSCraig Rodrigues int errors;
629e7c127fSCraig Rodrigues } *file, *topfile;
639e7c127fSCraig Rodrigues struct file *pushfile(const char *, int);
649e7c127fSCraig Rodrigues int popfile(void);
659e7c127fSCraig Rodrigues int check_file_secrecy(int, const char *);
669e7c127fSCraig Rodrigues int yyparse(void);
679e7c127fSCraig Rodrigues int yylex(void);
689e7c127fSCraig Rodrigues int yyerror(const char *, ...)
699e7c127fSCraig Rodrigues __attribute__((__format__ (printf, 1, 2)))
709e7c127fSCraig Rodrigues __attribute__((__nonnull__ (1)));
719e7c127fSCraig Rodrigues int kw_cmp(const void *, const void *);
729e7c127fSCraig Rodrigues int lookup(char *);
739e7c127fSCraig Rodrigues int lgetc(int);
749e7c127fSCraig Rodrigues int lungetc(int);
759e7c127fSCraig Rodrigues int findeol(void);
769e7c127fSCraig Rodrigues
779e7c127fSCraig Rodrigues TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead);
789e7c127fSCraig Rodrigues struct sym {
799e7c127fSCraig Rodrigues TAILQ_ENTRY(sym) entry;
809e7c127fSCraig Rodrigues int used;
819e7c127fSCraig Rodrigues int persist;
829e7c127fSCraig Rodrigues char *nam;
839e7c127fSCraig Rodrigues char *val;
849e7c127fSCraig Rodrigues };
859e7c127fSCraig Rodrigues int symset(const char *, const char *, int);
869e7c127fSCraig Rodrigues char *symget(const char *);
879e7c127fSCraig Rodrigues
889e7c127fSCraig Rodrigues struct env *conf = NULL;
899e7c127fSCraig Rodrigues struct idm *idm = NULL;
909e7c127fSCraig Rodrigues static int errors = 0;
919e7c127fSCraig Rodrigues
929e7c127fSCraig Rodrigues typedef struct {
939e7c127fSCraig Rodrigues union {
949e7c127fSCraig Rodrigues int64_t number;
959e7c127fSCraig Rodrigues char *string;
969e7c127fSCraig Rodrigues } v;
979e7c127fSCraig Rodrigues int lineno;
989e7c127fSCraig Rodrigues } YYSTYPE;
999e7c127fSCraig Rodrigues
1009e7c127fSCraig Rodrigues %}
1019e7c127fSCraig Rodrigues
1029e7c127fSCraig Rodrigues %token SERVER FILTER ATTRIBUTE BASEDN BINDDN GROUPDN BINDCRED MAPS CHANGE DOMAIN PROVIDE
1039e7c127fSCraig Rodrigues %token USER GROUP TO EXPIRE HOME SHELL GECOS UID GID INTERVAL
1049e7c127fSCraig Rodrigues %token PASSWD NAME FIXED LIST GROUPNAME GROUPPASSWD GROUPGID MAP
1059e7c127fSCraig Rodrigues %token INCLUDE DIRECTORY CLASS PORT ERROR GROUPMEMBERS
1069e7c127fSCraig Rodrigues %token <v.string> STRING
1079e7c127fSCraig Rodrigues %token <v.number> NUMBER
1089e7c127fSCraig Rodrigues %type <v.number> opcode attribute
1099e7c127fSCraig Rodrigues %type <v.string> port
1109e7c127fSCraig Rodrigues
1119e7c127fSCraig Rodrigues %%
1129e7c127fSCraig Rodrigues
1139e7c127fSCraig Rodrigues grammar : /* empty */
1149e7c127fSCraig Rodrigues | grammar '\n'
1159e7c127fSCraig Rodrigues | grammar include '\n'
1169e7c127fSCraig Rodrigues | grammar varset '\n'
1179e7c127fSCraig Rodrigues | grammar directory '\n'
1189e7c127fSCraig Rodrigues | grammar main '\n'
1199e7c127fSCraig Rodrigues | grammar error '\n' { file->errors++; }
1209e7c127fSCraig Rodrigues ;
1219e7c127fSCraig Rodrigues
1229e7c127fSCraig Rodrigues nl : '\n' optnl
1239e7c127fSCraig Rodrigues ;
1249e7c127fSCraig Rodrigues
1259e7c127fSCraig Rodrigues optnl : '\n' optnl
1269e7c127fSCraig Rodrigues | /* empty */
1279e7c127fSCraig Rodrigues ;
1289e7c127fSCraig Rodrigues
1299e7c127fSCraig Rodrigues
1309e7c127fSCraig Rodrigues include : INCLUDE STRING {
1319e7c127fSCraig Rodrigues struct file *nfile;
1329e7c127fSCraig Rodrigues
1339e7c127fSCraig Rodrigues if ((nfile = pushfile($2, 0)) == NULL) {
1349e7c127fSCraig Rodrigues yyerror("failed to include file %s", $2);
1359e7c127fSCraig Rodrigues free($2);
1369e7c127fSCraig Rodrigues YYERROR;
1379e7c127fSCraig Rodrigues }
1389e7c127fSCraig Rodrigues free($2);
1399e7c127fSCraig Rodrigues
1409e7c127fSCraig Rodrigues file = nfile;
1419e7c127fSCraig Rodrigues lungetc('\n');
1429e7c127fSCraig Rodrigues }
1439e7c127fSCraig Rodrigues ;
1449e7c127fSCraig Rodrigues
1459e7c127fSCraig Rodrigues varset : STRING '=' STRING {
146*391adcc5SMarcelo Araujo char *s = $1;
147*391adcc5SMarcelo Araujo while (*s++) {
148*391adcc5SMarcelo Araujo if (isspace((unsigned char) *s)) {
149*391adcc5SMarcelo Araujo yyerror("macro name cannot contain "
150*391adcc5SMarcelo Araujo "whitespace");
151*391adcc5SMarcelo Araujo YYERROR;
152*391adcc5SMarcelo Araujo }
153*391adcc5SMarcelo Araujo }
1549e7c127fSCraig Rodrigues if (symset($1, $3, 0) == -1)
1559e7c127fSCraig Rodrigues fatal("cannot store variable");
1569e7c127fSCraig Rodrigues free($1);
1579e7c127fSCraig Rodrigues free($3);
1589e7c127fSCraig Rodrigues }
1599e7c127fSCraig Rodrigues ;
1609e7c127fSCraig Rodrigues
1619e7c127fSCraig Rodrigues port : /* empty */ { $$ = NULL; }
1629e7c127fSCraig Rodrigues | PORT STRING { $$ = $2; }
1639e7c127fSCraig Rodrigues ;
1649e7c127fSCraig Rodrigues
1659e7c127fSCraig Rodrigues opcode : GROUP { $$ = 0; }
1669e7c127fSCraig Rodrigues | PASSWD { $$ = 1; }
1679e7c127fSCraig Rodrigues ;
1689e7c127fSCraig Rodrigues
1699e7c127fSCraig Rodrigues
1709e7c127fSCraig Rodrigues attribute : NAME { $$ = 0; }
1719e7c127fSCraig Rodrigues | PASSWD { $$ = 1; }
1729e7c127fSCraig Rodrigues | UID { $$ = 2; }
1739e7c127fSCraig Rodrigues | GID { $$ = 3; }
1749e7c127fSCraig Rodrigues | CLASS { $$ = 4; }
1759e7c127fSCraig Rodrigues | CHANGE { $$ = 5; }
1769e7c127fSCraig Rodrigues | EXPIRE { $$ = 6; }
1779e7c127fSCraig Rodrigues | GECOS { $$ = 7; }
1789e7c127fSCraig Rodrigues | HOME { $$ = 8; }
1799e7c127fSCraig Rodrigues | SHELL { $$ = 9; }
1809e7c127fSCraig Rodrigues | GROUPNAME { $$ = 10; }
1819e7c127fSCraig Rodrigues | GROUPPASSWD { $$ = 11; }
1829e7c127fSCraig Rodrigues | GROUPGID { $$ = 12; }
1839e7c127fSCraig Rodrigues | GROUPMEMBERS { $$ = 13; }
1849e7c127fSCraig Rodrigues ;
1859e7c127fSCraig Rodrigues
1869e7c127fSCraig Rodrigues diropt : BINDDN STRING {
1879e7c127fSCraig Rodrigues idm->idm_flags |= F_NEEDAUTH;
1889e7c127fSCraig Rodrigues if (strlcpy(idm->idm_binddn, $2,
1899e7c127fSCraig Rodrigues sizeof(idm->idm_binddn)) >=
1909e7c127fSCraig Rodrigues sizeof(idm->idm_binddn)) {
1919e7c127fSCraig Rodrigues yyerror("directory binddn truncated");
1929e7c127fSCraig Rodrigues free($2);
1939e7c127fSCraig Rodrigues YYERROR;
1949e7c127fSCraig Rodrigues }
1959e7c127fSCraig Rodrigues free($2);
1969e7c127fSCraig Rodrigues }
1979e7c127fSCraig Rodrigues | BINDCRED STRING {
1989e7c127fSCraig Rodrigues idm->idm_flags |= F_NEEDAUTH;
1999e7c127fSCraig Rodrigues if (strlcpy(idm->idm_bindcred, $2,
2009e7c127fSCraig Rodrigues sizeof(idm->idm_bindcred)) >=
2019e7c127fSCraig Rodrigues sizeof(idm->idm_bindcred)) {
2029e7c127fSCraig Rodrigues yyerror("directory bindcred truncated");
2039e7c127fSCraig Rodrigues free($2);
2049e7c127fSCraig Rodrigues YYERROR;
2059e7c127fSCraig Rodrigues }
2069e7c127fSCraig Rodrigues free($2);
2079e7c127fSCraig Rodrigues }
2089e7c127fSCraig Rodrigues | BASEDN STRING {
2099e7c127fSCraig Rodrigues if (strlcpy(idm->idm_basedn, $2,
2109e7c127fSCraig Rodrigues sizeof(idm->idm_basedn)) >=
2119e7c127fSCraig Rodrigues sizeof(idm->idm_basedn)) {
2129e7c127fSCraig Rodrigues yyerror("directory basedn truncated");
2139e7c127fSCraig Rodrigues free($2);
2149e7c127fSCraig Rodrigues YYERROR;
2159e7c127fSCraig Rodrigues }
2169e7c127fSCraig Rodrigues free($2);
2179e7c127fSCraig Rodrigues }
2189e7c127fSCraig Rodrigues | GROUPDN STRING {
2199e7c127fSCraig Rodrigues if(strlcpy(idm->idm_groupdn, $2,
2209e7c127fSCraig Rodrigues sizeof(idm->idm_groupdn)) >=
2219e7c127fSCraig Rodrigues sizeof(idm->idm_groupdn)) {
2229e7c127fSCraig Rodrigues yyerror("directory groupdn truncated");
2239e7c127fSCraig Rodrigues free($2);
2249e7c127fSCraig Rodrigues YYERROR;
2259e7c127fSCraig Rodrigues }
2269e7c127fSCraig Rodrigues free($2);
2279e7c127fSCraig Rodrigues }
2289e7c127fSCraig Rodrigues | opcode FILTER STRING {
2299e7c127fSCraig Rodrigues if (strlcpy(idm->idm_filters[$1], $3,
2309e7c127fSCraig Rodrigues sizeof(idm->idm_filters[$1])) >=
2319e7c127fSCraig Rodrigues sizeof(idm->idm_filters[$1])) {
2329e7c127fSCraig Rodrigues yyerror("filter truncated");
2339e7c127fSCraig Rodrigues free($3);
2349e7c127fSCraig Rodrigues YYERROR;
2359e7c127fSCraig Rodrigues }
2369e7c127fSCraig Rodrigues free($3);
2379e7c127fSCraig Rodrigues }
2389e7c127fSCraig Rodrigues | ATTRIBUTE attribute MAPS TO STRING {
2399e7c127fSCraig Rodrigues if (strlcpy(idm->idm_attrs[$2], $5,
2409e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$2])) >=
2419e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$2])) {
2429e7c127fSCraig Rodrigues yyerror("attribute truncated");
2439e7c127fSCraig Rodrigues free($5);
2449e7c127fSCraig Rodrigues YYERROR;
2459e7c127fSCraig Rodrigues }
2469e7c127fSCraig Rodrigues free($5);
2479e7c127fSCraig Rodrigues }
2489e7c127fSCraig Rodrigues | FIXED ATTRIBUTE attribute STRING {
2499e7c127fSCraig Rodrigues if (strlcpy(idm->idm_attrs[$3], $4,
2509e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$3])) >=
2519e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$3])) {
2529e7c127fSCraig Rodrigues yyerror("attribute truncated");
2539e7c127fSCraig Rodrigues free($4);
2549e7c127fSCraig Rodrigues YYERROR;
2559e7c127fSCraig Rodrigues }
2569e7c127fSCraig Rodrigues idm->idm_flags |= F_FIXED_ATTR($3);
2579e7c127fSCraig Rodrigues free($4);
2589e7c127fSCraig Rodrigues }
2599e7c127fSCraig Rodrigues | LIST attribute MAPS TO STRING {
2609e7c127fSCraig Rodrigues if (strlcpy(idm->idm_attrs[$2], $5,
2619e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$2])) >=
2629e7c127fSCraig Rodrigues sizeof(idm->idm_attrs[$2])) {
2639e7c127fSCraig Rodrigues yyerror("attribute truncated");
2649e7c127fSCraig Rodrigues free($5);
2659e7c127fSCraig Rodrigues YYERROR;
2669e7c127fSCraig Rodrigues }
2679e7c127fSCraig Rodrigues idm->idm_list |= F_LIST($2);
2689e7c127fSCraig Rodrigues free($5);
2699e7c127fSCraig Rodrigues }
2709e7c127fSCraig Rodrigues ;
2719e7c127fSCraig Rodrigues
2729e7c127fSCraig Rodrigues directory : DIRECTORY STRING port {
2739e7c127fSCraig Rodrigues if ((idm = calloc(1, sizeof(*idm))) == NULL)
2749e7c127fSCraig Rodrigues fatal(NULL);
2759e7c127fSCraig Rodrigues idm->idm_id = conf->sc_maxid++;
2769e7c127fSCraig Rodrigues
2779e7c127fSCraig Rodrigues if (strlcpy(idm->idm_name, $2,
2789e7c127fSCraig Rodrigues sizeof(idm->idm_name)) >=
2799e7c127fSCraig Rodrigues sizeof(idm->idm_name)) {
2809e7c127fSCraig Rodrigues yyerror("attribute truncated");
2819e7c127fSCraig Rodrigues free($2);
2829e7c127fSCraig Rodrigues YYERROR;
2839e7c127fSCraig Rodrigues }
2849e7c127fSCraig Rodrigues
2859e7c127fSCraig Rodrigues free($2);
2869e7c127fSCraig Rodrigues } '{' optnl diropts '}' {
2879e7c127fSCraig Rodrigues TAILQ_INSERT_TAIL(&conf->sc_idms, idm, idm_entry);
2889e7c127fSCraig Rodrigues idm = NULL;
2899e7c127fSCraig Rodrigues }
2909e7c127fSCraig Rodrigues ;
2919e7c127fSCraig Rodrigues
2929e7c127fSCraig Rodrigues main : INTERVAL NUMBER {
2939e7c127fSCraig Rodrigues conf->sc_conf_tv.tv_sec = $2;
2949e7c127fSCraig Rodrigues conf->sc_conf_tv.tv_usec = 0;
2959e7c127fSCraig Rodrigues }
2969e7c127fSCraig Rodrigues | DOMAIN STRING {
2979e7c127fSCraig Rodrigues if (strlcpy(conf->sc_domainname, $2,
2989e7c127fSCraig Rodrigues sizeof(conf->sc_domainname)) >=
2999e7c127fSCraig Rodrigues sizeof(conf->sc_domainname)) {
3009e7c127fSCraig Rodrigues yyerror("domainname truncated");
3019e7c127fSCraig Rodrigues free($2);
3029e7c127fSCraig Rodrigues YYERROR;
3039e7c127fSCraig Rodrigues }
3049e7c127fSCraig Rodrigues free($2);
3059e7c127fSCraig Rodrigues }
3069e7c127fSCraig Rodrigues | PROVIDE MAP STRING {
3079e7c127fSCraig Rodrigues if (strcmp($3, "passwd.byname") == 0)
3089e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_PASSWD_BYNAME;
3099e7c127fSCraig Rodrigues else if (strcmp($3, "passwd.byuid") == 0)
3109e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_PASSWD_BYUID;
3119e7c127fSCraig Rodrigues else if (strcmp($3, "master.passwd.byname") == 0)
3129e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_MASTER_PASSWD_BYNAME;
3139e7c127fSCraig Rodrigues else if (strcmp($3, "master.passwd.byuid") == 0)
3149e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_MASTER_PASSWD_BYUID;
3159e7c127fSCraig Rodrigues else if (strcmp($3, "group.byname") == 0)
3169e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_GROUP_BYNAME;
3179e7c127fSCraig Rodrigues else if (strcmp($3, "group.bygid") == 0)
3189e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_GROUP_BYGID;
3199e7c127fSCraig Rodrigues else if (strcmp($3, "netid.byname") == 0)
3209e7c127fSCraig Rodrigues conf->sc_flags |= YPMAP_NETID_BYNAME;
3219e7c127fSCraig Rodrigues else {
3229e7c127fSCraig Rodrigues yyerror("unsupported map type: %s", $3);
3239e7c127fSCraig Rodrigues free($3);
3249e7c127fSCraig Rodrigues YYERROR;
3259e7c127fSCraig Rodrigues }
3269e7c127fSCraig Rodrigues free($3);
3279e7c127fSCraig Rodrigues }
3289e7c127fSCraig Rodrigues ;
3299e7c127fSCraig Rodrigues
3309e7c127fSCraig Rodrigues diropts : diropts diropt nl
3319e7c127fSCraig Rodrigues | diropt optnl
3329e7c127fSCraig Rodrigues ;
3339e7c127fSCraig Rodrigues
3349e7c127fSCraig Rodrigues %%
3359e7c127fSCraig Rodrigues
3369e7c127fSCraig Rodrigues struct keywords {
3379e7c127fSCraig Rodrigues const char *k_name;
3389e7c127fSCraig Rodrigues int k_val;
3399e7c127fSCraig Rodrigues };
3409e7c127fSCraig Rodrigues
3419e7c127fSCraig Rodrigues int
yyerror(const char * fmt,...)3429e7c127fSCraig Rodrigues yyerror(const char *fmt, ...)
3439e7c127fSCraig Rodrigues {
3449e7c127fSCraig Rodrigues va_list ap;
3459e7c127fSCraig Rodrigues char *msg;
3469e7c127fSCraig Rodrigues
3479e7c127fSCraig Rodrigues file->errors++;
3489e7c127fSCraig Rodrigues va_start(ap, fmt);
3499e7c127fSCraig Rodrigues if (vasprintf(&msg, fmt, ap) == -1)
3509e7c127fSCraig Rodrigues fatalx("yyerror vasprintf");
3519e7c127fSCraig Rodrigues va_end(ap);
3529e7c127fSCraig Rodrigues logit(LOG_CRIT, "%s:%d: %s", file->name, yylval.lineno, msg);
3539e7c127fSCraig Rodrigues free(msg);
3549e7c127fSCraig Rodrigues return (0);
3559e7c127fSCraig Rodrigues }
3569e7c127fSCraig Rodrigues
3579e7c127fSCraig Rodrigues int
kw_cmp(const void * k,const void * e)3589e7c127fSCraig Rodrigues kw_cmp(const void *k, const void *e)
3599e7c127fSCraig Rodrigues {
3609e7c127fSCraig Rodrigues return (strcmp(k, ((const struct keywords *)e)->k_name));
3619e7c127fSCraig Rodrigues }
3629e7c127fSCraig Rodrigues
3639e7c127fSCraig Rodrigues int
lookup(char * s)3649e7c127fSCraig Rodrigues lookup(char *s)
3659e7c127fSCraig Rodrigues {
3669e7c127fSCraig Rodrigues /* this has to be sorted always */
3679e7c127fSCraig Rodrigues static const struct keywords keywords[] = {
3689e7c127fSCraig Rodrigues { "attribute", ATTRIBUTE },
3699e7c127fSCraig Rodrigues { "basedn", BASEDN },
3709e7c127fSCraig Rodrigues { "bindcred", BINDCRED },
3719e7c127fSCraig Rodrigues { "binddn", BINDDN },
3729e7c127fSCraig Rodrigues { "change", CHANGE },
3739e7c127fSCraig Rodrigues { "class", CLASS },
3749e7c127fSCraig Rodrigues { "directory", DIRECTORY },
3759e7c127fSCraig Rodrigues { "domain", DOMAIN },
3769e7c127fSCraig Rodrigues { "expire", EXPIRE },
3779e7c127fSCraig Rodrigues { "filter", FILTER },
3789e7c127fSCraig Rodrigues { "fixed", FIXED },
3799e7c127fSCraig Rodrigues { "gecos", GECOS },
3809e7c127fSCraig Rodrigues { "gid", GID },
3819e7c127fSCraig Rodrigues { "group", GROUP },
3829e7c127fSCraig Rodrigues { "groupdn", GROUPDN },
3839e7c127fSCraig Rodrigues { "groupgid", GROUPGID },
3849e7c127fSCraig Rodrigues { "groupmembers", GROUPMEMBERS },
3859e7c127fSCraig Rodrigues { "groupname", GROUPNAME },
3869e7c127fSCraig Rodrigues { "grouppasswd", GROUPPASSWD },
3879e7c127fSCraig Rodrigues { "home", HOME },
3889e7c127fSCraig Rodrigues { "include", INCLUDE },
3899e7c127fSCraig Rodrigues { "interval", INTERVAL },
3909e7c127fSCraig Rodrigues { "list", LIST },
3919e7c127fSCraig Rodrigues { "map", MAP },
3929e7c127fSCraig Rodrigues { "maps", MAPS },
3939e7c127fSCraig Rodrigues { "name", NAME },
3949e7c127fSCraig Rodrigues { "passwd", PASSWD },
3959e7c127fSCraig Rodrigues { "port", PORT },
3969e7c127fSCraig Rodrigues { "provide", PROVIDE },
3979e7c127fSCraig Rodrigues { "server", SERVER },
3989e7c127fSCraig Rodrigues { "shell", SHELL },
3999e7c127fSCraig Rodrigues { "to", TO },
4009e7c127fSCraig Rodrigues { "uid", UID },
4019e7c127fSCraig Rodrigues { "user", USER },
4029e7c127fSCraig Rodrigues };
4039e7c127fSCraig Rodrigues const struct keywords *p;
4049e7c127fSCraig Rodrigues
4059e7c127fSCraig Rodrigues p = bsearch(s, keywords, sizeof(keywords)/sizeof(keywords[0]),
4069e7c127fSCraig Rodrigues sizeof(keywords[0]), kw_cmp);
4079e7c127fSCraig Rodrigues
4089e7c127fSCraig Rodrigues if (p)
4099e7c127fSCraig Rodrigues return (p->k_val);
4109e7c127fSCraig Rodrigues else
4119e7c127fSCraig Rodrigues return (STRING);
4129e7c127fSCraig Rodrigues }
4139e7c127fSCraig Rodrigues
4149e7c127fSCraig Rodrigues #define MAXPUSHBACK 128
4159e7c127fSCraig Rodrigues
4169e7c127fSCraig Rodrigues u_char *parsebuf;
4179e7c127fSCraig Rodrigues int parseindex;
4189e7c127fSCraig Rodrigues u_char pushback_buffer[MAXPUSHBACK];
4199e7c127fSCraig Rodrigues int pushback_index = 0;
4209e7c127fSCraig Rodrigues
4219e7c127fSCraig Rodrigues int
lgetc(int quotec)4229e7c127fSCraig Rodrigues lgetc(int quotec)
4239e7c127fSCraig Rodrigues {
4249e7c127fSCraig Rodrigues int c, next;
4259e7c127fSCraig Rodrigues
4269e7c127fSCraig Rodrigues if (parsebuf) {
4279e7c127fSCraig Rodrigues /* Read character from the parsebuffer instead of input. */
4289e7c127fSCraig Rodrigues if (parseindex >= 0) {
4299e7c127fSCraig Rodrigues c = parsebuf[parseindex++];
4309e7c127fSCraig Rodrigues if (c != '\0')
4319e7c127fSCraig Rodrigues return (c);
4329e7c127fSCraig Rodrigues parsebuf = NULL;
4339e7c127fSCraig Rodrigues } else
4349e7c127fSCraig Rodrigues parseindex++;
4359e7c127fSCraig Rodrigues }
4369e7c127fSCraig Rodrigues
4379e7c127fSCraig Rodrigues if (pushback_index)
4389e7c127fSCraig Rodrigues return (pushback_buffer[--pushback_index]);
4399e7c127fSCraig Rodrigues
4409e7c127fSCraig Rodrigues if (quotec) {
4419e7c127fSCraig Rodrigues if ((c = getc(file->stream)) == EOF) {
4429e7c127fSCraig Rodrigues yyerror("reached end of file while parsing "
4439e7c127fSCraig Rodrigues "quoted string");
4449e7c127fSCraig Rodrigues if (file == topfile || popfile() == EOF)
4459e7c127fSCraig Rodrigues return (EOF);
4469e7c127fSCraig Rodrigues return (quotec);
4479e7c127fSCraig Rodrigues }
4489e7c127fSCraig Rodrigues return (c);
4499e7c127fSCraig Rodrigues }
4509e7c127fSCraig Rodrigues
4519e7c127fSCraig Rodrigues while ((c = getc(file->stream)) == '\\') {
4529e7c127fSCraig Rodrigues next = getc(file->stream);
4539e7c127fSCraig Rodrigues if (next != '\n') {
4549e7c127fSCraig Rodrigues c = next;
4559e7c127fSCraig Rodrigues break;
4569e7c127fSCraig Rodrigues }
4579e7c127fSCraig Rodrigues yylval.lineno = file->lineno;
4589e7c127fSCraig Rodrigues file->lineno++;
4599e7c127fSCraig Rodrigues }
4609e7c127fSCraig Rodrigues
4619e7c127fSCraig Rodrigues while (c == EOF) {
4629e7c127fSCraig Rodrigues if (file == topfile || popfile() == EOF)
4639e7c127fSCraig Rodrigues return (EOF);
4649e7c127fSCraig Rodrigues c = getc(file->stream);
4659e7c127fSCraig Rodrigues }
4669e7c127fSCraig Rodrigues return (c);
4679e7c127fSCraig Rodrigues }
4689e7c127fSCraig Rodrigues
4699e7c127fSCraig Rodrigues int
lungetc(int c)4709e7c127fSCraig Rodrigues lungetc(int c)
4719e7c127fSCraig Rodrigues {
4729e7c127fSCraig Rodrigues if (c == EOF)
4739e7c127fSCraig Rodrigues return (EOF);
4749e7c127fSCraig Rodrigues if (parsebuf) {
4759e7c127fSCraig Rodrigues parseindex--;
4769e7c127fSCraig Rodrigues if (parseindex >= 0)
4779e7c127fSCraig Rodrigues return (c);
4789e7c127fSCraig Rodrigues }
4799e7c127fSCraig Rodrigues if (pushback_index < MAXPUSHBACK-1)
4809e7c127fSCraig Rodrigues return (pushback_buffer[pushback_index++] = c);
4819e7c127fSCraig Rodrigues else
4829e7c127fSCraig Rodrigues return (EOF);
4839e7c127fSCraig Rodrigues }
4849e7c127fSCraig Rodrigues
4859e7c127fSCraig Rodrigues int
findeol(void)4869e7c127fSCraig Rodrigues findeol(void)
4879e7c127fSCraig Rodrigues {
4889e7c127fSCraig Rodrigues int c;
4899e7c127fSCraig Rodrigues
4909e7c127fSCraig Rodrigues parsebuf = NULL;
4919e7c127fSCraig Rodrigues
4929e7c127fSCraig Rodrigues /* skip to either EOF or the first real EOL */
4939e7c127fSCraig Rodrigues while (1) {
4949e7c127fSCraig Rodrigues if (pushback_index)
4959e7c127fSCraig Rodrigues c = pushback_buffer[--pushback_index];
4969e7c127fSCraig Rodrigues else
4979e7c127fSCraig Rodrigues c = lgetc(0);
4989e7c127fSCraig Rodrigues if (c == '\n') {
4999e7c127fSCraig Rodrigues file->lineno++;
5009e7c127fSCraig Rodrigues break;
5019e7c127fSCraig Rodrigues }
5029e7c127fSCraig Rodrigues if (c == EOF)
5039e7c127fSCraig Rodrigues break;
5049e7c127fSCraig Rodrigues }
5059e7c127fSCraig Rodrigues return (ERROR);
5069e7c127fSCraig Rodrigues }
5079e7c127fSCraig Rodrigues
5089e7c127fSCraig Rodrigues int
yylex(void)5099e7c127fSCraig Rodrigues yylex(void)
5109e7c127fSCraig Rodrigues {
5119e7c127fSCraig Rodrigues u_char buf[8096];
5129e7c127fSCraig Rodrigues u_char *p, *val;
5139e7c127fSCraig Rodrigues int quotec, next, c;
5149e7c127fSCraig Rodrigues int token;
5159e7c127fSCraig Rodrigues
5169e7c127fSCraig Rodrigues top:
5179e7c127fSCraig Rodrigues p = buf;
5189e7c127fSCraig Rodrigues while ((c = lgetc(0)) == ' ' || c == '\t')
5199e7c127fSCraig Rodrigues ; /* nothing */
5209e7c127fSCraig Rodrigues
5219e7c127fSCraig Rodrigues yylval.lineno = file->lineno;
5229e7c127fSCraig Rodrigues if (c == '#')
5239e7c127fSCraig Rodrigues while ((c = lgetc(0)) != '\n' && c != EOF)
5249e7c127fSCraig Rodrigues ; /* nothing */
5259e7c127fSCraig Rodrigues if (c == '$' && parsebuf == NULL) {
5269e7c127fSCraig Rodrigues while (1) {
5279e7c127fSCraig Rodrigues if ((c = lgetc(0)) == EOF)
5289e7c127fSCraig Rodrigues return (0);
5299e7c127fSCraig Rodrigues
5309e7c127fSCraig Rodrigues if (p + 1 >= buf + sizeof(buf) - 1) {
5319e7c127fSCraig Rodrigues yyerror("string too long");
5329e7c127fSCraig Rodrigues return (findeol());
5339e7c127fSCraig Rodrigues }
5349e7c127fSCraig Rodrigues if (isalnum(c) || c == '_') {
5359e7c127fSCraig Rodrigues *p++ = c;
5369e7c127fSCraig Rodrigues continue;
5379e7c127fSCraig Rodrigues }
5389e7c127fSCraig Rodrigues *p = '\0';
5399e7c127fSCraig Rodrigues lungetc(c);
5409e7c127fSCraig Rodrigues break;
5419e7c127fSCraig Rodrigues }
5429e7c127fSCraig Rodrigues val = symget(buf);
5439e7c127fSCraig Rodrigues if (val == NULL) {
5449e7c127fSCraig Rodrigues yyerror("macro '%s' not defined", buf);
5459e7c127fSCraig Rodrigues return (findeol());
5469e7c127fSCraig Rodrigues }
5479e7c127fSCraig Rodrigues parsebuf = val;
5489e7c127fSCraig Rodrigues parseindex = 0;
5499e7c127fSCraig Rodrigues goto top;
5509e7c127fSCraig Rodrigues }
5519e7c127fSCraig Rodrigues
5529e7c127fSCraig Rodrigues switch (c) {
5539e7c127fSCraig Rodrigues case '\'':
5549e7c127fSCraig Rodrigues case '"':
5559e7c127fSCraig Rodrigues quotec = c;
5569e7c127fSCraig Rodrigues while (1) {
5579e7c127fSCraig Rodrigues if ((c = lgetc(quotec)) == EOF)
5589e7c127fSCraig Rodrigues return (0);
5599e7c127fSCraig Rodrigues if (c == '\n') {
5609e7c127fSCraig Rodrigues file->lineno++;
5619e7c127fSCraig Rodrigues continue;
5629e7c127fSCraig Rodrigues } else if (c == '\\') {
5639e7c127fSCraig Rodrigues if ((next = lgetc(quotec)) == EOF)
5649e7c127fSCraig Rodrigues return (0);
5659e7c127fSCraig Rodrigues if (next == quotec || c == ' ' || c == '\t')
5669e7c127fSCraig Rodrigues c = next;
5679e7c127fSCraig Rodrigues else if (next == '\n') {
5689e7c127fSCraig Rodrigues file->lineno++;
5699e7c127fSCraig Rodrigues continue;
5709e7c127fSCraig Rodrigues } else
5719e7c127fSCraig Rodrigues lungetc(next);
5729e7c127fSCraig Rodrigues } else if (c == quotec) {
5739e7c127fSCraig Rodrigues *p = '\0';
5749e7c127fSCraig Rodrigues break;
5759e7c127fSCraig Rodrigues } else if (c == '\0') {
5769e7c127fSCraig Rodrigues yyerror("syntax error");
5779e7c127fSCraig Rodrigues return (findeol());
5789e7c127fSCraig Rodrigues }
5799e7c127fSCraig Rodrigues if (p + 1 >= buf + sizeof(buf) - 1) {
5809e7c127fSCraig Rodrigues yyerror("string too long");
5819e7c127fSCraig Rodrigues return (findeol());
5829e7c127fSCraig Rodrigues }
5839e7c127fSCraig Rodrigues *p++ = c;
5849e7c127fSCraig Rodrigues }
5859e7c127fSCraig Rodrigues yylval.v.string = strdup(buf);
5869e7c127fSCraig Rodrigues if (yylval.v.string == NULL)
5879e7c127fSCraig Rodrigues err(1, "yylex: strdup");
5889e7c127fSCraig Rodrigues return (STRING);
5899e7c127fSCraig Rodrigues }
5909e7c127fSCraig Rodrigues
5919e7c127fSCraig Rodrigues #define allowed_to_end_number(x) \
5929e7c127fSCraig Rodrigues (isspace(x) || x == ')' || x ==',' || x == '/' || x == '}' || x == '=')
5939e7c127fSCraig Rodrigues
5949e7c127fSCraig Rodrigues if (c == '-' || isdigit(c)) {
5959e7c127fSCraig Rodrigues do {
5969e7c127fSCraig Rodrigues *p++ = c;
5979e7c127fSCraig Rodrigues if ((unsigned)(p-buf) >= sizeof(buf)) {
5989e7c127fSCraig Rodrigues yyerror("string too long");
5999e7c127fSCraig Rodrigues return (findeol());
6009e7c127fSCraig Rodrigues }
6019e7c127fSCraig Rodrigues } while ((c = lgetc(0)) != EOF && isdigit(c));
6029e7c127fSCraig Rodrigues lungetc(c);
6039e7c127fSCraig Rodrigues if (p == buf + 1 && buf[0] == '-')
6049e7c127fSCraig Rodrigues goto nodigits;
6059e7c127fSCraig Rodrigues if (c == EOF || allowed_to_end_number(c)) {
6069e7c127fSCraig Rodrigues const char *errstr = NULL;
6079e7c127fSCraig Rodrigues
6089e7c127fSCraig Rodrigues *p = '\0';
6099e7c127fSCraig Rodrigues yylval.v.number = strtonum(buf, LLONG_MIN,
6109e7c127fSCraig Rodrigues LLONG_MAX, &errstr);
6119e7c127fSCraig Rodrigues if (errstr) {
6129e7c127fSCraig Rodrigues yyerror("\"%s\" invalid number: %s",
6139e7c127fSCraig Rodrigues buf, errstr);
6149e7c127fSCraig Rodrigues return (findeol());
6159e7c127fSCraig Rodrigues }
6169e7c127fSCraig Rodrigues return (NUMBER);
6179e7c127fSCraig Rodrigues } else {
6189e7c127fSCraig Rodrigues nodigits:
6199e7c127fSCraig Rodrigues while (p > buf + 1)
6209e7c127fSCraig Rodrigues lungetc(*--p);
6219e7c127fSCraig Rodrigues c = *--p;
6229e7c127fSCraig Rodrigues if (c == '-')
6239e7c127fSCraig Rodrigues return (c);
6249e7c127fSCraig Rodrigues }
6259e7c127fSCraig Rodrigues }
6269e7c127fSCraig Rodrigues
6279e7c127fSCraig Rodrigues #define allowed_in_string(x) \
6289e7c127fSCraig Rodrigues (isalnum(x) || (ispunct(x) && x != '(' && x != ')' && \
6299e7c127fSCraig Rodrigues x != '{' && x != '}' && x != '<' && x != '>' && \
6309e7c127fSCraig Rodrigues x != '!' && x != '=' && x != '#' && \
6319e7c127fSCraig Rodrigues x != ','))
6329e7c127fSCraig Rodrigues
6339e7c127fSCraig Rodrigues if (isalnum(c) || c == ':' || c == '_') {
6349e7c127fSCraig Rodrigues do {
6359e7c127fSCraig Rodrigues *p++ = c;
6369e7c127fSCraig Rodrigues if ((unsigned)(p-buf) >= sizeof(buf)) {
6379e7c127fSCraig Rodrigues yyerror("string too long");
6389e7c127fSCraig Rodrigues return (findeol());
6399e7c127fSCraig Rodrigues }
6409e7c127fSCraig Rodrigues } while ((c = lgetc(0)) != EOF && (allowed_in_string(c)));
6419e7c127fSCraig Rodrigues lungetc(c);
6429e7c127fSCraig Rodrigues *p = '\0';
6439e7c127fSCraig Rodrigues if ((token = lookup(buf)) == STRING)
6449e7c127fSCraig Rodrigues if ((yylval.v.string = strdup(buf)) == NULL)
6459e7c127fSCraig Rodrigues err(1, "yylex: strdup");
6469e7c127fSCraig Rodrigues return (token);
6479e7c127fSCraig Rodrigues }
6489e7c127fSCraig Rodrigues if (c == '\n') {
6499e7c127fSCraig Rodrigues yylval.lineno = file->lineno;
6509e7c127fSCraig Rodrigues file->lineno++;
6519e7c127fSCraig Rodrigues }
6529e7c127fSCraig Rodrigues if (c == EOF)
6539e7c127fSCraig Rodrigues return (0);
6549e7c127fSCraig Rodrigues return (c);
6559e7c127fSCraig Rodrigues }
6569e7c127fSCraig Rodrigues
6579e7c127fSCraig Rodrigues int
check_file_secrecy(int fd,const char * fname)6589e7c127fSCraig Rodrigues check_file_secrecy(int fd, const char *fname)
6599e7c127fSCraig Rodrigues {
6609e7c127fSCraig Rodrigues struct stat st;
6619e7c127fSCraig Rodrigues
6629e7c127fSCraig Rodrigues if (fstat(fd, &st)) {
6639e7c127fSCraig Rodrigues log_warn("cannot stat %s", fname);
6649e7c127fSCraig Rodrigues return (-1);
6659e7c127fSCraig Rodrigues }
6669e7c127fSCraig Rodrigues if (st.st_uid != 0 && st.st_uid != getuid()) {
6679e7c127fSCraig Rodrigues log_warnx("%s: owner not root or current user", fname);
6689e7c127fSCraig Rodrigues return (-1);
6699e7c127fSCraig Rodrigues }
6709e7c127fSCraig Rodrigues if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) {
6719e7c127fSCraig Rodrigues log_warnx("%s: group writable or world read/writable", fname);
6729e7c127fSCraig Rodrigues return (-1);
6739e7c127fSCraig Rodrigues }
6749e7c127fSCraig Rodrigues return (0);
6759e7c127fSCraig Rodrigues }
6769e7c127fSCraig Rodrigues
6779e7c127fSCraig Rodrigues struct file *
pushfile(const char * name,int secret)6789e7c127fSCraig Rodrigues pushfile(const char *name, int secret)
6799e7c127fSCraig Rodrigues {
6809e7c127fSCraig Rodrigues struct file *nfile;
6819e7c127fSCraig Rodrigues
6829e7c127fSCraig Rodrigues if ((nfile = calloc(1, sizeof(struct file))) == NULL) {
6839e7c127fSCraig Rodrigues log_warn("malloc");
6849e7c127fSCraig Rodrigues return (NULL);
6859e7c127fSCraig Rodrigues }
6869e7c127fSCraig Rodrigues if ((nfile->name = strdup(name)) == NULL) {
6879e7c127fSCraig Rodrigues log_warn("malloc");
6889e7c127fSCraig Rodrigues free(nfile);
6899e7c127fSCraig Rodrigues return (NULL);
6909e7c127fSCraig Rodrigues }
6919e7c127fSCraig Rodrigues if ((nfile->stream = fopen(nfile->name, "r")) == NULL) {
6929e7c127fSCraig Rodrigues log_warn("%s", nfile->name);
6939e7c127fSCraig Rodrigues free(nfile->name);
6949e7c127fSCraig Rodrigues free(nfile);
6959e7c127fSCraig Rodrigues return (NULL);
6969e7c127fSCraig Rodrigues } else if (secret &&
6979e7c127fSCraig Rodrigues check_file_secrecy(fileno(nfile->stream), nfile->name)) {
6989e7c127fSCraig Rodrigues fclose(nfile->stream);
6999e7c127fSCraig Rodrigues free(nfile->name);
7009e7c127fSCraig Rodrigues free(nfile);
7019e7c127fSCraig Rodrigues return (NULL);
7029e7c127fSCraig Rodrigues }
7039e7c127fSCraig Rodrigues nfile->lineno = 1;
7049e7c127fSCraig Rodrigues TAILQ_INSERT_TAIL(&files, nfile, entry);
7059e7c127fSCraig Rodrigues return (nfile);
7069e7c127fSCraig Rodrigues }
7079e7c127fSCraig Rodrigues
7089e7c127fSCraig Rodrigues int
popfile(void)7099e7c127fSCraig Rodrigues popfile(void)
7109e7c127fSCraig Rodrigues {
7119e7c127fSCraig Rodrigues struct file *prev;
7129e7c127fSCraig Rodrigues
7139e7c127fSCraig Rodrigues if ((prev = TAILQ_PREV(file, files, entry)) != NULL)
7149e7c127fSCraig Rodrigues prev->errors += file->errors;
7159e7c127fSCraig Rodrigues
7169e7c127fSCraig Rodrigues TAILQ_REMOVE(&files, file, entry);
7179e7c127fSCraig Rodrigues fclose(file->stream);
7189e7c127fSCraig Rodrigues free(file->name);
7199e7c127fSCraig Rodrigues free(file);
7209e7c127fSCraig Rodrigues file = prev;
7219e7c127fSCraig Rodrigues return (file ? 0 : EOF);
7229e7c127fSCraig Rodrigues }
7239e7c127fSCraig Rodrigues
7249e7c127fSCraig Rodrigues int
parse_config(struct env * x_conf,const char * filename,int opts)7259e7c127fSCraig Rodrigues parse_config(struct env *x_conf, const char *filename, int opts)
7269e7c127fSCraig Rodrigues {
7279e7c127fSCraig Rodrigues struct sym *sym, *next;
7289e7c127fSCraig Rodrigues
7299e7c127fSCraig Rodrigues conf = x_conf;
7309e7c127fSCraig Rodrigues bzero(conf, sizeof(*conf));
7319e7c127fSCraig Rodrigues
7329e7c127fSCraig Rodrigues TAILQ_INIT(&conf->sc_idms);
7339e7c127fSCraig Rodrigues conf->sc_conf_tv.tv_sec = DEFAULT_INTERVAL;
7349e7c127fSCraig Rodrigues conf->sc_conf_tv.tv_usec = 0;
7359e7c127fSCraig Rodrigues
7369e7c127fSCraig Rodrigues errors = 0;
7379e7c127fSCraig Rodrigues
7389e7c127fSCraig Rodrigues if ((file = pushfile(filename, 1)) == NULL) {
7399e7c127fSCraig Rodrigues return (-1);
7409e7c127fSCraig Rodrigues }
7419e7c127fSCraig Rodrigues topfile = file;
7429e7c127fSCraig Rodrigues
7439e7c127fSCraig Rodrigues /*
7449e7c127fSCraig Rodrigues * parse configuration
7459e7c127fSCraig Rodrigues */
7469e7c127fSCraig Rodrigues setservent(1);
7479e7c127fSCraig Rodrigues yyparse();
7489e7c127fSCraig Rodrigues endservent();
7499e7c127fSCraig Rodrigues errors = file->errors;
7509e7c127fSCraig Rodrigues popfile();
7519e7c127fSCraig Rodrigues
7529e7c127fSCraig Rodrigues /* Free macros and check which have not been used. */
7539e7c127fSCraig Rodrigues for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) {
7549e7c127fSCraig Rodrigues next = TAILQ_NEXT(sym, entry);
7559e7c127fSCraig Rodrigues if ((opts & YPLDAP_OPT_VERBOSE) && !sym->used)
7569e7c127fSCraig Rodrigues fprintf(stderr, "warning: macro '%s' not "
7579e7c127fSCraig Rodrigues "used\n", sym->nam);
7589e7c127fSCraig Rodrigues if (!sym->persist) {
7599e7c127fSCraig Rodrigues free(sym->nam);
7609e7c127fSCraig Rodrigues free(sym->val);
7619e7c127fSCraig Rodrigues TAILQ_REMOVE(&symhead, sym, entry);
7629e7c127fSCraig Rodrigues free(sym);
7639e7c127fSCraig Rodrigues }
7649e7c127fSCraig Rodrigues }
7659e7c127fSCraig Rodrigues
7669e7c127fSCraig Rodrigues if (errors) {
7679e7c127fSCraig Rodrigues return (-1);
7689e7c127fSCraig Rodrigues }
7699e7c127fSCraig Rodrigues
7709e7c127fSCraig Rodrigues return (0);
7719e7c127fSCraig Rodrigues }
7729e7c127fSCraig Rodrigues
7739e7c127fSCraig Rodrigues int
symset(const char * nam,const char * val,int persist)7749e7c127fSCraig Rodrigues symset(const char *nam, const char *val, int persist)
7759e7c127fSCraig Rodrigues {
7769e7c127fSCraig Rodrigues struct sym *sym;
7779e7c127fSCraig Rodrigues
7789e7c127fSCraig Rodrigues for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam);
7799e7c127fSCraig Rodrigues sym = TAILQ_NEXT(sym, entry))
7809e7c127fSCraig Rodrigues ; /* nothing */
7819e7c127fSCraig Rodrigues
7829e7c127fSCraig Rodrigues if (sym != NULL) {
7839e7c127fSCraig Rodrigues if (sym->persist == 1)
7849e7c127fSCraig Rodrigues return (0);
7859e7c127fSCraig Rodrigues else {
7869e7c127fSCraig Rodrigues free(sym->nam);
7879e7c127fSCraig Rodrigues free(sym->val);
7889e7c127fSCraig Rodrigues TAILQ_REMOVE(&symhead, sym, entry);
7899e7c127fSCraig Rodrigues free(sym);
7909e7c127fSCraig Rodrigues }
7919e7c127fSCraig Rodrigues }
7929e7c127fSCraig Rodrigues if ((sym = calloc(1, sizeof(*sym))) == NULL)
7939e7c127fSCraig Rodrigues return (-1);
7949e7c127fSCraig Rodrigues
7959e7c127fSCraig Rodrigues sym->nam = strdup(nam);
7969e7c127fSCraig Rodrigues if (sym->nam == NULL) {
7979e7c127fSCraig Rodrigues free(sym);
7989e7c127fSCraig Rodrigues return (-1);
7999e7c127fSCraig Rodrigues }
8009e7c127fSCraig Rodrigues sym->val = strdup(val);
8019e7c127fSCraig Rodrigues if (sym->val == NULL) {
8029e7c127fSCraig Rodrigues free(sym->nam);
8039e7c127fSCraig Rodrigues free(sym);
8049e7c127fSCraig Rodrigues return (-1);
8059e7c127fSCraig Rodrigues }
8069e7c127fSCraig Rodrigues sym->used = 0;
8079e7c127fSCraig Rodrigues sym->persist = persist;
8089e7c127fSCraig Rodrigues TAILQ_INSERT_TAIL(&symhead, sym, entry);
8099e7c127fSCraig Rodrigues return (0);
8109e7c127fSCraig Rodrigues }
8119e7c127fSCraig Rodrigues
8129e7c127fSCraig Rodrigues int
cmdline_symset(char * s)8139e7c127fSCraig Rodrigues cmdline_symset(char *s)
8149e7c127fSCraig Rodrigues {
8159e7c127fSCraig Rodrigues char *sym, *val;
8169e7c127fSCraig Rodrigues int ret;
8179e7c127fSCraig Rodrigues size_t len;
8189e7c127fSCraig Rodrigues
8199e7c127fSCraig Rodrigues if ((val = strrchr(s, '=')) == NULL)
8209e7c127fSCraig Rodrigues return (-1);
8219e7c127fSCraig Rodrigues
8229e7c127fSCraig Rodrigues len = strlen(s) - strlen(val) + 1;
8239e7c127fSCraig Rodrigues if ((sym = malloc(len)) == NULL)
8249e7c127fSCraig Rodrigues errx(1, "cmdline_symset: malloc");
8259e7c127fSCraig Rodrigues
8269e7c127fSCraig Rodrigues (void)strlcpy(sym, s, len);
8279e7c127fSCraig Rodrigues
8289e7c127fSCraig Rodrigues ret = symset(sym, val + 1, 1);
8299e7c127fSCraig Rodrigues free(sym);
8309e7c127fSCraig Rodrigues
8319e7c127fSCraig Rodrigues return (ret);
8329e7c127fSCraig Rodrigues }
8339e7c127fSCraig Rodrigues
8349e7c127fSCraig Rodrigues char *
symget(const char * nam)8359e7c127fSCraig Rodrigues symget(const char *nam)
8369e7c127fSCraig Rodrigues {
8379e7c127fSCraig Rodrigues struct sym *sym;
8389e7c127fSCraig Rodrigues
8399e7c127fSCraig Rodrigues TAILQ_FOREACH(sym, &symhead, entry)
8409e7c127fSCraig Rodrigues if (strcmp(nam, sym->nam) == 0) {
8419e7c127fSCraig Rodrigues sym->used = 1;
8429e7c127fSCraig Rodrigues return (sym->val);
8439e7c127fSCraig Rodrigues }
8449e7c127fSCraig Rodrigues return (NULL);
8459e7c127fSCraig Rodrigues }
846