* about m4 quoting &c., but we have to #include it so that the C
* objects from the lexer are available.
*
- * Copyright (C)1996-1997 Ian Jackson
+ * Copyright (C)1996-1999 Ian Jackson
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
tstate->filename,tstate->reportlineno);
}
-void parseerrprint(const char *fmt, ...) {
+int parseerrprint(const char *fmt, ...) {
va_list al;
char errmsg[MAX_ERRMSG_LEN];
vsnytprintfcat(errmsg,sizeof(errmsg),fmt,al);
senderrmsg(errmsg,eh.handling);
va_end(al);
+
+ return tokv_error;
}
static int unexpected(int found, int wanted, const char *wantedstr) {
*/
if (found == wanted) return 0;
if (found == tokv_error) return found;
- parseerrprint("found %s, expected %s",printtoken(found),wantedstr);
- return tokv_error;
+ return parseerrprint("found %s, expected %s",printtoken(found),wantedstr);
}
static int stringoverflow(const char *where) {
- parseerrprint("string buffer became far too large building %s",where);
- return tokv_error;
+ return parseerrprint("string buffer became far too large building %s",where);
}
/*
free(array);
}
+static void countnewlines(void) {
+ char *p;
+ for (p=yytext; *p; p++)
+ if (*p == '\n')
+ cstate->lineno++;
+}
+
static int dequote(char *inplace) {
char *p, *q, buf[4], *bep;
int v;
-
+
p=q=inplace;
assert(*p++ = '"');
while (*p && *p != '"') {
if (*p != '\\') { *q++= *p++; continue; }
switch (*++p) {
- case 'n': *q++= '\n'; continue;
- case 'r': *q++= '\r'; continue;
- case 't': *q++= '\t'; continue;
+ case 'n': *q++= '\n'; p++; continue;
+ case 'r': *q++= '\r'; p++; continue;
+ case 't': *q++= '\t'; p++; continue;
case 'x':
- assert(buf[0]= *++p); assert(buf[1]= *++p); buf[2]= 0;
- v= strtoul(buf,&bep,16); assert(bep == buf+2);
- assert(!(v & ~0xff)); *q++= v; p++; continue;
+ p++;
+ if (!((buf[0]= *p++) && (buf[1]= *p++)))
+ return parseerrprint("quoted string ends inside \\x<hex> sequence");
+ buf[2]= 0;
+ v= strtoul(buf,&bep,16);
+ if (bep != buf+2)
+ return parseerrprint("invalid \\<hex> sequence \\x%s in quoted string",buf);
+ assert(!(v & ~0xff));
+ *q++= v;
+ continue;
default:
- if (isalpha(*p)) {
- parseerrprint("unknown \\<letter> sequence \\%c in quoted string",*p);
- return tokv_error;
- } else if (isdigit(*p)) {
- assert(buf[0]= *++p); assert(buf[1]= *++p); assert(buf[2]= *++p);
+ if (ISCHAR(isalpha,*p))
+ return parseerrprint("unknown \\<letter> sequence \\%c in quoted string",*p);
+ if (ISCHAR(isdigit,*p)) {
+ if (!((buf[0]= *p++) && (buf[1]= *p++) && (buf[2]= *p++))) abort();
buf[3]= 0; v= strtoul(buf,&bep,8);
- if (bep != buf+3 || (v & ~0xff)); {
- parseerrprint("invalid \\<octal> sequence \\%s in quoted string",buf);
- return tokv_error;
- }
- *q++= v; p++; continue;
- } else if (ispunct(*p)) {
+ if (bep != buf+3 || (v & ~0xff))
+ return parseerrprint("invalid \\<octal> sequence \\%s in quoted string",buf);
+ *q++= v; continue;
+ } else if (ISCHAR(ispunct,*p)) {
*q++= *p++; continue;
} else {
while (*p==' ' || *p=='\t') p++;
- assert(*p=='\n');
+ v= *p++; assert(v=='\n');
}
}
}
l= strlen(buf); i= sizeof(buf)-l-2; p= yytext; q= buf+l;
while ((c= *p++)) {
if (i-- <= 0) { q--; strcpy(q-3,"..."); break; }
- if (isspace(c)) c= ' ';
- else if (!isprint(c) || iscntrl(c)) c= '?';
+ if (ISCHAR(isspace,c)) c= ' ';
+ else if (!ISCHAR(isprint,c) || ISCHAR(iscntrl,c)) c= '?';
else *q++= c;
}
strcpy(q,"'");
}
if (used>=size) {
if (used >= MAX_ARGSDEFVAR) {
- parseerrprint("far too many arguments to service program");
- r= tokv_error; goto error;
+ r= parseerrprint("far too many arguments to service program");
+ goto error;
}
size= (used+5)<<1;
newargs= xrealloc(newargs,sizeof(char*)*(size+1));
/* Returned value is invalidated by repeated calls. */
static char *buildbuf;
static int buildbuflen;
+ const char *usetext;
int r, tl;
buildbuf[0]= 0;
for (;;) {
r= yylex(); if (r == tokv_error) return r;
- if (r == tokv_eof) {
- parseerrprint("unexpected end of file in message text");
- return tokv_error;
- }
+ if (r == tokv_eof)
+ return parseerrprint("unexpected end of file in message text");
if (r == tokv_newline) break;
- tl+= strlen(yytext);
+ usetext= r == tokv_lwsp ? " " : yytext;
+ tl+= strlen(usetext);
if (makeroom(&buildbuf,&buildbuflen,tl)) return stringoverflow("message");
- strcat(buildbuf,yytext);
+ strcat(buildbuf,usetext);
}
*message_r= buildbuf;
return 0;
if (token == tokv_newline) return 0;
if (token == tokv_error) return token;
assert(token == tokv_eof);
- parseerrprint("unexpected end of file while looking for end of line");
- return tokv_error;
+ return parseerrprint("unexpected end of file while looking for end of line");
}
static int skip(int allowce) {
r= skip(token); if (r & tokt_exception) return r;
}
} else if (!(token & tokt_directive) && !(token & tokt_condop)) {
- parseerrprint("not a directive (or conditional operator) "
- "while looking for control structure end");
- return tokv_error;
+ return parseerrprint("not a directive (or conditional operator) "
+ "while looking for control structure end");
}
r= skiptoeol(); if (r) return r;
}
}
static int pf_callinguser(int ptoken, char ***rvalues) {
- return parm_usernameuid(rvalues,logname,request_mbuf.callinguid);
+ return parm_usernameuid(rvalues,loginname,request_mbuf.callinguid);
}
static int pf_serviceuser(int ptoken, char ***rvalues) {
r= paa_1path(&cp); if (r) return r;
file= fopen(cp,"r");
- if (!file) {
- parseerrprint("unable to open file `%s' for grep: %s",cp,strerror(errno));
- return tokv_error;
- }
+ if (!file)
+ return parseerrprint("unable to open file `%s' for grep: %s",cp,strerror(errno));
maxlen= 0;
for (pp= pv; *pp; pp++) { l= strlen(*pp); if (l > maxlen) maxlen= l; }
buf= xmalloc(maxlen+2); actrue= 0; c= 0;
while (!actrue && c!=EOF) {
c= getc(file); if (c==EOF) break;
- if (isspace(c)) continue;
+ if (ISCHAR(isspace,c)) continue;
l= maxlen+1; p= buf;
while (l>0 && c!='\n' && c!=EOF) { *p++= c; l--; c= getc(file); }
- if (c=='\n' || c==EOF || isspace(c)) {
- while (p>buf && isspace(p[-1])) --p;
+ if (c=='\n' || c==EOF || ISCHAR(isspace,c)) {
+ while (p>buf && ISCHAR(isspace,p[-1])) --p;
*p= 0; posstrue= 0;
for (pp= pv; !posstrue && *pp; pp++)
if (!strcmp(*pp,buf)) posstrue= 1;
for (;;) {
c= getc(file);
if (c==EOF || c=='\n') break;
- if (!isspace(c)) posstrue= 0;
+ if (!ISCHAR(isspace,c)) posstrue= 0;
}
}
if (posstrue) actrue= 1;
r= paa_pathargs(&rv,&newargs); if (r) return r;
p= strrchr(service,'/'); if (p) p++; else p= service;
- if (!*p || !isalnum(*p)) {
+ if (!*p || !ISCHAR(isalnum,*p)) {
parseerrprint("execute-from-directory requires initial char of service "
"portion to be alphanumeric (service portion was `%s')",
p);
return tokv_error;
}
for (q=p+1; *q; q++) {
- if (!isalnum(*q) && *q != '-') {
+ if (!ISCHAR(isalnum,*q) && *q != '-') {
parseerrprint("execute-from-directory requires service portion to "
"contain only alphanumerics and hyphens (was `%s')",
p);
r= pa_mnl(); if (r) return r;
r= parse_string(RESET_CONFIGURATION,"<builtin reset configuration>",1);
- assert(!r);
- return 0;
+ return r;
}
int dfg_fdwant(int dtoken) {
if (!(r & tokt_fdrange)) return unexpected(r,-1,"file descriptor range");
fdmin= lr_min; fdmax= lr_max;
if (fdmin<0 || fdmin>MAX_ALLOW_FD ||
- (fdmax != -1 && fdmax<0) || fdmax>MAX_ALLOW_FD) {
- parseerrprint("file descriptor in range is negative or far too large");
- return tokv_error;
- }
+ (fdmax != -1 && fdmax<0) || fdmax>MAX_ALLOW_FD)
+ return parseerrprint("file descriptor in range is negative or far too large");
r= yylex(); if (r == tokv_error) return r;
if (r == tokv_newline) {
- if (needreadwrite > 0) {
- parseerrprint("read or write is required");
- return tokv_error;
- }
+ if (needreadwrite > 0)
+ return parseerrprint("read or write is required");
havereadwrite= 0;
} else if (r == tokv_lwsp) {
- if (needreadwrite < 0) {
- parseerrprint("read or write not allowed"); return tokv_error;
- }
+ if (needreadwrite < 0)
+ return parseerrprint("read or write not allowed");
r= yylex(); if (r == tokv_error) return r;
if (!(r & tokt_readwrite))
return unexpected(r,-1,"read or write (or perhaps newline)");
ensurefdarray(fdmin);
if (fdmax == -1) {
if (!(dtoken == tokv_word_rejectfd || dtoken == tokv_word_ignorefd))
- parseerrprint("unspecified maximum only allowed with reject-fd and ignore-fd");
+ return parseerrprint("unspecified maximum only allowed"
+ " with reject-fd and ignore-fd");
fdmax= fdarrayused-1;
restfdwantstate= dtoken;
restfdwantrw= havereadwrite;
r= paa_1path(&cp); if (r) return r;
file= fopen(cp,"a");
- if (!file) {
- parseerrprint("unable to open error log file `%s': %s",cp,strerror(errno));
- return tokv_error;
- }
+ if (!file)
+ return parseerrprint("unable to open error log file `%s': %s",cp,strerror(errno));
if (setvbuf(file,0,_IOLBF,MAX_ERRMSG_LEN)) {
parseerrprint("unable to set line buffering on errors file: %s",strerror(errno));
fclose(file); return tokv_error;
r= paa_1path(&cp); if (r) return r;
r= parse_file(cp,&found); if (r) return r;
if (found || dtoken == tokv_word_includeifexist) return 0;
- parseerrprint(dtoken == tokv_word_includesysconfig ?
- "system configuration file `%s' does not exist" :
- "included file `%s' does not exist",
- cp);
- return tokv_error;
+ return parseerrprint(dtoken == tokv_word_includesysconfig ?
+ "system configuration file `%s' does not exist" :
+ "included file `%s' does not exist",
+ cp);
}
int df_includedirectory(int dtoken) {
int r, cpl, tel, c, found;
DIR *d;
struct dirent *de;
- const char *p, *cp;
+ const char *p, *cpget;
+ char *cp;
- r= paa_1path(&cp); if (r) return r;
- d= opendir(cp);
- if (!d) {
- parseerrprint("unable to open directory `%s': %s",cp,strerror(errno));
- return tokv_error;
- }
+ r= paa_1path(&cpget); if (r) return r;
+ d= opendir(cpget);
+ if (!d)
+ return parseerrprint("unable to open directory `%s': %s",cpget,strerror(errno));
+ cp= xstrsave(cpget);
cpl= strlen(cp);
while ((de= readdir(d))) {
tel= strlen(de->d_name);
if (!tel) continue;
p= de->d_name;
- if (!*p || !isalnum(*p)) continue;
- while ((c= *++p)) if (!(isalnum(c) || c=='-')) break;
+ if (!*p || !ISCHAR(isalnum,*p)) continue;
+ while ((c= *++p)) if (!(ISCHAR(isalnum,c) || c=='-')) break;
if (c) continue;
- if (makeroom(&buildbuf,&buildbuflen,cpl+1+tel+1))
- return stringoverflow("pathname in directory");
+ if (makeroom(&buildbuf,&buildbuflen,cpl+1+tel+1)) {
+ stringoverflow("pathname in directory");
+ r= tokv_error; goto x_err;
+ }
snyprintf(buildbuf,buildbuflen,"%s/%s",cp,de->d_name);
- r= parse_file(buildbuf,&found); if (r) { closedir(d); return r; }
+ r= parse_file(buildbuf,&found); if (r) goto x_err;
if (!found) {
- parseerrprint("unable to open file `%s' in included directory `%s': %s",
- de->d_name,cp,strerror(errno));
- closedir(d);
- return tokv_error;
+ r= parseerrprint("unable to open file `%s' in included directory `%s': %s",
+ de->d_name,cp,strerror(errno));
+ goto x_err;
}
}
if (closedir(d)) {
parseerrprint("error closing directory `%s': %s",cp,strerror(errno));
+ free(cp);
return tokv_error;
}
+ free(cp);
return 0;
+
+x_err:
+ closedir(d);
+ free(cp);
+ return r;
}
int df_includelookup(int dtoken) {
static char *buildbuf=0;
int buildbuflen=0;
- char **parmvalues, **pp, *p, *q;
- const char *cp;
+ char **parmvalues, **pp, *p, *q, *cp;
+ const char *cpget;
struct stat stab;
int r, done, thisdone, cpl, c;
r= pa_mwsp(); if (r) return r;
r= pa_parameter(&parmvalues,0); if (r) return r;
- r= paa_1path(&cp); if (r) { freecharparray(parmvalues); return r; }
- if (stat(cp,&stab)) {
- parseerrprint("unable to access directory `%s': %s",cp,strerror(errno));
+ r= paa_1path(&cpget); if (r) { freecharparray(parmvalues); return r; }
+ if (stat(cpget,&stab)) {
+ parseerrprint("unable to access directory `%s': %s",cpget,strerror(errno));
freecharparray(parmvalues); return tokv_error;
}
if (!S_ISDIR(stab.st_mode)) {
- parseerrprint("object `%s' is not a directory or link to one",cp);
+ parseerrprint("object `%s' is not a directory or link to one",cpget);
freecharparray(parmvalues); return tokv_error;
}
done= 0;
+ cp= xstrsave(cpget);
cpl= strlen(cp);
if (!parmvalues[0]) {
- if (makeroom(&buildbuf,&buildbuflen,cpl+1+sizeof(NONEINCLUDELOOKUP)))
- return stringoverflow("pathname in directory for lookup of undefined parameter");
+ if (makeroom(&buildbuf,&buildbuflen,cpl+1+sizeof(NONEINCLUDELOOKUP))) {
+ stringoverflow("pathname in directory for lookup of undefined parameter");
+ r= tokv_error; goto x_err;
+ }
snyprintf(buildbuf,buildbuflen,"%s/" NONEINCLUDELOOKUP,cp);
- r= parse_file(buildbuf,&thisdone);
- if (r) { freecharparray(parmvalues); return r; }
+ r= parse_file(buildbuf,&thisdone); if (r) goto x_err;
if (thisdone) done= 1;
} else {
for (pp=parmvalues;
*pp && (!done || dtoken == tokv_word_includelookupall);
pp++) {
if (makeroom(&buildbuf,&buildbuflen,
- cpl+1+strlen(*pp)*2+3+sizeof(EMPTYINCLUDELOOKUP)+1))
- return stringoverflow("pathname in directory for lookup");
+ cpl+1+strlen(*pp)*2+3+sizeof(EMPTYINCLUDELOOKUP)+1)) {
+ stringoverflow("pathname in directory for lookup");
+ r= tokv_error; goto x_err;
+ }
strcpy(buildbuf,cp);
p= *pp; q= buildbuf+cpl;
*q++= '/';
} else {
if (*p=='.') *q++= ':';
while ((c= *p++)) {
- if (c=='/') { *q++= ':'; c='-'; }
- else if (c==':') { *q++= ':'; }
+ if (c=='/') {
+ *q++= ':';
+ c= '-';
+ } else if (!((c >= '0' && c <= '9') ||
+ (c >= 'a' && c <= 'z') ||
+ c == '-' || c == '_')) {
+ *q++= ':';
+ }
*q++= c;
}
*q++= 0;
}
r= parse_file(buildbuf,&thisdone);
- if (r) { freecharparray(parmvalues); return r; }
+ if (r) goto x_err;
if (thisdone) done= 1;
}
}
- freecharparray(parmvalues);
if (!done) {
if (makeroom(&buildbuf,&buildbuflen,
- cpl+1+sizeof(DEFAULTINCLUDELOOKUP)))
- return stringoverflow("pathname in directory for lookup of default");
+ cpl+1+sizeof(DEFAULTINCLUDELOOKUP))) {
+ stringoverflow("pathname in directory for lookup of default");
+ r= tokv_error; goto x_err;
+ }
snyprintf(buildbuf,buildbuflen,"%s/" DEFAULTINCLUDELOOKUP,cp);
- r= parse_file(buildbuf,0); if (r) return r;
+ r= parse_file(buildbuf,0); if (r) goto x_err;
}
- return 0;
+ r= 0;
+
+x_err:
+ freecharparray(parmvalues);
+ free(cp);
+ return r;
}
/* Control constructs */
r= paa_1path(&cp); if (r) return r;
if (!chdir(cp)) return 0;
- parseerrprint("unable to change directory to `%s': %s",cp,strerror(errno));
- return tokv_error;
+ return parseerrprint("unable to change directory to `%s': %s",cp,strerror(errno));
}
int df_userrcfile(int dtoken) {
int r;
r= paa_message(&mp); if (r) return r;
- parseerrprint("`error' directive: %s",mp);
- return tokv_error;
+ return parseerrprint("`error' directive: %s",mp);
}
int df_eof(int dtoken) {
char *filename;
struct stat newstab;
- if (fileparselevel >= MAX_INCLUDE_NEST) {
- parseerrprint("too many nested levels of included files");
- return tokv_error;
- }
+ if (fileparselevel >= MAX_INCLUDE_NEST)
+ return parseerrprint("too many nested levels of included files");
file= fopen(string,"r");
if (!file) {
if (errno == ENOENT) {
if (didexist) *didexist= 0;
return 0;
}
- parseerrprint("unable to open config file `%s': %s",string,strerror(errno));
- return tokv_error;
+ return parseerrprint("unable to open config file `%s': %s",string,strerror(errno));
}
r= fstat(fileno(file),&newstab); if (r) syscallerror("unable to fstat new file");
for (checkrecurse= cstate; checkrecurse; checkrecurse= checkrecurse->upstate) {
if (!checkrecurse->filestab.st_mode) continue;
if (newstab.st_dev==checkrecurse->filestab.st_dev &&
newstab.st_ino==checkrecurse->filestab.st_ino) {
- parseerrprint("recursion detected - config file `%s' calls itself",string);
fclose(file);
- return tokv_error;
+ return parseerrprint("recursion detected - config file `%s' calls itself",string);
}
}
fileparselevel++;
r= parser(0);
- if (ferror(file)) {
- parseerrprint("error reading configuration file `%s'",string);
- r= tokv_error;
- }
+ if (ferror(file))
+ r= parseerrprint("error reading configuration file `%s'",string);
fileparselevel--;
parser_pop();