provide that info if there is an error.
_\b/_\be_\bt_\bc_\b/_\bs_\bu_\bd_\bo_\be_\br_\bs_\b._\bt_\bm_\bp Lock file for visudo
D\bDI\bIA\bAG\bGN\bNO\bOS\bST\bTI\bIC\bCS\bS
+ In addition to reporting _\bs_\bu_\bd_\bo_\be_\br_\bs parse errors, v\bvi\bis\bsu\bud\bdo\bo may produce the
+ following messages:
+
sudoers file busy, try again later.
Someone else is currently editing the _\bs_\bu_\bd_\bo_\be_\br_\bs file.
/etc/sudoers.tmp: Permission denied
You didn't run v\bvi\bis\bsu\bud\bdo\bo as root.
- Can't find you in the passwd database
- Your user ID does not appear in the system passwd file.
+ you do not exist in the passwd database
+ Your user ID does not appear in the system passwd database.
- Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined
+ {User,Runas,Host,Cmnd}_Alias referenced but not defined
Either you are trying to use an undeclared
{User,Runas,Host,Cmnd}_Alias or you have a user or host name listed
that consists solely of uppercase letters, digits, and the
underscore (`_') character. In the latter case, you can ignore the
- warnings (s\bsu\bud\bdo\bo will not complain). In -\b-s\bs (strict) mode these are
- errors, not warnings.
+ warnings (s\bsu\bud\bdo\bo will not complain). The message is prefixed with
+ the path name of the _\bs_\bu_\bd_\bo_\be_\br_\bs file and the line number where the
+ undefined alias was used. In -\b-s\bs (strict) mode these are errors,
+ not warnings.
- Warning: unused {User,Runas,Host,Cmnd}_Alias
+ unused {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias was defined but never
- used. You may wish to comment out or remove the unused alias.
+ used. The message is prefixed with the path name of the _\bs_\bu_\bd_\bo_\be_\br_\bs
+ file and the line number where the unused alias was defined. You
+ may wish to comment out or remove the unused alias.
- Warning: cycle in {User,Runas,Host,Cmnd}_Alias
+ cycle in {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
- itself, either directly or through an alias it includes. This is
- only a warning by default as s\bsu\bud\bdo\bo will ignore cycles when parsing
- the _\bs_\bu_\bd_\bo_\be_\br_\bs file.
+ itself, either directly or through an alias it includes. The
+ message is prefixed with the path name of the _\bs_\bu_\bd_\bo_\be_\br_\bs file and the
+ line number where the cycle was detected. This is only a warning
+ unless v\bvi\bis\bsu\bud\bdo\bo is run in -\b-s\bs (strict) mode as s\bsu\bud\bdo\bo will ignore cycles
+ when parsing the _\bs_\bu_\bd_\bo_\be_\br_\bs file.
+
+ unknown defaults entry "name"
+ The _\bs_\bu_\bd_\bo_\be_\br_\bs file contains a Defaults variable not recognized by
+ v\bvi\bis\bsu\bud\bdo\bo.
- visudo: /etc/sudoers: input and output files must be different
+ /etc/sudoers: input and output files must be different
The -\b-x\bx flag was used and the specified _\bo_\bu_\bt_\bp_\bu_\bt_\b__\bf_\bi_\bl_\be has the same
path name as the _\bs_\bu_\bd_\bo_\be_\br_\bs file to export.
file distributed with s\bsu\bud\bdo\bo or https://www.sudo.ws/license.html for
complete details.
-Sudo 1.8.18 November 20, 2015 Sudo 1.8.18
+Sudo 1.8.19 November 12, 2016 Sudo 1.8.19
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
-.TH "VISUDO" "8" "November 20, 2015" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
+.TH "VISUDO" "8" "November 12, 2016" "Sudo @PACKAGE_VERSION@" "System Manager's Manual"
.nh
.if n .ad l
.SH "NAME"
\fI@sysconfdir@/sudoers.tmp\fR
Lock file for visudo
.SH "DIAGNOSTICS"
+In addition to reporting
+\fIsudoers\fR
+parse errors,
+\fBvisudo\fR
+may produce the following messages:
.TP 6n
\fRsudoers file busy, try again later.\fR
Someone else is currently editing the
\fBvisudo\fR
as root.
.TP 6n
-\fRCan't find you in the passwd database\fR
-Your user ID does not appear in the system passwd file.
+\fRyou do not exist in the passwd database\fR
+Your user ID does not appear in the system passwd database.
.TP 6n
-\fRWarning: {User,Runas,Host,Cmnd}_Alias referenced but not defined\fR
+\fR{User,Runas,Host,Cmnd}_Alias referenced but not defined\fR
Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
or you have a user or host name listed that consists solely of
uppercase letters, digits, and the underscore
(\fBsudo\fR
will not complain)
\&.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the undefined alias was used.
In
\fB\-s\fR
(strict) mode these are errors, not warnings.
.TP 6n
-\fRWarning: unused {User,Runas,Host,Cmnd}_Alias\fR
+\fRunused {User,Runas,Host,Cmnd}_Alias\fR
The specified {User,Runas,Host,Cmnd}_Alias was defined but never
used.
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the unused alias was defined.
You may wish to comment out or remove the unused alias.
.TP 6n
-\fRWarning: cycle in {User,Runas,Host,Cmnd}_Alias\fR
+\fRcycle in {User,Runas,Host,Cmnd}_Alias\fR
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
itself, either directly or through an alias it includes.
-This is only a warning by default as
+The message is prefixed with the path name of the
+\fIsudoers\fR
+file and the line number where the cycle was detected.
+This is only a warning unless
+\fBvisudo\fR
+is run in
+\fB\-s\fR
+(strict) mode as
\fBsudo\fR
will ignore cycles when parsing
the
\fIsudoers\fR
file.
.TP 6n
-\fRvisudo: @sysconfdir@/sudoers: input and output files must be different\fR
+\fRunknown defaults entry \&"name\&"\fR
+The
+\fIsudoers\fR
+file contains a
+\fRDefaults\fR
+variable not recognized by
+\fBvisudo\fR.
+.TP 6n
+\fR@sysconfdir@/sudoers: input and output files must be different\fR
The
\fB\-x\fR
flag was used and the specified
.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
.\"
-.Dd November 20, 2015
+.Dd November 12, 2016
.Dt VISUDO @mansectsu@
.Os Sudo @PACKAGE_VERSION@
.Sh NAME
Lock file for visudo
.El
.Sh DIAGNOSTICS
+In addition to reporting
+.Em sudoers
+parse errors,
+.Nm
+may produce the following messages:
.Bl -tag -width 4n
.It Li sudoers file busy, try again later.
Someone else is currently editing the
You didn't run
.Nm
as root.
-.It Li Can't find you in the passwd database
-Your user ID does not appear in the system passwd file.
-.It Li Warning: {User,Runas,Host,Cmnd}_Alias referenced but not defined
+.It Li you do not exist in the passwd database
+Your user ID does not appear in the system passwd database.
+.It Li {User,Runas,Host,Cmnd}_Alias referenced but not defined
Either you are trying to use an undeclared {User,Runas,Host,Cmnd}_Alias
or you have a user or host name listed that consists solely of
uppercase letters, digits, and the underscore
.Nm sudo
will not complain
.Pc .
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the undefined alias was used.
In
.Fl s
(strict) mode these are errors, not warnings.
-.It Li Warning: unused {User,Runas,Host,Cmnd}_Alias
+.It Li unused {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias was defined but never
used.
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the unused alias was defined.
You may wish to comment out or remove the unused alias.
-.It Li Warning: cycle in {User,Runas,Host,Cmnd}_Alias
+.It Li cycle in {User,Runas,Host,Cmnd}_Alias
The specified {User,Runas,Host,Cmnd}_Alias includes a reference to
itself, either directly or through an alias it includes.
-This is only a warning by default as
+The message is prefixed with the path name of the
+.Em sudoers
+file and the line number where the cycle was detected.
+This is only a warning unless
+.Nm
+is run in
+.Fl s
+(strict) mode as
.Nm sudo
will ignore cycles when parsing
the
.Em sudoers
file.
-.It Li visudo: @sysconfdir@/sudoers: input and output files must be different
+.It Li unknown defaults entry \&"name\&"
+The
+.Em sudoers
+file contains a
+.Li Defaults
+variable not recognized by
+.Nm .
+.It Li @sysconfdir@/sudoers: input and output files must be different
The
.Fl x
flag was used and the specified
/*
- * Copyright (c) 2004-2005, 2007-2015
+ * Copyright (c) 2004-2005, 2007-2016
* Todd C. Miller <Todd.Miller@courtesan.com>
*
* Permission to use, copy, modify, and distribute this software for any
/*
* Add an alias to the aliases redblack tree.
+ * Note that "file" must be a reference-counted string.
* Returns NULL on success and an error string on failure.
*/
const char *
-alias_add(char *name, int type, struct member *members)
+alias_add(char *name, int type, char *file, int lineno, struct member *members)
{
static char errbuf[512];
struct alias *a;
a->name = name;
a->type = type;
/* a->used = false; */
+ a->file = rcstr_addref(file);
+ a->lineno = lineno;
HLTQ_TO_TAILQ(&a->members, members, entries);
switch (rbinsert(aliases, a, NULL)) {
case 1:
debug_decl(alias_free, SUDOERS_DEBUG_ALIAS)
free(a->name);
+ rcstr_delref(a->file);
free_members(&a->members);
free(a);
#include "parse.h"
#include "toke.h"
+/* If we last saw a newline the entry is on the preceding line. */
+#define this_lineno (last_token == COMMENT ? sudolineno - 1 : sudolineno)
+
/*
* Globals
*/
static struct defaults *new_default(char *, char *, short);
static struct member *new_member(char *, int);
static struct sudo_digest *new_digest(int, const char *);
-#line 73 "gram.y"
+#line 76 "gram.y"
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {
int tok;
} YYSTYPE;
#endif /* YYSTYPE_DEFINED */
-#line 127 "gram.c"
+#line 130 "gram.c"
#define COMMAND 257
#define ALIAS 258
#define DEFVAR 259
YYSTYPE *yyvs;
unsigned int yystacksize;
int yyparse(void);
-#line 849 "gram.y"
+#line 856 "gram.y"
void
sudoerserror(const char *s)
{
debug_decl(sudoerserror, SUDOERS_DEBUG_PARSER)
- /* If we last saw a newline the error is on the preceding line. */
- if (last_token == COMMENT)
- sudolineno--;
-
/* Save the line the first error occurred on. */
if (errorlineno == -1) {
- errorlineno = sudolineno;
+ errorlineno = this_lineno;
rcstr_delref(errorfile);
errorfile = rcstr_addref(sudoers);
}
/* Warnings are displayed in the user's locale. */
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
- sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), sudolineno);
+ sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), this_lineno);
sudoers_setlocale(oldlocale, NULL);
}
#endif
/* d->type = 0; */
d->op = op;
/* d->binding = NULL */
- d->lineno = last_token == COMMENT ? sudolineno - 1 : sudolineno;
+ d->lineno = this_lineno;
d->file = rcstr_addref(sudoers);
HLTQ_INIT(d, entries);
"unable to allocate memory");
debug_return_bool(false);
}
+ u->lineno = this_lineno;
+ u->file = rcstr_addref(sudoers);
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
+ /* XXX - move into a free function */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) {
struct member *m, *m_next;
struct privilege *priv, *priv_next;
}
free(priv);
}
+ rcstr_delref(us->file);
free(us);
}
TAILQ_INIT(&userspecs);
debug_return_bool(ret);
}
-#line 955 "gram.c"
+#line 958 "gram.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void)
switch (yyn)
{
case 1:
-#line 167 "gram.y"
+#line 170 "gram.y"
{ ; }
break;
case 5:
-#line 175 "gram.y"
+#line 178 "gram.y"
{
;
}
break;
case 6:
-#line 178 "gram.y"
+#line 181 "gram.y"
{
yyerrok;
}
break;
case 7:
-#line 181 "gram.y"
+#line 184 "gram.y"
{
if (!add_userspec(yyvsp[-1].member, yyvsp[0].privilege)) {
sudoerserror(N_("unable to allocate memory"));
}
break;
case 8:
-#line 187 "gram.y"
+#line 190 "gram.y"
{
;
}
break;
case 9:
-#line 190 "gram.y"
+#line 193 "gram.y"
{
;
}
break;
case 10:
-#line 193 "gram.y"
+#line 196 "gram.y"
{
;
}
break;
case 11:
-#line 196 "gram.y"
+#line 199 "gram.y"
{
;
}
break;
case 12:
-#line 199 "gram.y"
+#line 202 "gram.y"
{
if (!add_defaults(DEFAULTS, NULL, yyvsp[0].defaults))
YYERROR;
}
break;
case 13:
-#line 203 "gram.y"
+#line 206 "gram.y"
{
if (!add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 14:
-#line 207 "gram.y"
+#line 210 "gram.y"
{
if (!add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 15:
-#line 211 "gram.y"
+#line 214 "gram.y"
{
if (!add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 16:
-#line 215 "gram.y"
+#line 218 "gram.y"
{
if (!add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults))
YYERROR;
}
break;
case 18:
-#line 222 "gram.y"
+#line 225 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].defaults, yyvsp[0].defaults, entries);
yyval.defaults = yyvsp[-2].defaults;
}
break;
case 19:
-#line 228 "gram.y"
+#line 231 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, true);
if (yyval.defaults == NULL) {
}
break;
case 20:
-#line 235 "gram.y"
+#line 238 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, false);
if (yyval.defaults == NULL) {
}
break;
case 21:
-#line 242 "gram.y"
+#line 245 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, true);
if (yyval.defaults == NULL) {
}
break;
case 22:
-#line 249 "gram.y"
+#line 252 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
if (yyval.defaults == NULL) {
}
break;
case 23:
-#line 256 "gram.y"
+#line 259 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
if (yyval.defaults == NULL) {
}
break;
case 25:
-#line 266 "gram.y"
+#line 269 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].privilege, yyvsp[0].privilege, entries);
yyval.privilege = yyvsp[-2].privilege;
}
break;
case 26:
-#line 272 "gram.y"
+#line 275 "gram.y"
{
struct privilege *p = calloc(1, sizeof(*p));
if (p == NULL) {
}
break;
case 27:
-#line 285 "gram.y"
+#line 288 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 28:
-#line 289 "gram.y"
+#line 292 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 29:
-#line 295 "gram.y"
+#line 298 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
}
break;
case 30:
-#line 302 "gram.y"
+#line 305 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 31:
-#line 309 "gram.y"
+#line 312 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
}
break;
case 32:
-#line 316 "gram.y"
+#line 319 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
if (yyval.member == NULL) {
}
break;
case 33:
-#line 323 "gram.y"
+#line 326 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
break;
case 35:
-#line 333 "gram.y"
+#line 336 "gram.y"
{
struct cmndspec *prev;
prev = HLTQ_LAST(yyvsp[-2].cmndspec, cmndspec, entries);
}
break;
case 36:
-#line 378 "gram.y"
+#line 381 "gram.y"
{
struct cmndspec *cs = calloc(1, sizeof(*cs));
if (cs == NULL) {
}
break;
case 37:
-#line 426 "gram.y"
+#line 429 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA224, yyvsp[0].string);
if (yyval.digest == NULL) {
}
break;
case 38:
-#line 433 "gram.y"
+#line 436 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA256, yyvsp[0].string);
if (yyval.digest == NULL) {
}
break;
case 39:
-#line 440 "gram.y"
+#line 443 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA384, yyvsp[0].string);
if (yyval.digest == NULL) {
}
break;
case 40:
-#line 447 "gram.y"
+#line 450 "gram.y"
{
yyval.digest = new_digest(SUDO_DIGEST_SHA512, yyvsp[0].string);
if (yyval.digest == NULL) {
}
break;
case 41:
-#line 456 "gram.y"
+#line 459 "gram.y"
{
yyval.member = yyvsp[0].member;
}
break;
case 42:
-#line 459 "gram.y"
+#line 462 "gram.y"
{
if (yyvsp[0].member->type != COMMAND) {
sudoerserror(N_("a digest requires a path name"));
}
break;
case 43:
-#line 470 "gram.y"
+#line 473 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 44:
-#line 474 "gram.y"
+#line 477 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 45:
-#line 480 "gram.y"
+#line 483 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 46:
-#line 485 "gram.y"
+#line 488 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 47:
-#line 490 "gram.y"
+#line 493 "gram.y"
{
yyval.seinfo.role = NULL;
yyval.seinfo.type = NULL;
}
break;
case 48:
-#line 494 "gram.y"
+#line 497 "gram.y"
{
yyval.seinfo.role = yyvsp[0].string;
yyval.seinfo.type = NULL;
}
break;
case 49:
-#line 498 "gram.y"
+#line 501 "gram.y"
{
yyval.seinfo.type = yyvsp[0].string;
yyval.seinfo.role = NULL;
}
break;
case 50:
-#line 502 "gram.y"
+#line 505 "gram.y"
{
yyval.seinfo.role = yyvsp[-1].string;
yyval.seinfo.type = yyvsp[0].string;
}
break;
case 51:
-#line 506 "gram.y"
+#line 509 "gram.y"
{
yyval.seinfo.type = yyvsp[-1].string;
yyval.seinfo.role = yyvsp[0].string;
}
break;
case 52:
-#line 512 "gram.y"
+#line 515 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 53:
-#line 516 "gram.y"
+#line 519 "gram.y"
{
yyval.string = yyvsp[0].string;
}
break;
case 54:
-#line 521 "gram.y"
+#line 524 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = NULL;
}
break;
case 55:
-#line 525 "gram.y"
+#line 528 "gram.y"
{
yyval.privinfo.privs = yyvsp[0].string;
yyval.privinfo.limitprivs = NULL;
}
break;
case 56:
-#line 529 "gram.y"
+#line 532 "gram.y"
{
yyval.privinfo.privs = NULL;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 57:
-#line 533 "gram.y"
+#line 536 "gram.y"
{
yyval.privinfo.privs = yyvsp[-1].string;
yyval.privinfo.limitprivs = yyvsp[0].string;
}
break;
case 58:
-#line 537 "gram.y"
+#line 540 "gram.y"
{
yyval.privinfo.limitprivs = yyvsp[-1].string;
yyval.privinfo.privs = yyvsp[0].string;
}
break;
case 59:
-#line 543 "gram.y"
+#line 546 "gram.y"
{
yyval.runas = NULL;
}
break;
case 60:
-#line 546 "gram.y"
+#line 549 "gram.y"
{
yyval.runas = yyvsp[-1].runas;
}
break;
case 61:
-#line 551 "gram.y"
+#line 554 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) {
}
break;
case 62:
-#line 566 "gram.y"
+#line 569 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 63:
-#line 575 "gram.y"
+#line 578 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 64:
-#line 584 "gram.y"
+#line 587 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas == NULL) {
}
break;
case 65:
-#line 593 "gram.y"
+#line 596 "gram.y"
{
yyval.runas = calloc(1, sizeof(struct runascontainer));
if (yyval.runas != NULL) {
}
break;
case 66:
-#line 610 "gram.y"
+#line 613 "gram.y"
{
TAGS_INIT(yyval.tag);
}
break;
case 67:
-#line 613 "gram.y"
+#line 616 "gram.y"
{
yyval.tag.nopasswd = true;
}
break;
case 68:
-#line 616 "gram.y"
+#line 619 "gram.y"
{
yyval.tag.nopasswd = false;
}
break;
case 69:
-#line 619 "gram.y"
+#line 622 "gram.y"
{
yyval.tag.noexec = true;
}
break;
case 70:
-#line 622 "gram.y"
+#line 625 "gram.y"
{
yyval.tag.noexec = false;
}
break;
case 71:
-#line 625 "gram.y"
+#line 628 "gram.y"
{
yyval.tag.setenv = true;
}
break;
case 72:
-#line 628 "gram.y"
+#line 631 "gram.y"
{
yyval.tag.setenv = false;
}
break;
case 73:
-#line 631 "gram.y"
+#line 634 "gram.y"
{
yyval.tag.log_input = true;
}
break;
case 74:
-#line 634 "gram.y"
+#line 637 "gram.y"
{
yyval.tag.log_input = false;
}
break;
case 75:
-#line 637 "gram.y"
+#line 640 "gram.y"
{
yyval.tag.log_output = true;
}
break;
case 76:
-#line 640 "gram.y"
+#line 643 "gram.y"
{
yyval.tag.log_output = false;
}
break;
case 77:
-#line 643 "gram.y"
+#line 646 "gram.y"
{
yyval.tag.follow = true;
}
break;
case 78:
-#line 646 "gram.y"
+#line 649 "gram.y"
{
yyval.tag.follow = false;
}
break;
case 79:
-#line 649 "gram.y"
+#line 652 "gram.y"
{
yyval.tag.send_mail = true;
}
break;
case 80:
-#line 652 "gram.y"
+#line 655 "gram.y"
{
yyval.tag.send_mail = false;
}
break;
case 81:
-#line 657 "gram.y"
+#line 660 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 82:
-#line 664 "gram.y"
+#line 667 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
}
break;
case 83:
-#line 671 "gram.y"
+#line 674 "gram.y"
{
struct sudo_command *c = calloc(1, sizeof(*c));
if (c == NULL) {
}
break;
case 86:
-#line 692 "gram.y"
+#line 695 "gram.y"
{
const char *s;
- if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) {
+ s = alias_add(yyvsp[-2].string, HOSTALIAS, sudoers, this_lineno, yyvsp[0].member);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
}
break;
case 88:
-#line 702 "gram.y"
+#line 706 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 91:
-#line 712 "gram.y"
+#line 716 "gram.y"
{
const char *s;
- if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) {
+ s = alias_add(yyvsp[-2].string, CMNDALIAS, sudoers, this_lineno, yyvsp[0].member);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
}
break;
case 93:
-#line 722 "gram.y"
+#line 727 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 96:
-#line 732 "gram.y"
+#line 737 "gram.y"
{
const char *s;
- if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) {
+ s = alias_add(yyvsp[-2].string, RUNASALIAS, sudoers, this_lineno, yyvsp[0].member);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
}
break;
case 99:
-#line 745 "gram.y"
+#line 751 "gram.y"
{
const char *s;
- if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) {
+ s = alias_add(yyvsp[-2].string, USERALIAS, sudoers, this_lineno, yyvsp[0].member);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
}
break;
case 101:
-#line 755 "gram.y"
+#line 762 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 102:
-#line 761 "gram.y"
+#line 768 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 103:
-#line 765 "gram.y"
+#line 772 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 104:
-#line 771 "gram.y"
+#line 778 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
}
break;
case 105:
-#line 778 "gram.y"
+#line 785 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 106:
-#line 785 "gram.y"
+#line 792 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
if (yyval.member == NULL) {
}
break;
case 107:
-#line 792 "gram.y"
+#line 799 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
if (yyval.member == NULL) {
}
break;
case 108:
-#line 799 "gram.y"
+#line 806 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
break;
case 110:
-#line 809 "gram.y"
+#line 816 "gram.y"
{
HLTQ_CONCAT(yyvsp[-2].member, yyvsp[0].member, entries);
yyval.member = yyvsp[-2].member;
}
break;
case 111:
-#line 815 "gram.y"
+#line 822 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = false;
}
break;
case 112:
-#line 819 "gram.y"
+#line 826 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = true;
}
break;
case 113:
-#line 825 "gram.y"
+#line 832 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
if (yyval.member == NULL) {
}
break;
case 114:
-#line 832 "gram.y"
+#line 839 "gram.y"
{
yyval.member = new_member(NULL, ALL);
if (yyval.member == NULL) {
}
break;
case 115:
-#line 839 "gram.y"
+#line 846 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
if (yyval.member == NULL) {
}
}
break;
-#line 2038 "gram.c"
+#line 2045 "gram.c"
}
yyssp -= yym;
yystate = *yyssp;
#include "parse.h"
#include "toke.h"
+/* If we last saw a newline the entry is on the preceding line. */
+#define this_lineno (last_token == COMMENT ? sudolineno - 1 : sudolineno)
+
/*
* Globals
*/
hostalias : ALIAS '=' hostlist {
const char *s;
- if ((s = alias_add($1, HOSTALIAS, $3)) != NULL) {
+ s = alias_add($1, HOSTALIAS, sudoers, this_lineno, $3);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
cmndalias : ALIAS '=' cmndlist {
const char *s;
- if ((s = alias_add($1, CMNDALIAS, $3)) != NULL) {
+ s = alias_add($1, CMNDALIAS, sudoers, this_lineno, $3);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
runasalias : ALIAS '=' userlist {
const char *s;
- if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) {
+ s = alias_add($1, RUNASALIAS, sudoers, this_lineno, $3);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
useralias : ALIAS '=' userlist {
const char *s;
- if ((s = alias_add($1, USERALIAS, $3)) != NULL) {
+ s = alias_add($1, USERALIAS, sudoers, this_lineno, $3);
+ if (s != NULL) {
sudoerserror(s);
YYERROR;
}
{
debug_decl(sudoerserror, SUDOERS_DEBUG_PARSER)
- /* If we last saw a newline the error is on the preceding line. */
- if (last_token == COMMENT)
- sudolineno--;
-
/* Save the line the first error occurred on. */
if (errorlineno == -1) {
- errorlineno = sudolineno;
+ errorlineno = this_lineno;
rcstr_delref(errorfile);
errorfile = rcstr_addref(sudoers);
}
/* Warnings are displayed in the user's locale. */
sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
- sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), sudolineno);
+ sudo_printf(SUDO_CONV_ERROR_MSG, _(fmt), sudoers, _(s), this_lineno);
sudoers_setlocale(oldlocale, NULL);
}
#endif
/* d->type = 0; */
d->op = op;
/* d->binding = NULL */
- d->lineno = last_token == COMMENT ? sudolineno - 1 : sudolineno;
+ d->lineno = this_lineno;
d->file = rcstr_addref(sudoers);
HLTQ_INIT(d, entries);
"unable to allocate memory");
debug_return_bool(false);
}
+ u->lineno = this_lineno;
+ u->file = rcstr_addref(sudoers);
HLTQ_TO_TAILQ(&u->users, members, entries);
HLTQ_TO_TAILQ(&u->privileges, privs, entries);
TAILQ_INSERT_TAIL(&userspecs, u, entries);
bool ret = true;
debug_decl(init_parser, SUDOERS_DEBUG_PARSER)
+ /* XXX - move into a free function */
TAILQ_FOREACH_SAFE(us, &userspecs, entries, us_next) {
struct member *m, *m_next;
struct privilege *priv, *priv_next;
}
free(priv);
}
+ rcstr_delref(us->file);
free(us);
}
TAILQ_INIT(&userspecs);
TAILQ_ENTRY(userspec) entries;
struct member_list users; /* list of users */
struct privilege_list privileges; /* list of privileges */
+ int lineno;
+ char *file;
};
/*
struct alias {
char *name; /* alias name */
unsigned short type; /* {USER,HOST,RUNAS,CMND}ALIAS */
- bool used; /* "used" flag for cycle detection */
+ short used; /* "used" flag for cycle detection */
+ int lineno; /* line number of alias entry */
+ char *file; /* file the alias entry was in */
struct member_list members; /* list of alias members */
};
/* alias.c */
bool no_aliases(void);
-const char *alias_add(char *name, int type, struct member *members);
+const char *alias_add(char *name, int type, char *file, int lineno, struct member *members);
int alias_compare(const void *a1, const void *a2);
struct alias *alias_get(char *name, int type);
struct alias *alias_remove(char *name, int type);
-visudo: Error: cycle in User_Alias "FOO"
+visudo: stdin:1 cycle in User_Alias "FOO"
-visudo: Warning: unused User_Alias "A"
-visudo: Warning: unused User_Alias "B"
+visudo: stdin:1 unused User_Alias "A"
+visudo: stdin:2 unused User_Alias "B"
static void quit(int);
static void get_hostname(void);
static int whatnow(void);
-static int check_aliases(bool, bool);
+static int check_aliases(bool strict, bool quiet);
static char *get_editor(int *editor_argc, char ***editor_argv);
static bool check_syntax(const char *, bool, bool, bool);
static bool edit_sudoers(struct sudoersfile *, char *, int, char **, int);
}
static int
-check_alias(char *name, int type, int strict, int quiet)
+check_alias(char *name, int type, char *file, int lineno, bool quiet)
{
struct member *m;
struct alias *a;
if ((a = alias_get(name, type)) != NULL) {
/* check alias contents */
TAILQ_FOREACH(m, &a->members, entries) {
- if (m->type == ALIAS)
- errors += check_alias(m->name, type, strict, quiet);
+ if (m->type != ALIAS)
+ continue;
+ errors += check_alias(m->name, type, a->file, a->lineno, quiet);
}
alias_put(a);
} else {
if (!quiet) {
if (errno == ELOOP) {
- sudo_warnx(strict ?
- U_("Error: cycle in %s \"%s\"") :
- U_("Warning: cycle in %s \"%s\""),
- alias_type_to_string(type), name);
+ sudo_warnx(U_("%s:%d cycle in %s \"%s\""),
+ file, lineno, alias_type_to_string(type), name);
} else {
- sudo_warnx(strict ?
- U_("Error: %s \"%s\" referenced but not defined") :
- U_("Warning: %s \"%s\" referenced but not defined"),
- alias_type_to_string(type), name);
+ sudo_warnx(U_("%s:%d %s \"%s\" referenced but not defined"),
+ file, lineno, alias_type_to_string(type), name);
}
}
errors++;
TAILQ_FOREACH(us, &userspecs, entries) {
TAILQ_FOREACH(m, &us->users, entries) {
if (m->type == ALIAS) {
- errors += check_alias(m->name, USERALIAS, strict, quiet);
+ errors += check_alias(m->name, USERALIAS,
+ us->file, us->lineno, quiet);
}
}
TAILQ_FOREACH(priv, &us->privileges, entries) {
TAILQ_FOREACH(m, &priv->hostlist, entries) {
if (m->type == ALIAS) {
- errors += check_alias(m->name, HOSTALIAS, strict, quiet);
+ errors += check_alias(m->name, HOSTALIAS,
+ us->file, us->lineno, quiet);
}
}
TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
if (cs->runasuserlist != NULL) {
TAILQ_FOREACH(m, cs->runasuserlist, entries) {
if (m->type == ALIAS) {
- errors += check_alias(m->name, RUNASALIAS, strict, quiet);
+ errors += check_alias(m->name, RUNASALIAS,
+ us->file, us->lineno, quiet);
}
}
}
if (cs->runasgrouplist != NULL) {
TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
if (m->type == ALIAS) {
- errors += check_alias(m->name, RUNASALIAS, strict, quiet);
+ errors += check_alias(m->name, RUNASALIAS,
+ us->file, us->lineno, quiet);
}
}
}
if ((m = cs->cmnd)->type == ALIAS) {
- errors += check_alias(m->name, CMNDALIAS, strict, quiet);
+ errors += check_alias(m->name, CMNDALIAS,
+ us->file, us->lineno, quiet);
}
}
}
{
struct alias *a = (struct alias *)v1;
- sudo_warnx_nodebug(U_("Warning: unused %s \"%s\""),
- alias_type_to_string(a->type), a->name);
+ sudo_warnx_nodebug(U_("%s:%d unused %s \"%s\""),
+ a->file, a->lineno, alias_type_to_string(a->type), a->name);
return 0;
}