]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/dird/run_conf.c
correct date
[bacula/bacula] / bacula / src / dird / run_conf.c
index 3fe299354a5768e0f23c0b1f36b6d132142cdc5c..66fafec301403240ae131b9a79fc454203cf3395 100644 (file)
@@ -4,6 +4,8 @@
  *   directives, which are part of the Schedule Resource
  *
  *     Kern Sibbald, May MM
+ *
+ *     Version $Id$
  */
 /*
    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
@@ -45,6 +47,8 @@ enum e_state {
    s_weekly,
    s_monthly,
    s_hourly,
+   s_wom,                          /* 1st, 2nd, ...*/
+   s_woy,                          /* week of year w00 - w53 */
 };  
 
 struct s_keyw {
@@ -101,53 +105,65 @@ static struct s_keyw keyw[] = {
   {N_("weekly"),     s_weekly,  0},
   {N_("monthly"),    s_monthly, 0},
   {N_("hourly"),     s_hourly,  0},
+
+  {N_("1st"),        s_wom,     0},
+  {N_("2nd"),        s_wom,     1},
+  {N_("3rd"),        s_wom,     2},
+  {N_("4th"),        s_wom,     3},
+  {N_("5th"),        s_wom,     4},
+
+  {N_("first"),      s_wom,     0},
+  {N_("second"),     s_wom,     1},
+  {N_("third"),      s_wom,     2},
+  {N_("fourth"),     s_wom,     3},
+  {N_("fifth"),      s_wom,     4},
   {NULL,        s_none,    0}
 };
 
-static int have_hour, have_mday, have_wday, have_month;
-static int have_at;
+static bool have_hour, have_mday, have_wday, have_month, have_wom;
+static bool have_at, have_woy;
 static RUN lrun;
 
 static void clear_defaults()
 {
-   have_hour = have_mday = have_wday = have_month = TRUE;
+   have_hour = have_mday = have_wday = have_month = have_wom = have_woy = true;
    clear_bit(0,lrun.hour);
    clear_bits(0, 30, lrun.mday);
    clear_bits(0, 6, lrun.wday);
    clear_bits(0, 11, lrun.month);
+   clear_bits(0, 4, lrun.wom);
+   clear_bits(0, 53, lrun.woy);
 }
 
 static void set_defaults()
 {
-   have_hour = have_mday = have_wday = have_month = FALSE;
-   have_at = FALSE;
+   have_hour = have_mday = have_wday = have_month = have_wom = have_woy = false;
+   have_at = false;
    set_bit(0,lrun.hour);
    set_bits(0, 30, lrun.mday);
    set_bits(0, 6, lrun.wday);
    set_bits(0, 11, lrun.month);
+   set_bits(0, 4, lrun.wom);
+   set_bits(0, 53, lrun.woy);
 }
 
 
-/* Check if string is a number */
-static int is_num(char *num)
-{
-   char *p = num;
-   int ch;
-   while ((ch = *p++)) {
-      if (ch < '0' || ch > '9') {
-        return FALSE;
-      }
-   }
-   return TRUE;
-}
-
+/* Keywords (RHS) permitted in Run records */
+static struct s_kw RunFields[] = {
+   {"pool",     'P'},
+   {"level",    'L'},
+   {"storage",  'S'},
+   {"messages", 'M'},
+   {"priority", 'p'},
+   {NULL,       0}
+};
 
 /* 
  * Store Schedule Run information   
  * 
  * Parse Run statement:
  *
- *  Run <full|incremental|...> [on] 2 january at 23:45
+ *  Run <keyword=value ...> [on] 2 january at 23:45
  *
  *   Default Run time is daily at 0:0
  *  
@@ -157,11 +173,14 @@ static int is_num(char *num)
  */
 void store_run(LEX *lc, struct res_items *item, int index, int pass)
 {
-   int token, state, state2, i, code, code2;
+   int i, j;
+   bool found;
+   int token, state, state2 = 0, code = 0, code2 = 0;
    int options = lc->options;
    RUN **run = (RUN **)(item->value);  
    RUN *trun;
    char *p;
+   RES *res;
 
 
    lc->options |= LOPT_NO_IDENT;      /* want only "strings" */
@@ -170,28 +189,95 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass)
    memset(&lrun, 0, sizeof(RUN));
 
    /* scan for Job level "full", "incremental", ... */
-   token = lex_get_token(lc);
-   if (token != T_STRING) {
-      scan_err1(lc, _("Expected a Job level identifier, got: %s"), lc->str);
-   } else {
-      if (strcasecmp(lc->str, "level")) {
-        if (lex_get_token(lc) != T_EQUALS) {
-            scan_err1(lc, "Expected an equals, got: %s", lc->str);
-        }
-        token = lex_get_token(lc);
-      }
-      for (i=0; joblevels[i].level_name; i++) {
-        if (strcasecmp(lc->str, joblevels[i].level_name) == 0) {
-           lrun.level = joblevels[i].level;
-           lrun.job_type = joblevels[i].job_type;
-           i = 0;
+   for (found=true; found; ) {
+      found = false;
+      token = lex_get_token(lc, T_NAME);
+      for (i=0; RunFields[i].name; i++) {
+        if (strcasecmp(lc->str, RunFields[i].name) == 0) {
+           found = true;
+           if (lex_get_token(lc, T_ALL) != T_EQUALS) {
+               scan_err1(lc, "Expected an equals, got: %s", lc->str);
+              /* NOT REACHED */ 
+           }
+           switch (RunFields[i].token) {
+            case 'L':                 /* level */
+              token = lex_get_token(lc, T_NAME);
+              for (j=0; joblevels[j].level_name; j++) {
+                 if (strcasecmp(lc->str, joblevels[j].level_name) == 0) {
+                    lrun.level = joblevels[j].level;
+                    lrun.job_type = joblevels[j].job_type;
+                    j = 0;
+                    break;
+                 }
+              }
+              if (j != 0) {
+                  scan_err1(lc, _("Job level field: %s not found in run record"), lc->str);
+                 /* NOT REACHED */
+              }
+              break;
+            case 'p':                 /* Priority */
+              token = lex_get_token(lc, T_PINT32);
+              if (pass == 2) {
+                 lrun.Priority = lc->pint32_val;
+              }
+              break;
+            case 'P':                 /* Pool */
+              token = lex_get_token(lc, T_NAME);
+              if (pass == 2) {
+                 res = GetResWithName(R_POOL, lc->str);
+                 if (res == NULL) {
+                     scan_err1(lc, "Could not find specified Pool Resource: %s",
+                               lc->str);
+                    /* NOT REACHED */
+                 }
+                 lrun.pool = (POOL *)res;
+              }
+              break;
+            case 'S':                 /* storage */
+              token = lex_get_token(lc, T_NAME);
+              if (pass == 2) {
+                 res = GetResWithName(R_STORAGE, lc->str);
+                 if (res == NULL) {
+                     scan_err1(lc, "Could not find specified Storage Resource: %s",
+                               lc->str);
+                    /* NOT REACHED */
+                 }
+                 lrun.storage = (STORE *)res;
+              }
+              break;
+            case 'M':                 /* messages */
+              token = lex_get_token(lc, T_NAME);
+              if (pass == 2) {
+                 res = GetResWithName(R_MSGS, lc->str);
+                 if (res == NULL) {
+                     scan_err1(lc, "Could not find specified Messages Resource: %s",
+                               lc->str);
+                    /* NOT REACHED */
+                 }
+                 lrun.msgs = (MSGS *)res;
+              }
+              break;
+           default:
+               scan_err1(lc, "Expected a keyword name, got: %s", lc->str);
+              /* NOT REACHED */
+              break;
+           } /* end switch */     
+        } /* end if strcasecmp */
+      } /* end for RunFields */
+
+      /* At this point, it is not a keyword. Check for old syle
+       * Job Levels without keyword. This form is depreciated!!!
+       */
+      for (j=0; joblevels[j].level_name; j++) {
+        if (strcasecmp(lc->str, joblevels[j].level_name) == 0) {
+           lrun.level = joblevels[j].level;
+           lrun.job_type = joblevels[j].job_type;
+           found = true;
            break;
         }
       }
-      if (i != 0) {
-         scan_err1(lc, _("Job level field: %s not found in run record"), lc->str);
-      }
-   }
+   } /* end for found */
+
 
    /*
     * Scan schedule times.
@@ -200,217 +286,287 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass)
    state = s_none;
    set_defaults();
 
-   while ((token = lex_get_token(lc)) != T_EOL) {
-      int len, pm;
+   for ( ; token != T_EOL; (token = lex_get_token(lc, T_ALL))) {
+      int len, pm = 0;
       switch (token) {
-        case T_NUMBER:
-           state = s_mday;
-           code = atoi(lc->str) - 1;
-           if (code < 0 || code > 30) {
-               scan_err0(lc, _("Day number out of range (1-31)"));
-           }
+      case T_NUMBER:
+        state = s_mday;
+        code = atoi(lc->str) - 1;
+        if (code < 0 || code > 30) {
+            scan_err0(lc, _("Day number out of range (1-31)"));
+        }
+        break;
+      case T_NAME:                /* this handles drop through from keyword */
+      case T_UNQUOTED_STRING:
+         if (strchr(lc->str, (int)'-')) {
+           state = s_range;
            break;
-        case T_STRING:
-            if (strchr(lc->str, (int)'-')) {
-              state = s_range;
-              break;
+        }
+         if (strchr(lc->str, (int)':')) {
+           state = s_time;
+           break;
+        }
+         if (lc->str_len == 3 && (lc->str[0] == 'w' || lc->str[0] == 'W') &&
+            is_an_integer(lc->str+1)) {
+           code = atoi(lc->str+1);
+           if (code < 0 || code > 53) {
+               scan_err0(lc, _("Week number out of range (0-53)"));
            }
-            if (strchr(lc->str, (int)':')) {
-              state = s_time;
+           state = s_woy;            /* week of year */
+           break;
+        }
+        /* everything else must be a keyword */
+        for (i=0; keyw[i].name; i++) {
+           if (strcasecmp(lc->str, keyw[i].name) == 0) {
+              state = keyw[i].state;
+              code   = keyw[i].code;
+              i = 0;
               break;
            }
-           /* everything else must be a keyword */
-           lcase(lc->str);
-           for (i=0; keyw[i].name; i++) {
-              if (strcmp(lc->str, keyw[i].name) == 0) {
-                 state = keyw[i].state;
-                 code   = keyw[i].code;
-                 i = 0;
-                 break;
-              }
-           }
-           if (i != 0) {
-               scan_err1(lc, _("Job type field: %s in run record not found"), lc->str);
-           }
-           break;
-        case T_COMMA:
-           continue;
-        default:
-            scan_err1(lc, _("Unexpected token: %s"), lc->str);
-           break;
+        }
+        if (i != 0) {
+            scan_err1(lc, _("Job type field: %s in run record not found"), lc->str);
+           /* NOT REACHED */
+        }
+        break;
+      case T_COMMA:
+        continue;
+      default:
+         scan_err2(lc, _("Unexpected token: %d:%s"), token, lc->str);
+        /* NOT REACHED */
+        break;
       }
       switch (state) {
-        case s_none:
-           continue;
-        case s_mday:                 /* day of month */
+      case s_none:
+        continue;
+      case s_mday:                /* day of month */
+        if (!have_mday) {
+           clear_bits(0, 30, lrun.mday);
+           clear_bits(0, 6, lrun.wday);
+           have_mday = true;
+        }
+        set_bit(code, lrun.mday);
+        break;
+      case s_month:               /* month of year */
+        if (!have_month) {
+           clear_bits(0, 11, lrun.month);
+           have_month = true;
+        }
+        set_bit(code, lrun.month);
+        break;
+      case s_wday:                /* week day */
+        if (!have_wday) {
+           clear_bits(0, 6, lrun.wday);
+           clear_bits(0, 30, lrun.mday);
+           have_wday = true;
+        }
+        set_bit(code, lrun.wday);
+        break;
+      case s_wom:                 /* Week of month 1st, ... */
+        if (!have_wom) {
+           clear_bits(0, 4, lrun.wom);
+           have_wom = true;
+        }
+        set_bit(code, lrun.wom);
+        break;
+      case s_woy:
+        if (!have_woy) {
+           clear_bits(0, 53, lrun.woy);
+           have_woy = true;
+        }
+        set_bit(code, lrun.woy);
+        break;
+      case s_time:                /* time */
+        if (!have_at) {
+            scan_err0(lc, _("Time must be preceded by keyword AT."));
+           /* NOT REACHED */
+        }
+        if (!have_hour) {
+           clear_bit(0, lrun.hour);
+        }
+         p = strchr(lc->str, ':');
+        if (!p)  {
+            scan_err0(lc, _("Time logic error.\n"));
+           /* NOT REACHED */
+        }
+        *p++ = 0;                 /* separate two halves */
+        code = atoi(lc->str);
+        len = strlen(p);
+         if (len > 2 && p[len-1] == 'm') {
+            if (p[len-2] == 'a') {
+              pm = 0;
+            } else if (p[len-2] == 'p') {
+              pm = 1;
+           } else {
+               scan_err0(lc, _("Bad time specification."));
+              /* NOT REACHED */
+           }
+        } else {
+           pm = 0;
+        }
+        code2 = atoi(p);
+        if (pm) {
+           code += 12;
+        }
+        if (code < 0 || code > 23 || code2 < 0 || code2 > 59) {
+            scan_err0(lc, _("Bad time specification."));
+           /* NOT REACHED */
+        }
+        set_bit(code, lrun.hour);
+        lrun.minute = code2;
+        have_hour = true;
+        break;
+      case s_at:
+        have_at = true;
+        break;
+      case s_range:
+         p = strchr(lc->str, '-');
+        if (!p) {
+            scan_err0(lc, _("Range logic error.\n"));
+        }
+        *p++ = 0;                 /* separate two halves */
+
+        /* Check for day range */
+        if (is_an_integer(lc->str) && is_an_integer(p)) {
+           code = atoi(lc->str) - 1;
+           code2 = atoi(p) - 1;
+           if (code < 0 || code > 30 || code2 < 0 || code2 > 30) {
+               scan_err0(lc, _("Bad day range specification."));
+           }
            if (!have_mday) {
               clear_bits(0, 30, lrun.mday);
               clear_bits(0, 6, lrun.wday);
-              have_mday = TRUE;
-           }
-           set_bit(code, lrun.mday);
-           break;
-        case s_month:                /* month of year */
-           if (!have_month) {
-              clear_bits(0, 11, lrun.month);
-              have_month = TRUE;
+              have_mday = true;
            }
-           set_bit(code, lrun.month);
-           break;
-        case s_wday:                 /* week day */
-           if (!have_wday) {
-              clear_bits(0, 6, lrun.wday);
-              clear_bits(0, 30, lrun.mday);
-              have_wday = TRUE;
+           if (code < code2) {
+              set_bits(code, code2, lrun.mday);
+           } else {
+              set_bits(code, 30, lrun.mday);
+              set_bits(0, code2, lrun.mday);
            }
-           set_bit(code, lrun.wday);
            break;
-        case s_time:                 /* time */
-           if (!have_at) {
-               scan_err0(lc, _("Time must be preceded by keyword AT."));
-           }
-           if (!have_hour) {
-              clear_bit(0, lrun.hour);
-              have_hour = TRUE;
+        }
+        /* Check for week of year range */
+        if (strlen(lc->str) == 3 && strlen(p) == 3 &&
+             (lc->str[0] == 'w' || lc->str[0] == 'W') &&
+             (p[0] == 'w' || p[0] == 'W') &&
+            is_an_integer(lc->str+1) && is_an_integer(p+1)) {
+           code = atoi(lc->str+1);
+           code2 = atoi(p+1);
+           if (code < 0 || code > 53 || code2 < 0 || code2 > 53) {
+               scan_err0(lc, _("Week number out of range (0-53)"));
            }
-            p = strchr(lc->str, ':');
-           if (!p)  {
-               scan_err0(lc, _("Time logic error.\n"));
+           if (!have_woy) {
+              clear_bits(0, 53, lrun.woy);
+              have_woy = true;
            }
-           *p++ = 0;                 /* separate two halves */
-           code = atoi(lc->str);
-           len = strlen(p);
-            if (len > 2 && p[len-1] == 'm') {
-               if (p[len-2] == 'a') {
-                 pm = 0;
-               } else if (p[len-2] == 'p') {
-                 pm = 1;
-              } else {
-                  scan_err0(lc, _("Bad time specification."));
-              }
+           if (code < code2) {
+              set_bits(code, code2, lrun.woy);
            } else {
-              pm = 0;
-           }
-           code2 = atoi(p);
-           if (pm) {
-              code += 12;
+              set_bits(code, 53, lrun.woy);
+              set_bits(0, code2, lrun.woy);
            }
-           if (code < 0 || code > 23 || code2 < 0 || code2 > 59) {
-               scan_err0(lc, _("Bad time specification."));
-           }
-           set_bit(code, lrun.hour);
-           lrun.minute = code2;
            break;
-        case s_at:
-           have_at = TRUE;
-           break;
-        case s_range:
-            p = strchr(lc->str, '-');
-           if (!p) {
-               scan_err0(lc, _("Range logic error.\n"));
-           }
-           *p++ = 0;                 /* separate two halves */
-
-           /* Check for day range */
-           if (is_num(lc->str) && is_num(p)) {
-              code = atoi(lc->str) - 1;
-              code2 = atoi(p) - 1;
-              if (code < 0 || code > 30 || code2 < 0 || code2 > 30) {
-                  scan_err0(lc, _("Bad day range specification."));
-              }
-              if (!have_mday) {
-                 clear_bits(0, 30, lrun.mday);
-                 clear_bits(0, 6, lrun.wday);
-                 have_mday = TRUE;
-              }
-              if (code < code2) {
-                 set_bits(code, code2, lrun.mday);
-              } else {
-                 set_bits(code, 30, lrun.mday);
-                 set_bits(0, code2, lrun.mday);
-              }
+        }
+        /* lookup first half of keyword range (week days or months) */
+        lcase(lc->str);
+        for (i=0; keyw[i].name; i++) {
+           if (strcmp(lc->str, keyw[i].name) == 0) {
+              state = keyw[i].state;
+              code   = keyw[i].code;
+              i = 0;
               break;
            }
+        }
+        if (i != 0 || (state != s_month && state != s_wday && state != s_wom)) {
+            scan_err0(lc, _("Invalid month, week or position day range"));
+           /* NOT REACHED */
+        }
 
-           /* lookup first half of keyword range (week days or months) */
-           lcase(lc->str);
-           for (i=0; keyw[i].name; i++) {
-              if (strcmp(lc->str, keyw[i].name) == 0) {
-                 state = keyw[i].state;
-                 code   = keyw[i].code;
-                 i = 0;
-                 break;
-              }
+        /* Lookup end of range */
+        lcase(p);
+        for (i=0; keyw[i].name; i++) {
+           if (strcmp(p, keyw[i].name) == 0) {
+              state2  = keyw[i].state;
+              code2   = keyw[i].code;
+              i = 0;
+              break;
            }
-           if (i != 0 || (state != s_month && state != s_wday)) {
-               scan_err0(lc, _("Invalid month or week day range"));
+        }
+        if (i != 0 || state != state2 || code == code2) {
+            scan_err0(lc, _("Invalid month, weekday or position range"));
+           /* NOT REACHED */
+        }
+        if (state == s_wday) {
+           if (!have_wday) {
+              clear_bits(0, 6, lrun.wday);
+              clear_bits(0, 30, lrun.mday);
+              have_wday = true;
            }
-
-           /* Lookup end of range */
-           lcase(p);
-           for (i=0; keyw[i].name; i++) {
-              if (strcmp(p, keyw[i].name) == 0) {
-                 state2  = keyw[i].state;
-                 code2   = keyw[i].code;
-                 i = 0;
-                 break;
-              }
+           if (code < code2) {
+              set_bits(code, code2, lrun.wday);
+           } else {
+              set_bits(code, 6, lrun.wday);
+              set_bits(0, code2, lrun.wday);
            }
-           if (i != 0 || state != state2 || 
-              (state2 != s_month && state2 != s_wday) || code == code2) {
-               scan_err0(lc, _("Invalid month or weekday range"));
+        } else if (state == s_month) {
+           if (!have_month) {
+              clear_bits(0, 30, lrun.month);
+              have_month = true;
            }
-           if (state == s_wday) {
-              if (!have_wday) {
-                 clear_bits(0, 6, lrun.wday);
-                 clear_bits(0, 30, lrun.mday);
-                 have_wday = TRUE;
-              }
-              if (code < code2) {
-                 set_bits(code, code2, lrun.wday);
-              } else {
-                 set_bits(code, 6, lrun.wday);
-                 set_bits(0, code2, lrun.wday);
-              }
+           if (code < code2) {
+              set_bits(code, code2, lrun.month);
            } else {
-              /* must be s_month */
-              if (!have_month) {
-                 clear_bits(0, 30, lrun.month);
-                 have_month = TRUE;
-              }
-              if (code < code2) {
-                 set_bits(code, code2, lrun.month);
-              } else {
-                 /* this is a bit odd, but we accept it anyway */
-                 set_bits(code, 30, lrun.month);
-                 set_bits(0, code2, lrun.month);
-              }
+              /* this is a bit odd, but we accept it anyway */
+              set_bits(code, 30, lrun.month);
+              set_bits(0, code2, lrun.month);
            }
-           break;
-        case s_hourly:
-           clear_defaults();
-           set_bits(0, 23, lrun.hour);
-           set_bits(0, 30, lrun.mday);
-           set_bits(0, 11, lrun.month);
-           break;
-        case s_weekly:
-           clear_defaults();
-           set_bit(0, lrun.wday);
-           set_bits(0, 11, lrun.month);
-           break;
-        case s_daily:
-           clear_defaults();
-           set_bits(0, 30, lrun.mday);
-           set_bits(0, 11, lrun.month);
-           break;
-        case s_monthly:
-           clear_defaults();
-           set_bit(0, lrun.mday);
-           set_bits(0, 11, lrun.month);
-           break;
-        default:
-            scan_err0(lc, _("Unexpected run state\n"));
-           break;
+        } else {
+           /* Must be position */
+           if (!have_wom) {
+              clear_bits(0, 4, lrun.wom);
+              have_wom = true;
+           }
+           if (code < code2) {
+              set_bits(code, code2, lrun.wom);
+           } else {
+              set_bits(code, 4, lrun.wom);
+              set_bits(0, code2, lrun.wom);
+           }
+        }                      
+        break;
+      case s_hourly:
+        clear_defaults();
+        set_bits(0, 23, lrun.hour);
+        set_bits(0, 30, lrun.mday);
+        set_bits(0, 11, lrun.month);
+        set_bits(0, 4, lrun.wom);
+        set_bits(0, 53, lrun.woy);
+        break;
+      case s_weekly:
+        clear_defaults();
+        set_bit(0, lrun.wday);
+        set_bits(0, 11, lrun.month);
+        set_bits(0, 4, lrun.wom);
+        set_bits(0, 53, lrun.woy);
+        break;
+      case s_daily:
+        clear_defaults();
+        set_bits(0, 30, lrun.mday);
+        set_bits(0, 11, lrun.month);
+        set_bits(0, 4,  lrun.wom);
+        set_bits(0, 53, lrun.woy);
+        break;
+      case s_monthly:
+        clear_defaults();
+        set_bits(0, 11, lrun.month);
+        set_bits(0, 4,  lrun.wom);
+        set_bits(0, 53, lrun.woy);
+        break;
+      default:
+         scan_err0(lc, _("Unexpected run state\n"));
+        /* NOT REACHED */
+        break;
       }
    }
 
@@ -418,8 +574,8 @@ void store_run(LEX *lc, struct res_items *item, int index, int pass)
     * and link it into the list of run records 
     * in the schedule resource.
     */
-   if (pass == 1) {
-      trun = (RUN *) malloc(sizeof(RUN));
+   if (pass == 2) {
+      trun = (RUN *)malloc(sizeof(RUN));
       memcpy(trun, &lrun, sizeof(RUN));
       if (*run) {
         trun->next = *run;