update Debian standards version
[debian/sudo] / gram.y
1 %{
2 /*
3  * Copyright (c) 1996, 1998-2005, 2007-2009
4  *      Todd C. Miller <Todd.Miller@courtesan.com>
5  *
6  * Permission to use, copy, modify, and distribute this software for any
7  * purpose with or without fee is hereby granted, provided that the above
8  * copyright notice and this permission notice appear in all copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
18  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
19  *
20  * Sponsored in part by the Defense Advanced Research Projects
21  * Agency (DARPA) and Air Force Research Laboratory, Air Force
22  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
23  */
24
25 #include <config.h>
26
27 #include <sys/types.h>
28 #include <sys/param.h>
29 #include <stdio.h>
30 #ifdef STDC_HEADERS
31 # include <stdlib.h>
32 # include <stddef.h>
33 #else
34 # ifdef HAVE_STDLIB_H
35 #  include <stdlib.h>
36 # endif
37 #endif /* STDC_HEADERS */
38 #ifdef HAVE_STRING_H
39 # include <string.h>
40 #else
41 # ifdef HAVE_STRINGS_H
42 #  include <strings.h>
43 # endif
44 #endif /* HAVE_STRING_H */
45 #ifdef HAVE_UNISTD_H
46 # include <unistd.h>
47 #endif /* HAVE_UNISTD_H */
48 #if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
49 # include <alloca.h>
50 #endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
51 #include <limits.h>
52
53 #include "sudo.h"
54 #include "parse.h"
55
56 #ifndef lint
57 __unused static const char rcsid[] = "$Sudo: gram.y,v 1.36 2009/05/25 12:02:41 millert Exp $";
58 #endif /* lint */
59
60 /*
61  * We must define SIZE_MAX for yacc's skeleton.c.
62  * If there is no SIZE_MAX or SIZE_T_MAX we have to assume that size_t
63  * could be signed (as it is on SunOS 4.x).
64  */
65 #ifndef SIZE_MAX
66 # ifdef SIZE_T_MAX
67 #  define SIZE_MAX      SIZE_T_MAX
68 # else
69 #  define SIZE_MAX      INT_MAX
70 # endif /* SIZE_T_MAX */
71 #endif /* SIZE_MAX */
72
73 /*
74  * Globals
75  */
76 extern int sudolineno;
77 extern char *sudoers;
78 int parse_error;
79 int pedantic = FALSE;
80 int verbose = FALSE;
81 int errorlineno = -1;
82 char *errorfile = NULL;
83
84 struct defaults_list defaults;
85 struct userspec_list userspecs;
86
87 /*
88  * Local protoypes
89  */
90 static void  add_defaults       __P((int, struct member *, struct defaults *));
91 static void  add_userspec       __P((struct member *, struct privilege *));
92 static struct defaults *new_default __P((char *, char *, int));
93 static struct member *new_member __P((char *, int));
94        void  yyerror            __P((const char *));
95
96 void
97 yyerror(s)
98     const char *s;
99 {
100     /* Save the line the first error occurred on. */
101     if (errorlineno == -1) {
102         errorlineno = sudolineno ? sudolineno - 1 : 0;
103         errorfile = estrdup(sudoers);
104     }
105     if (verbose && s != NULL) {
106 #ifndef TRACELEXER
107         (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s,
108             sudolineno ? sudolineno - 1 : 0);
109 #else
110         (void) fprintf(stderr, "<*> ");
111 #endif
112     }
113     parse_error = TRUE;
114 }
115 %}
116
117 %union {
118     struct cmndspec *cmndspec;
119     struct defaults *defaults;
120     struct member *member;
121     struct runascontainer *runas;
122     struct privilege *privilege;
123     struct sudo_command command;
124     struct cmndtag tag;
125     struct selinux_info seinfo;
126     char *string;
127     int tok;
128 }
129
130 %start file                             /* special start symbol */
131 %token <command> COMMAND                /* absolute pathname w/ optional args */
132 %token <string>  ALIAS                  /* an UPPERCASE alias name */
133 %token <string>  DEFVAR                 /* a Defaults variable name */
134 %token <string>  NTWKADDR               /* ipv4 or ipv6 address */
135 %token <string>  NETGROUP               /* a netgroup (+NAME) */
136 %token <string>  USERGROUP              /* a usergroup (%NAME) */
137 %token <string>  WORD                   /* a word */
138 %token <tok>     DEFAULTS               /* Defaults entry */
139 %token <tok>     DEFAULTS_HOST          /* Host-specific defaults entry */
140 %token <tok>     DEFAULTS_USER          /* User-specific defaults entry */
141 %token <tok>     DEFAULTS_RUNAS         /* Runas-specific defaults entry */
142 %token <tok>     DEFAULTS_CMND          /* Command-specific defaults entry */
143 %token <tok>     NOPASSWD               /* no passwd req for command */
144 %token <tok>     PASSWD                 /* passwd req for command (default) */
145 %token <tok>     NOEXEC                 /* preload dummy execve() for cmnd */
146 %token <tok>     EXEC                   /* don't preload dummy execve() */
147 %token <tok>     SETENV                 /* user may set environment for cmnd */
148 %token <tok>     NOSETENV               /* user may not set environment */
149 %token <tok>     ALL                    /* ALL keyword */
150 %token <tok>     COMMENT                /* comment and/or carriage return */
151 %token <tok>     HOSTALIAS              /* Host_Alias keyword */
152 %token <tok>     CMNDALIAS              /* Cmnd_Alias keyword */
153 %token <tok>     USERALIAS              /* User_Alias keyword */
154 %token <tok>     RUNASALIAS             /* Runas_Alias keyword */
155 %token <tok>     ':' '=' ',' '!' '+' '-' /* union member tokens */
156 %token <tok>     '(' ')'                /* runas tokens */
157 %token <tok>     ERROR
158 %token <tok>     TYPE                   /* SELinux type */
159 %token <tok>     ROLE                   /* SELinux role */
160
161 %type <cmndspec>  cmndspec
162 %type <cmndspec>  cmndspeclist
163 %type <defaults>  defaults_entry
164 %type <defaults>  defaults_list
165 %type <member>    cmnd
166 %type <member>    opcmnd
167 %type <member>    cmndlist
168 %type <member>    host
169 %type <member>    hostlist
170 %type <member>    ophost
171 %type <member>    opuser
172 %type <member>    user
173 %type <member>    userlist
174 %type <member>    opgroup
175 %type <member>    group
176 %type <member>    grouplist
177 %type <runas>     runasspec
178 %type <runas>     runaslist
179 %type <privilege> privilege
180 %type <privilege> privileges
181 %type <tag>       cmndtag
182 %type <seinfo>    selinux
183 %type <string>    rolespec
184 %type <string>    typespec
185
186 %%
187
188 file            :       { ; }
189                 |       line
190                 ;
191
192 line            :       entry
193                 |       line entry
194                 ;
195
196 entry           :       COMMENT {
197                             ;
198                         }
199                 |       error COMMENT {
200                             yyerrok;
201                         }
202                 |       userlist privileges {
203                             add_userspec($1, $2);
204                         }
205                 |       USERALIAS useraliases {
206                             ;
207                         }
208                 |       HOSTALIAS hostaliases {
209                             ;
210                         }
211                 |       CMNDALIAS cmndaliases {
212                             ;
213                         }
214                 |       RUNASALIAS runasaliases {
215                             ;
216                         }
217                 |       DEFAULTS defaults_list {
218                             add_defaults(DEFAULTS, NULL, $2);
219                         }
220                 |       DEFAULTS_USER userlist defaults_list {
221                             add_defaults(DEFAULTS_USER, $2, $3);
222                         }
223                 |       DEFAULTS_RUNAS userlist defaults_list {
224                             add_defaults(DEFAULTS_RUNAS, $2, $3);
225                         }
226                 |       DEFAULTS_HOST hostlist defaults_list {
227                             add_defaults(DEFAULTS_HOST, $2, $3);
228                         }
229                 |       DEFAULTS_CMND cmndlist defaults_list {
230                             add_defaults(DEFAULTS_CMND, $2, $3);
231                         }
232                 ;
233
234 defaults_list   :       defaults_entry
235                 |       defaults_list ',' defaults_entry {
236                             list_append($1, $3);
237                             $$ = $1;
238                         }
239                 ;
240
241 defaults_entry  :       DEFVAR {
242                             $$ = new_default($1, NULL, TRUE);
243                         }
244                 |       '!' DEFVAR {
245                             $$ = new_default($2, NULL, FALSE);
246                         }
247                 |       DEFVAR '=' WORD {
248                             $$ = new_default($1, $3, TRUE);
249                         }
250                 |       DEFVAR '+' WORD {
251                             $$ = new_default($1, $3, '+');
252                         }
253                 |       DEFVAR '-' WORD {
254                             $$ = new_default($1, $3, '-');
255                         }
256                 ;
257
258 privileges      :       privilege
259                 |       privileges ':' privilege {
260                             list_append($1, $3);
261                             $$ = $1;
262                         }
263                 ;
264
265 privilege       :       hostlist '=' cmndspeclist {
266                             struct privilege *p = emalloc(sizeof(*p));
267                             list2tq(&p->hostlist, $1);
268                             list2tq(&p->cmndlist, $3);
269                             p->prev = p;
270                             p->next = NULL;
271                             $$ = p;
272                         }
273                 ;
274
275 ophost          :       host {
276                             $$ = $1;
277                             $$->negated = FALSE;
278                         }
279                 |       '!' host {
280                             $$ = $2;
281                             $$->negated = TRUE;
282                         }
283                 ;
284
285 host            :       ALIAS {
286                             $$ = new_member($1, ALIAS);
287                         }
288                 |       ALL {
289                             $$ = new_member(NULL, ALL);
290                         }
291                 |       NETGROUP {
292                             $$ = new_member($1, NETGROUP);
293                         }
294                 |       NTWKADDR {
295                             $$ = new_member($1, NTWKADDR);
296                         }
297                 |       WORD {
298                             $$ = new_member($1, WORD);
299                         }
300                 ;
301
302 cmndspeclist    :       cmndspec
303                 |       cmndspeclist ',' cmndspec {
304                             list_append($1, $3);
305 #ifdef HAVE_SELINUX
306                             /* propagate role and type */
307                             if ($3->role == NULL)
308                                 $3->role = $3->prev->role;
309                             if ($3->type == NULL)
310                                 $3->type = $3->prev->type;
311 #endif /* HAVE_SELINUX */
312                             /* propagate tags and runas list */
313                             if ($3->tags.nopasswd == UNSPEC)
314                                 $3->tags.nopasswd = $3->prev->tags.nopasswd;
315                             if ($3->tags.noexec == UNSPEC)
316                                 $3->tags.noexec = $3->prev->tags.noexec;
317                             if ($3->tags.setenv == UNSPEC &&
318                                 $3->prev->tags.setenv != IMPLIED)
319                                 $3->tags.setenv = $3->prev->tags.setenv;
320                             if ((tq_empty(&$3->runasuserlist) &&
321                                  tq_empty(&$3->runasgrouplist)) &&
322                                 (!tq_empty(&$3->prev->runasuserlist) ||
323                                  !tq_empty(&$3->prev->runasgrouplist))) {
324                                 $3->runasuserlist = $3->prev->runasuserlist;
325                                 $3->runasgrouplist = $3->prev->runasgrouplist;
326                             }
327                             $$ = $1;
328                         }
329                 ;
330
331 cmndspec        :       runasspec selinux cmndtag opcmnd {
332                             struct cmndspec *cs = emalloc(sizeof(*cs));
333                             if ($1 != NULL) {
334                                 list2tq(&cs->runasuserlist, $1->runasusers);
335                                 list2tq(&cs->runasgrouplist, $1->runasgroups);
336                                 efree($1);
337                             } else {
338                                 tq_init(&cs->runasuserlist);
339                                 tq_init(&cs->runasgrouplist);
340                             }
341 #ifdef HAVE_SELINUX
342                             cs->role = $2.role;
343                             cs->type = $2.type;
344 #endif
345                             cs->tags = $3;
346                             cs->cmnd = $4;
347                             cs->prev = cs;
348                             cs->next = NULL;
349                             /* sudo "ALL" implies the SETENV tag */
350                             if (cs->cmnd->type == ALL && !cs->cmnd->negated &&
351                                 cs->tags.setenv == UNSPEC)
352                                 cs->tags.setenv = IMPLIED;
353                             $$ = cs;
354                         }
355                 ;
356
357 opcmnd          :       cmnd {
358                             $$ = $1;
359                             $$->negated = FALSE;
360                         }
361                 |       '!' cmnd {
362                             $$ = $2;
363                             $$->negated = TRUE;
364                         }
365                 ;
366
367 rolespec        :       ROLE '=' WORD {
368                             $$ = $3;
369                         }
370                 ;
371
372 typespec        :       TYPE '=' WORD {
373                             $$ = $3;
374                         }
375                 ;
376
377 selinux         :       /* empty */ {
378                             $$.role = NULL;
379                             $$.type = NULL;
380                         }
381                 |       rolespec {
382                             $$.role = $1;
383                             $$.type = NULL;
384                         }
385                 |       typespec {
386                             $$.type = $1;
387                             $$.role = NULL;
388                         }
389                 |       rolespec typespec {
390                             $$.role = $1;
391                             $$.type = $2;
392                         }
393                 |       typespec rolespec {
394                             $$.type = $1;
395                             $$.role = $2;
396                         }
397                 ;
398
399 runasspec       :       /* empty */ {
400                             $$ = NULL;
401                         }
402                 |       '(' runaslist ')' {
403                             $$ = $2;
404                         }
405                 ;
406
407 runaslist       :       userlist {
408                             $$ = emalloc(sizeof(struct runascontainer));
409                             $$->runasusers = $1;
410                             $$->runasgroups = NULL;
411                         }
412                 |       userlist ':' grouplist {
413                             $$ = emalloc(sizeof(struct runascontainer));
414                             $$->runasusers = $1;
415                             $$->runasgroups = $3;
416                         }
417                 |       ':' grouplist {
418                             $$ = emalloc(sizeof(struct runascontainer));
419                             $$->runasusers = NULL;
420                             $$->runasgroups = $2;
421                         }
422                 ;
423
424 cmndtag         :       /* empty */ {
425                             $$.nopasswd = $$.noexec = $$.setenv = UNSPEC;
426                         }
427                 |       cmndtag NOPASSWD {
428                             $$.nopasswd = TRUE;
429                         }
430                 |       cmndtag PASSWD {
431                             $$.nopasswd = FALSE;
432                         }
433                 |       cmndtag NOEXEC {
434                             $$.noexec = TRUE;
435                         }
436                 |       cmndtag EXEC {
437                             $$.noexec = FALSE;
438                         }
439                 |       cmndtag SETENV {
440                             $$.setenv = TRUE;
441                         }
442                 |       cmndtag NOSETENV {
443                             $$.setenv = FALSE;
444                         }
445                 ;
446
447 cmnd            :       ALL {
448                             $$ = new_member(NULL, ALL);
449                         }
450                 |       ALIAS {
451                             $$ = new_member($1, ALIAS);
452                         }
453                 |       COMMAND {
454                             struct sudo_command *c = emalloc(sizeof(*c));
455                             c->cmnd = $1.cmnd;
456                             c->args = $1.args;
457                             $$ = new_member((char *)c, COMMAND);
458                         }
459                 ;
460
461 hostaliases     :       hostalias
462                 |       hostaliases ':' hostalias
463                 ;
464
465 hostalias       :       ALIAS '=' hostlist {
466                             char *s;
467                             if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) {
468                                 yyerror(s);
469                                 YYERROR;
470                             }
471                         }
472                 ;
473
474 hostlist        :       ophost
475                 |       hostlist ',' ophost {
476                             list_append($1, $3);
477                             $$ = $1;
478                         }
479                 ;
480
481 cmndaliases     :       cmndalias
482                 |       cmndaliases ':' cmndalias
483                 ;
484
485 cmndalias       :       ALIAS '=' cmndlist {
486                             char *s;
487                             if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) {
488                                 yyerror(s);
489                                 YYERROR;
490                             }
491                         }
492                 ;
493
494 cmndlist        :       opcmnd
495                 |       cmndlist ',' opcmnd {
496                             list_append($1, $3);
497                             $$ = $1;
498                         }
499                 ;
500
501 runasaliases    :       runasalias
502                 |       runasaliases ':' runasalias
503                 ;
504
505 runasalias      :       ALIAS '=' userlist {
506                             char *s;
507                             if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) {
508                                 yyerror(s);
509                                 YYERROR;
510                             }
511                         }
512                 ;
513
514 useraliases     :       useralias
515                 |       useraliases ':' useralias
516                 ;
517
518 useralias       :       ALIAS '=' userlist {
519                             char *s;
520                             if ((s = alias_add($1, USERALIAS, $3)) != NULL) {
521                                 yyerror(s);
522                                 YYERROR;
523                             }
524                         }
525                 ;
526
527 userlist        :       opuser
528                 |       userlist ',' opuser {
529                             list_append($1, $3);
530                             $$ = $1;
531                         }
532                 ;
533
534 opuser          :       user {
535                             $$ = $1;
536                             $$->negated = FALSE;
537                         }
538                 |       '!' user {
539                             $$ = $2;
540                             $$->negated = TRUE;
541                         }
542                 ;
543
544 user            :       ALIAS {
545                             $$ = new_member($1, ALIAS);
546                         }
547                 |       ALL {
548                             $$ = new_member(NULL, ALL);
549                         }
550                 |       NETGROUP {
551                             $$ = new_member($1, NETGROUP);
552                         }
553                 |       USERGROUP {
554                             $$ = new_member($1, USERGROUP);
555                         }
556                 |       WORD {
557                             $$ = new_member($1, WORD);
558                         }
559                 ;
560
561 grouplist       :       opgroup
562                 |       grouplist ',' opgroup {
563                             list_append($1, $3);
564                             $$ = $1;
565                         }
566                 ;
567
568 opgroup         :       group {
569                             $$ = $1;
570                             $$->negated = FALSE;
571                         }
572                 |       '!' group {
573                             $$ = $2;
574                             $$->negated = TRUE;
575                         }
576                 ;
577
578 group           :       ALIAS {
579                             $$ = new_member($1, ALIAS);
580                         }
581                 |       ALL {
582                             $$ = new_member(NULL, ALL);
583                         }
584                 |       WORD {
585                             $$ = new_member($1, WORD);
586                         }
587                 ;
588
589 %%
590 static struct defaults *
591 new_default(var, val, op)
592     char *var;
593     char *val;
594     int op;
595 {
596     struct defaults *d;
597
598     d = emalloc(sizeof(struct defaults));
599     d->var = var;
600     d->val = val;
601     tq_init(&d->binding);
602     d->type = 0;
603     d->op = op;
604     d->prev = d;
605     d->next = NULL;
606
607     return(d);
608 }
609
610 static struct member *
611 new_member(name, type)
612     char *name;
613     int type;
614 {
615     struct member *m;
616
617     m = emalloc(sizeof(struct member));
618     m->name = name;
619     m->type = type;
620     m->prev = m;
621     m->next = NULL;
622
623     return(m);
624 }
625
626 /*
627  * Add a list of defaults structures to the defaults list.
628  * The binding, if non-NULL, specifies a list of hosts, users, or
629  * runas users the entries apply to (specified by the type).
630  */
631 static void
632 add_defaults(type, bmem, defs)
633     int type;
634     struct member *bmem;
635     struct defaults *defs;
636 {
637     struct defaults *d;
638     struct member_list binding;
639
640     /*
641      * We can only call list2tq once on bmem as it will zero
642      * out the prev pointer when it consumes bmem.
643      */
644     list2tq(&binding, bmem);
645
646     /*
647      * Set type and binding (who it applies to) for new entries.
648      */
649     for (d = defs; d != NULL; d = d->next) {
650         d->type = type;
651         d->binding = binding;
652     }
653     tq_append(&defaults, defs);
654 }
655
656 /*
657  * Allocate a new struct userspec, populate it, and insert it at the
658  * and of the userspecs list.
659  */
660 static void
661 add_userspec(members, privs)
662     struct member *members;
663     struct privilege *privs;
664 {
665     struct userspec *u;
666
667     u = emalloc(sizeof(*u));
668     list2tq(&u->users, members);
669     list2tq(&u->privileges, privs);
670     u->prev = u;
671     u->next = NULL;
672     tq_append(&userspecs, u);
673 }
674
675 /*
676  * Free up space used by data structures from a previous parser run and sets
677  * the current sudoers file to path.
678  */
679 void
680 init_parser(path, quiet)
681     char *path;
682     int quiet;
683 {
684     struct defaults *d;
685     struct member *m, *binding;
686     struct userspec *us;
687     struct privilege *priv;
688     struct cmndspec *cs;
689     struct sudo_command *c;
690
691     while ((us = tq_pop(&userspecs)) != NULL) {
692         while ((m = tq_pop(&us->users)) != NULL) {
693             efree(m->name);
694             efree(m);
695         }
696         while ((priv = tq_pop(&us->privileges)) != NULL) {
697             struct member *runasuser = NULL, *runasgroup = NULL;
698 #ifdef HAVE_SELINUX
699             char *role = NULL, *type = NULL;
700 #endif /* HAVE_SELINUX */
701
702             while ((m = tq_pop(&priv->hostlist)) != NULL) {
703                 efree(m->name);
704                 efree(m);
705             }
706             while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
707 #ifdef HAVE_SELINUX
708                 /* Only free the first instance of a role/type. */
709                 if (cs->role != role) {
710                     role = cs->role;
711                     efree(cs->role);
712                 }
713                 if (cs->type != type) {
714                     type = cs->type;
715                     efree(cs->type);
716                 }
717 #endif /* HAVE_SELINUX */
718                 if (tq_last(&cs->runasuserlist) != runasuser) {
719                     runasuser = tq_last(&cs->runasuserlist);
720                     while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
721                         efree(m->name);
722                         efree(m);
723                     }
724                 }
725                 if (tq_last(&cs->runasgrouplist) != runasgroup) {
726                     runasgroup = tq_last(&cs->runasgrouplist);
727                     while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
728                         efree(m->name);
729                         efree(m);
730                     }
731                 }
732                 if (cs->cmnd->type == COMMAND) {
733                         c = (struct sudo_command *) cs->cmnd->name;
734                         efree(c->cmnd);
735                         efree(c->args);
736                 }
737                 efree(cs->cmnd->name);
738                 efree(cs->cmnd);
739                 efree(cs);
740             }
741             efree(priv);
742         }
743         efree(us);
744     }
745     tq_init(&userspecs);
746
747     binding = NULL;
748     while ((d = tq_pop(&defaults)) != NULL) {
749         if (tq_last(&d->binding) != binding) {
750             binding = tq_last(&d->binding);
751             while ((m = tq_pop(&d->binding)) != NULL) {
752                 if (m->type == COMMAND) {
753                         c = (struct sudo_command *) m->name;
754                         efree(c->cmnd);
755                         efree(c->args);
756                 }
757                 efree(m->name);
758                 efree(m);
759             }
760         }
761         efree(d->var);
762         efree(d->val);
763         efree(d);
764     }
765     tq_init(&defaults);
766
767     init_aliases();
768
769     init_lexer();
770
771     efree(sudoers);
772     sudoers = path ? estrdup(path) : NULL;
773
774     parse_error = FALSE;
775     errorlineno = -1;
776     errorfile = NULL;
777     sudolineno = 1;
778     verbose = !quiet;
779 }