fix possible crash on user deletion
[srvx.git] / src / recdb.c
index e873378d165b3845aa451550ec953f7d7eed777f..9b8ac1455e67c1df3e9bff0d6764aa4caef0c9f6 100644 (file)
@@ -1,11 +1,12 @@
 /* recdb.c - recursive/record database implementation
  * Copyright 2000-2004 srvx Development Team
  *
- * This program is free software; you can redistribute it and/or modify
+ * This file is part of srvx.
+ *
+ * srvx is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.  Important limitations are
- * listed in the COPYING file that accompanies this software.
+ * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -13,7 +14,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, email srvx-maintainers@srvx.net.
+ * along with srvx; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
  */
 
 #include "recdb.h"
@@ -91,7 +93,7 @@ typedef struct recdb_outfile {
 } RECDB_OUT;
 
 #ifdef HAVE_MMAP
-static int mmap_error=0;
+static int mmap_error;
 #endif
 
 #define EOL '\n'
@@ -107,6 +109,7 @@ ABORT(RECDB *recdb, int code, unsigned char ch) {
 
 enum fail_codes {
     UNTERMINATED_STRING,
+    UNTERMINATED_COMMENT,
     EXPECTED_OPEN_QUOTE,
     EXPECTED_OPEN_BRACE,
     EXPECTED_OPEN_PAREN,
@@ -343,8 +346,10 @@ parse_skip_ws(RECDB *recdb)
             do {
                 do {
                     c = dbgetc(recdb);
-                } while (c != '*' && c != EOF);
+                   if (c == EOF) ABORT(recdb, UNTERMINATED_COMMENT, c);
+                } while (c != '*');
                 if ((c = dbgetc(recdb)) == '/') in_comment = 0;
+               if (c == EOF) ABORT(recdb, UNTERMINATED_COMMENT, c);
             } while (in_comment);
         } else if (d == '/') {
             /* C++ style comment, with slash slash comment newline */
@@ -550,6 +555,7 @@ failure_reason(int code)
     const char *reason;
     switch (code >> 8) {
     case UNTERMINATED_STRING: reason = "Unterminated string"; break;
+    case UNTERMINATED_COMMENT: reason = "Unterminated comment"; break;
     case EXPECTED_OPEN_QUOTE: reason = "Expected '\"'"; break;
     case EXPECTED_OPEN_BRACE: reason = "Expected '{'"; break;
     case EXPECTED_OPEN_PAREN: reason = "Expected '('"; break;
@@ -566,9 +572,16 @@ failure_reason(int code)
 void
 explain_failure(RECDB *recdb, int code)
 {
-    log_module(MAIN_LOG, LOG_ERROR, "%s (got '%c') at %s line %d column %d.",
-               failure_reason(code), code & 255,
-               recdb->source, recdb->ctx.line, recdb->ctx.col);
+    static char msg[1024];
+    snprintf(msg, sizeof(msg), "%s (got '%c') at %s line %d column %d.",
+             failure_reason(code), code & 255,
+             recdb->source, recdb->ctx.line, recdb->ctx.col);
+    if (MAIN_LOG == NULL) {
+        fputs(msg, stderr);
+        fputc('\n', stderr);
+        fflush(stderr);
+    } else
+        log_module(MAIN_LOG, LOG_ERROR, "%s", msg);
 }
 
 const char *
@@ -611,14 +624,20 @@ parse_database(const char *filename)
 
     if (fstat(fileno(recdb.f), &statinfo)) {
         log_module(MAIN_LOG, LOG_ERROR, "Unable to fstat database file '%s': %s", filename, strerror(errno));
+        fclose(recdb.f);
         return NULL;
     }
     recdb.length = (size_t)statinfo.st_size;
+    if (recdb.length == 0) {
+        fclose(recdb.f);
+        return alloc_database();
+    }
 
 #ifdef HAVE_MMAP
     /* Try mmap */
     if (!mmap_error && (recdb.s = mmap(NULL, recdb.length, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(recdb.f), 0)) != MAP_FAILED) {
         recdb.type = RECDB_MMAP;
+        madvise(recdb.s, recdb.length, MADV_SEQUENTIAL);
     } else {
         /* Fall back to stdio */
         if (!mmap_error) {