* Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-struct parser_state {
- int lineno, atnewline, notedreferer;
- const char *filename;
- YY_BUFFER_STATE ybuf;
- struct parser_state *upstate;
-};
-
-static const char *currentfile= 0;
-static struct parser_state *parser_topstate= 0;
-
-static directive_fnt *lr_dir=0;
-static parmcondition_fnt *lr_parmcond=0;
-static parameter_fnt *lr_parameter=0;
-static int lr_loglevel, lr_logfacility, lr_min, lr_max, *lr_flag;
-static int lr_flagval, lr_controlend;
-static int lr_fdwant_readwrite;
-
static void useless(void) { (void)yyunput; (void)useless; /* to shut up GCC ! */ }
static void closeerrorfile(void) {
- if (ehfile && !ehfilekeep) { fclose(ehfile); free(ehfilename); }
- ehfile= 0; ehfilename= 0; ehfilekeep= 0;
+ if (eh.file && !eh.filekeep) {
+ if (fclose(eh.file)) {
+ eh.handling= tokv_word_errorstostderr;
+ parseerrprint("error writing to error log file `%s': %s",
+ eh.filename,strerror(errno));
+ }
+ free(eh.filename);
+ }
+ eh.handling= 0;
+ eh.file= 0; eh.filename= 0; eh.filekeep= 0;
}
static void senderrmsg(const char *errmsg, int useehandling) {
senderrmsgstderr(errmsg);
break;
case tokv_word_errorstosyslog:
- ensurelogopen(ehlogfacility);
- syslog(ehloglevel,"%s",errmsg);
+ ensurelogopen(eh.logfacility);
+ syslog(eh.loglevel,"%s",errmsg);
break;
case tokv_word_errorstofile:
if (time(&now)==-1) syscallerror("get current time");
lt= localtime(&now); if (!lt) syscallerror("convert current time");
- if (fprintf(ehfile,"%d-%02d-%02d %02d:%02d:%02d: uservd: %s\n",
+ if (fprintf(eh.file,"%d-%02d-%02d %02d:%02d:%02d: uservd: %s\n",
lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
lt->tm_hour, lt->tm_min, lt->tm_sec,
errmsg) == EOF) {
e= errno;
- closeerrorfile(); ehandling= tokv_word_errorstofile;
+ closeerrorfile(); eh.handling= tokv_word_errorstofile;
snyprintf(suberrmsg,sizeof(suberrmsg),
"error writing to error log file `%.*s': %s;"
" reverting to errors-to-stderr",
- (int)(sizeof(suberrmsg)>>1),ehfilename,strerror(e));
- senderrmsg(suberrmsg,ehandling);
- senderrmsg(errmsg,ehandling);
+ (int)(sizeof(suberrmsg)>>1),eh.filename,strerror(e));
+ senderrmsg(suberrmsg,eh.handling);
+ senderrmsg(errmsg,eh.handling);
}
break;
default:
}
}
-static void errwhere(int iflineno, const char *filename, int *ifnotedreferer,
- struct parser_state *upstate, char *bufput, int bufputlen) {
+static void errwhere(struct parser_state *tstate, char *bufput, int bufputlen) {
static const char suffix[]= "references ...";
char errmsg[MAX_ERRMSG_LEN];
- if (!upstate) {
- filename= "<initialisation>";
- } else if (!*ifnotedreferer && upstate->upstate && upstate->upstate->upstate) {
- errwhere(upstate->lineno-upstate->atnewline,upstate->filename,
- &upstate->notedreferer,upstate->upstate,
- errmsg,sizeof(errmsg)-sizeof(suffix));
+ if (!tstate) {
+ strnycpy(bufput,"<initialisation>: ",bufputlen);
+ return;
+ }
+ if (!tstate->notedreferer && tstate->upstate && !tstate->upstate->isinternal) {
+ errwhere(tstate->upstate,errmsg,sizeof(errmsg)-sizeof(suffix));
strcat(errmsg,suffix);
- senderrmsg(errmsg,ehandling);
- *ifnotedreferer= 1;
+ senderrmsg(errmsg,eh.handling);
+ tstate->notedreferer= 1;
}
- snyprintf(bufput,bufputlen,"%.*s:%d: ",bufputlen-10,filename,iflineno);
+ snyprintf(bufput,bufputlen,"%.*s:%d: ",bufputlen-10,
+ tstate->filename,tstate->reportlineno);
}
void parseerrprint(const char *fmt, ...) {
char errmsg[MAX_ERRMSG_LEN];
va_start(al,fmt);
- errwhere(lineno-atnewline,currentfile,¬edreferer,parser_topstate,
- errmsg,sizeof(errmsg)>>1);
+ errwhere(cstate,errmsg,sizeof(errmsg)>>1);
vsnytprintfcat(errmsg,sizeof(errmsg),fmt,al);
- senderrmsg(errmsg,ehandling);
+ senderrmsg(errmsg,eh.handling);
va_end(al);
}
static char *p=0;
static int pl=0;
- int l;
-
- if (strncmp(in,USERDIRPREFIX,sizeof(USERDIRPREFIX)-1)) return in;
- l= strlen(serviceuser_dir)+strlen(in)+1-(sizeof(USERDIRPREFIX)-1)+
- sizeof(DIRSEP)-1;
- if (l>pl) { p= realloc(p,l); pl=l; }
- strcpy(p,serviceuser_dir); strcat(p,DIRSEP);
- strcat(p,in+(sizeof(USERDIRPREFIX)-1));
+ if (strncmp(in,"~/",2)) return in;
+ makeroom(&p,&pl,strlen(serviceuser_dir)+1+strlen(in+2)+1);
+ snyprintf(p,pl,"%s/%s",serviceuser_dir,in+2);
return p;
}
-static void parser_push(struct parser_state *saveinto,
- const char *newfile) {
- saveinto->lineno= lineno;
- saveinto->atnewline= atnewline;
- saveinto->filename= currentfile;
- saveinto->notedreferer= notedreferer;
- saveinto->ybuf= YY_CURRENT_BUFFER;
- saveinto->upstate= parser_topstate;
-
- lineno= 1;
- notedreferer= 0;
- currentfile= newfile;
- parser_topstate= saveinto;
+static void parser_push(struct parser_state *usestate,
+ const char *newfile,
+ YY_BUFFER_STATE ybuf,
+ int isinternal) {
+ usestate->lineno= 1;
+ usestate->reportlineno= 1;
+ usestate->filename= newfile;
+ usestate->notedreferer= 0;
+ usestate->isinternal= isinternal;
+ usestate->ybuf= ybuf;
+ usestate->upstate= cstate;
+
+ cstate= usestate;
+ yy_switch_to_buffer(ybuf);
}
static void parser_pop(void) {
- YY_BUFFER_STATE ybuf;
- ybuf= YY_CURRENT_BUFFER;
-
- lineno= parser_topstate->lineno;
- atnewline= parser_topstate->atnewline;
- currentfile= parser_topstate->filename;
- notedreferer= parser_topstate->notedreferer;
- if (parser_topstate->ybuf) yy_switch_to_buffer(parser_topstate->ybuf);
- parser_topstate= parser_topstate->upstate;
-
- yy_delete_buffer(ybuf);
+ struct parser_state *oldstate;
+
+ oldstate= cstate;
+ cstate= cstate->upstate;
+ if (cstate) yy_switch_to_buffer(cstate->ybuf);
+ yy_delete_buffer(oldstate->ybuf);
}
/* parser component functions pa_ return tokv_error or 0,
static void parm_1string(char ***rvalues, const char *tocopy) {
char **a;
a= xmalloc(sizeof(char*)*2);
- a[0]= xstrdup(tocopy);
+ a[0]= xstrsave(tocopy);
a[1]= 0;
*rvalues= a;
}
*rv= string2path(cp); return 0;
}
-static int pa_parameter(char ***rvalues) {
+static int pa_parameter(char ***rvalues, char **rname) {
/* Scans a single parameter token and calls the appropriate parameter
* function, returning tokv_error or 0 just like the parameter function.
+ * If rname is non-null then the name of the parameter (malloc'd) will
+ * be stored in it.
*/
int token, r, i;
+ char *name;
token= yylex(); if (token == tokv_error) return token;
+ name= xstrsave(yytext);
if ((token & tokm_repres) != tokr_nonstring &&
!memcmp(yytext,"u-",2) && strlen(yytext)>=3) {
for (i=0;
- i<request_mbuf.nvars && strcmp(yytext+2,defvararray[i][0]);
+ i<request_mbuf.nvars && strcmp(yytext+2,defvararray[i].key);
i++);
if (i>=request_mbuf.nvars) {
*rvalues= xmalloc(sizeof(char*));
**rvalues= 0;
} else {
- parm_1string(rvalues,defvararray[i][1]);
+ parm_1string(rvalues,defvararray[i].value);
}
} else {
- if (!(token & tokt_parameter)) return unexpected(token,-1,"parameter name");
+ if (!(token & tokt_parameter)) {
+ free(name);
+ return unexpected(token,-1,"parameter name");
+ }
r= (lr_parameter)(token,rvalues);
- if (r) return r;
+ if (r) { free(name); return r; }
}
- debug_dumpparameter(yytext,*rvalues);
+ debug_dumpparameter(name,*rvalues);
+ if (rname) *rname= name;
+ else free(name);
return 0;
}
} else if (token == tokv_openparen) {
andor= 0; actrue= -1;
for (;;) {
+ cstate->reportlineno= cstate->lineno;
r= pa_condition(&ctrue); if (r) return r;
switch (andor) {
case 0: assert(actrue==-1); actrue= ctrue; break;
*rtrue= actrue; return 0;
} else if (token & tokt_parmcondition) {
r= pa_mwsp(); if (r) return r;
- r= pa_parameter(&parmvalues); if (r) return r;
+ r= pa_parameter(&parmvalues,0); if (r) return r;
r= (lr_parmcond)(token,parmvalues,rtrue); freecharparray(parmvalues);
return r;
}
int token, r;
for (;;) { /* loop over lines */
+ cstate->reportlineno= cstate->lineno;
do { token= yylex(); } while (token == tokv_lwsp);
if (token & tokt_exception) {
return token;
r= token;
while (r & tokt_controlstart) {
r= skiptoeol(); if (r) return r;
+ cstate->reportlineno= cstate->lineno;
r= skip(token); if (r & tokt_exception) return r;
}
} else if (!(token & tokt_directive) && !(token & tokt_condop)) {
int token, r;
for (;;) { /* loop over lines */
+ cstate->reportlineno= cstate->lineno;
do { token= yylex(); } while (token == tokv_lwsp);
if (token & tokt_exception) {
return token;
}
}
-int parse_string(const char *string, const char *descrip) {
+int parse_string(const char *string, const char *descrip, int isinternal) {
/* Returns the same things as parser, except that tokv_eof
* is turned into 0. */
- struct parser_state save;
+ struct parser_state usestate;
YY_BUFFER_STATE ybuf;
int r;
-
- parser_push(&save,descrip);
+
ybuf= yy_scan_string(string);
if (!ybuf) syscallerror("unable to create flex buffer for internal string");
- yy_switch_to_buffer(ybuf);
+ parser_push(&usestate,descrip,ybuf,isinternal);
r= parser(0);
* is turned into 0. */
static int fileparselevel= 0;
- struct parser_state save;
+ struct parser_state usestate;
YY_BUFFER_STATE ybuf;
int r;
FILE *file;
}
if (didexist) *didexist= 1;
- parser_push(&save,string);
ybuf= yy_create_buffer(file,YY_BUF_SIZE);
if (!ybuf) syscallerror("unable to create flex buffer for file");
- yy_switch_to_buffer(ybuf);
+ parser_push(&usestate,string,ybuf,0);
fileparselevel++;
r= parser(0);
static int parm_usernameuid(char ***rvalues, const char *name, uid_t id) {
char **a;
a= xmalloc(sizeof(char*)*3);
- a[0]= xstrdup(name);
+ a[0]= xstrsave(name);
a[1]= parm_ulong(id);
a[2]= 0;
*rvalues= a; return 0;
sprintf(ebuf,"look up group with id %lu",(unsigned long)id);
syscallerror(ebuf);
}
- return xstrdup(ge->gr_name);
+ return xstrsave(ge->gr_name);
}
static int parm_gids(char ***rvalues, int size, gid_t *list) {
}
int pf_callinggroup(int ptoken, char ***rvalues) {
- return parm_gids(rvalues,request_mbuf.ngids,gidarray);
+ return parm_gids(rvalues,request_mbuf.ngids,calling_gids);
}
int pf_servicegroup(int ptoken, char ***rvalues) {
- static int size=-1;
- static gid_t *list;
-
- if (size == -1) {
- size= getgroups(0,0); if (size == -1) syscallerror("getgroups(0,0)");
- list= xmalloc(sizeof(gid_t)*(size+1));
- if (getgroups(size,list+1) != size) syscallerror("getgroups(size,list)");
- list[0]= serviceuser_gid;
- }
- return parm_gids(rvalues,size,list);
+ return parm_gids(rvalues,service_ngids,service_gids);
}
int pf_callingusershell(int ptoken, char ***rvalues) {
- struct passwd *pw;
-
- pw= getpwnam(logname); if (!pw) syscallerror("looking up calling user");
- parm_1string(rvalues,pw->pw_shell); return 0;
+ parm_1string(rvalues,callinguser_shell); return 0;
}
int pf_serviceusershell(int ptoken, char ***rvalues) {
/* Directive functions and associated `common code' functions */
-int df_reject(int dtoken) {
- int r;
-
- r= pa_mnl(); if (r) return r;
- execute= tokv_word_reject;
- free(execpath); execpath= 0;
- freecharparray(execargs); execargs= 0;
- return 0;
-}
-
-int df_executefrompath(int dtoken) {
- int r;
-
- r= pa_mnl(); if (r) return r;
- execute= tokv_word_executefrompath;
- free(execpath); execpath= 0;
- freecharparray(execargs); execargs= 0;
- return 0;
-}
-
static int paa_pathargs(const char **rv, char ***newargs_r) {
/* Repeated calls do _not_ overwrite newargs_r; caller must free.
* Repeated calls _do_ overwrite string returned in rv.
size= (used+5)<<2;
newargs= xrealloc(newargs,sizeof(char*)*(size+1));
}
- newargs[used++]= xmstrsave(yytext);
+ newargs[used++]= xstrsave(yytext);
}
newargs[used]= 0;
*newargs_r= newargs;
return r;
}
+static void execreset(void) {
+ execute= 0;
+ execbuiltin= 0;
+ free(execpath); execpath= 0;
+ freecharparray(execargs); execargs= 0;
+}
+
+int df_reject(int dtoken) {
+ int r;
+
+ r= pa_mnl(); if (r) return r;
+ execreset();
+ execute= tokv_word_reject;
+ return 0;
+}
+
+int df_executefrompath(int dtoken) {
+ int r;
+
+ r= pa_mnl(); if (r) return r;
+ execreset();
+ execute= tokv_word_executefrompath;
+ return 0;
+}
+
int df_execute(int dtoken) {
const char *rv;
char **newargs;
int r;
r= paa_pathargs(&rv,&newargs); if (r) return r;
+ execreset();
execute= tokv_word_execute;
- freecharparray(execargs); execargs= newargs;
- free(execpath); execpath= xmstrsave(rv);
+ execargs= newargs;
+ execpath= xstrsave(rv);
return 0;
}
return tokv_error;
}
}
- l= strlen(rv)+sizeof(DIRSEP)+strlen(p);
- fn= xmalloc(l); strcpy(fn,rv); strcat(fn,DIRSEP); strcat(fn,p);
+ l= strlen(rv)+1+strlen(p)+1;
+ fn= xmalloc(l);
+ snyprintf(fn,l,"%s/%s",rv,p);
if (stat(fn,&stab)) {
if (errno == ENOENT) { free(fn); freecharparray(newargs); return 0; }
parseerrprint("failed to stat `%s' for execute-from-directory: %s",
" or link to one (mode=0%o)",fn,stab.st_mode);
free(fn); freecharparray(newargs); return tokv_error;
}
+ execreset();
execute= tokv_word_executefromdirectory;
- freecharparray(execargs); execargs= newargs;
- free(execpath); execpath= fn;
+ execargs= newargs;
+ execpath= fn;
+ return 0;
+}
+
+static int bispa_none(char ***rnewargs) {
+ return pa_mnl();
+}
+
+static int bispa_parameter(char ***rnewargs) {
+ int r, i;
+ char **parmvalues, *name, **newargs;
+
+ r= pa_mwsp(); if (r) return r;
+ r= pa_parameter(&parmvalues,&name); if (r) return r;
+ for (i=0; parmvalues[i]; i++);
+ newargs= xmalloc(sizeof(char*)*(i+2));
+ newargs[0]= name;
+ memcpy(newargs+1,parmvalues,sizeof(char*)*(i+1));
+ free(parmvalues);
+ r= pa_mnl(); if (r) { free(newargs); return r; }
+ *rnewargs= newargs;
+ return 0;
+}
+
+int df_executebuiltin(int dtoken) {
+ int r;
+ builtinserviceexec_fnt *bisexec;
+ char *newpath, **newargs;
+
+ r= pa_mwsp(); if (r) return r;
+ r= yylex(); if (r == tokv_error) return r;
+ if (!(r & tokt_builtinservice)) return unexpected(r,-1,"builtin service name");
+ bisexec= lr_bisexec;
+ newpath= xstrsave(yytext);
+ newargs= 0;
+ r= lr_bispa(&newargs); if (r) { free(newpath); return r; }
+
+ execreset();
+ execute= tokv_word_executebuiltin;
+ execbuiltin= bisexec;
+ execpath= newpath;
+ execargs= newargs;
return 0;
}
int r;
r= pa_mnl(); if (r) return r;
- closeerrorfile(); ehandling= dtoken; return 0;
+ closeerrorfile(); eh.handling= dtoken; return 0;
}
int df_errorstosyslog(int dtoken) {
}
if (unexpected(token,tokv_newline,"end of line somewhere after errors-to-syslog"))
return tokv_error;
- closeerrorfile(); ehandling= tokv_word_errorstosyslog;
- ehlogfacility= facility; ehloglevel= level; return 0;
+ closeerrorfile(); eh.handling= tokv_word_errorstosyslog;
+ eh.logfacility= facility; eh.loglevel= level; return 0;
}
int df_errorstofile(int dtoken) {
parseerrprint("unable to set line buffering on errors file: %s",strerror(errno));
fclose(file); return tokv_error;
}
- closeerrorfile(); ehandling= tokv_word_errorstofile;
- ehfile= file; ehfilename= xmstrsave(cp); ehfilekeep= 0; return 0;
+ closeerrorfile(); eh.handling= tokv_word_errorstofile;
+ eh.file= file; eh.filename= xstrsave(cp); return 0;
}
int dfg_setflag(int dtoken) {
int r;
r= pa_mnl(); if (r) return r;
- r= parse_string(RESET_CONFIGURATION,"<builtin reset configuration>");
+ r= parse_string(RESET_CONFIGURATION,"<builtin reset configuration>",1);
assert(!r); return 0;
}
int r;
r= paa_1path(&cp); if (r) return r;
- free(userrcfile); userrcfile= xstrdup(cp);
+ free(userrcfile); userrcfile= xstrsave(cp);
return 0;
}
"found but configuration not overridden");
return tokv_error;
}
- return parse_string(overridedata,"<configuration override data>");
+ return parse_string(overridedata,"<configuration override data>",0);
}
int df_include(int dtoken) {
if (!isalnum(*p)) continue;
while ((c= *++p)) if (!(isalnum(c) || c=='-')) break;
if (c) continue;
- makeroom(&buildbuf,&buildbuflen,cpl+tel+sizeof(DIRSEP));
- strcpy(buildbuf,cp);
- strcat(buildbuf,DIRSEP);
- strcat(buildbuf,de->d_name);
+ makeroom(&buildbuf,&buildbuflen,cpl+1+tel+1);
+ snyprintf(buildbuf,buildbuflen,"%s/%s",cp,de->d_name);
r= parse_file(buildbuf,&found); if (r) { closedir(d); return r; }
if (!found) {
parseerrprint("unable to open file `%s' in included directory `%s': %s",
int r, done, thisdone, cpl, c;
r= pa_mwsp(); if (r) return r;
- r= pa_parameter(&parmvalues); 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));
done= 0;
cpl= strlen(cp);
if (!parmvalues[0]) {
- makeroom(&buildbuf,&buildbuflen,cpl+sizeof(DIRSEP NONEINCLUDELOOKUP));
- strcpy(buildbuf,cp);
- strcat(buildbuf,DIRSEP NONEINCLUDELOOKUP);
+ makeroom(&buildbuf,&buildbuflen,cpl+1+sizeof(NONEINCLUDELOOKUP));
+ snyprintf(buildbuf,buildbuflen,"%s/" NONEINCLUDELOOKUP,cp);
r= parse_file(buildbuf,&thisdone);
if (r) { freecharparray(parmvalues); return r; }
if (thisdone) done= 1;
*pp && (!done || dtoken == tokv_word_includelookupall);
pp++) {
makeroom(&buildbuf,&buildbuflen,
- cpl+sizeof(DIRSEP)+strlen(*pp)*2+3+sizeof(EMPTYINCLUDELOOKUP));
+ cpl+1+strlen(*pp)*2+3+sizeof(EMPTYINCLUDELOOKUP)+1);
strcpy(buildbuf,cp);
- strcat(buildbuf,DIRSEP);
- p= *pp; q= buildbuf+cpl+sizeof(DIRSEP)-1;
+ p= *pp; q= buildbuf+cpl;
+ *q++= '/';
if (*p=='.') *q++= ':';
while ((c= *p++)) {
if (c=='/') { *q++= ':'; c='-'; }
freecharparray(parmvalues);
if (!done) {
makeroom(&buildbuf,&buildbuflen,
- cpl+sizeof(DIRSEP)+sizeof(DEFAULTINCLUDELOOKUP));
- strcpy(buildbuf,cp);
- strcat(buildbuf,DIRSEP DEFAULTINCLUDELOOKUP);
+ cpl+1+sizeof(DEFAULTINCLUDELOOKUP));
+ snyprintf(buildbuf,buildbuflen,"%s/" DEFAULTINCLUDELOOKUP,cp);
r= parse_file(buildbuf,0); if (r) return r;
}
return 0;
} else if (r == tokv_quit || r == tokv_error) {
if (r == tokv_error) {
r= parse_string(RESET_CONFIGURATION,
- "<builtin reset configuration (caught error)>");
+ "<builtin reset configuration (caught error)>",1);
assert(!r);
- while (!atnewline) {
- r= yylex(); if (r == tokv_error) return r;
- }
}
r= skip(tokv_word_catchquit);
if (r & tokt_controlend) {
} while (r == tokv_word_elif);
if (r == tokv_word_else) {
r= pa_mnl(); if (r) return r;
+ cstate->reportlineno= cstate->lineno;
if (done) r= skip(tokv_word_if);
else r= parser(tokv_word_if);
if (!(r & tokv_word_if)) return r;
}
int df_errorspush(int dt) {
- int saveehandling, saveehlogfacility, saveehloglevel, saveehfilekeep;
- FILE *saveehfile;
- char *saveehfilename;
+ struct error_handling save;
int r;
r= pa_mnl(); if (r) return r;
- saveehandling= ehandling;
- saveehlogfacility= ehlogfacility;
- saveehloglevel= ehloglevel;
- saveehfile= ehfile;
- saveehfilekeep= ehfilekeep;
- saveehfilename= ehfilename;
- if (ehandling == tokv_word_errorstofile) ehfilekeep= 1;
+ save= eh;
+ eh.filekeep= 1;
r= parser(tokv_word_errorspush);
-
- ehandling= saveehandling;
- ehlogfacility= saveehlogfacility;
- ehloglevel= saveehloglevel;
- ehfile= saveehfile;
- ehfilekeep= saveehfilekeep;
- ehfilename= saveehfilename;
+
+ closeerrorfile();
+ eh= save;
if (r & tokt_controlend) {
assert(r == tokv_word_srorre);