chiark / gitweb /
Incorporate markups on all paper copies to date.
[userv.git] / parser.c
index 2395837..4b55743 100644 (file)
--- a/parser.c
+++ b/parser.c
  * 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) {
@@ -57,24 +48,24 @@ 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:
@@ -82,22 +73,22 @@ static void senderrmsg(const char *errmsg, int useehandling) {
   }
 }
 
-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, ...) {
@@ -105,10 +96,9 @@ void parseerrprint(const char *fmt, ...) {
   char errmsg[MAX_ERRMSG_LEN];
 
   va_start(al,fmt);
-  errwhere(lineno-atnewline,currentfile,&notedreferer,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);
 }
 
@@ -209,44 +199,35 @@ static const char *string2path(const char *in) {
   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,
@@ -276,7 +257,7 @@ static int pa_mwsp(void) {
 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;
 }
@@ -315,30 +296,39 @@ static int paa_1path(const char **rv) {
   *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;
 }
 
@@ -361,6 +351,7 @@ static int pa_condition(int *rtrue) {
   } 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;
@@ -383,7 +374,7 @@ static int pa_condition(int *rtrue) {
     *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;
   }
@@ -422,6 +413,7 @@ static int skip(int allowce) {
   int token, r;
 
   for (;;) { /* loop over lines */
+    cstate->reportlineno= cstate->lineno;
     do { token= yylex(); } while (token == tokv_lwsp);
     if (token & tokt_exception) {
       return token;
@@ -432,6 +424,7 @@ static int skip(int allowce) {
       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)) {
@@ -454,6 +447,7 @@ static int parser(int allowce) {
   int token, r;
 
   for (;;) { /* loop over lines */
+    cstate->reportlineno= cstate->lineno;
     do { token= yylex(); } while (token == tokv_lwsp);
     if (token & tokt_exception) {
       return token;
@@ -470,17 +464,16 @@ static int parser(int allowce) {
   }
 }
 
-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);
 
@@ -494,7 +487,7 @@ static int parse_file(const char *string, int *didexist) {
    * is turned into 0. */
   static int fileparselevel= 0;
   
-  struct parser_state save;
+  struct parser_state usestate;
   YY_BUFFER_STATE ybuf;
   int r;
   FILE *file;
@@ -513,10 +506,9 @@ static int parse_file(const char *string, int *didexist) {
   }
   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);
@@ -635,7 +627,7 @@ static char *parm_ulong(unsigned long ul) {
 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;
@@ -659,7 +651,7 @@ static char *parm_gidname(gid_t id) {
     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) {
@@ -677,20 +669,11 @@ 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) {
@@ -703,26 +686,6 @@ 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.
@@ -749,7 +712,7 @@ static int paa_pathargs(const char **rv, char ***newargs_r) {
       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;
@@ -761,15 +724,41 @@ error:
   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;
 }
 
@@ -797,8 +786,9 @@ int df_executefromdirectory(int dtoken) {
       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",
@@ -810,9 +800,51 @@ int df_executefromdirectory(int dtoken) {
                  " 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;
 }
 
@@ -820,7 +852,7 @@ int df_errorstostderr(int dtoken) {
   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) {
@@ -845,8 +877,8 @@ 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) {
@@ -864,8 +896,8 @@ 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) {
@@ -879,7 +911,7 @@ int df_reset(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;  
 }
 
@@ -898,7 +930,7 @@ int df_userrcfile(int dtoken) {
   int r;
 
   r= paa_1path(&cp); if (r) return r;
-  free(userrcfile); userrcfile= xstrdup(cp);
+  free(userrcfile); userrcfile= xstrsave(cp);
   return 0;
 }
 
@@ -920,7 +952,7 @@ int dfi_includeclientconfig(int dtoken) {
                  "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) {
@@ -1001,10 +1033,8 @@ int df_includedirectory(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",
@@ -1029,7 +1059,7 @@ int df_includelookup(int dtoken) {
   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));
@@ -1042,9 +1072,8 @@ int df_includelookup(int dtoken) {
   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;
@@ -1053,10 +1082,10 @@ int df_includelookup(int dtoken) {
         *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='-'; }
@@ -1072,9 +1101,8 @@ int df_includelookup(int dtoken) {
   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;
@@ -1091,11 +1119,8 @@ int df_catchquit(int dtoken) {
   } 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) {
@@ -1118,6 +1143,7 @@ int df_if(int dtoken) {
   } 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;
@@ -1182,29 +1208,18 @@ int df_eof(int dtoken) {
 }
 
 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);