]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Use jcr->is_xxx instead of direct tests
[bacula/bacula] / bacula / src / dird / ua_run.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *   Bacula Director -- Run Command
31  *
32  *     Kern Sibbald, December MMI
33  *
34  */
35
36 #include "bacula.h"
37 #include "dird.h"
38
39 class run_ctx {
40 public:
41    char *job_name, *level_name, *jid, *store_name, *pool_name;
42    char *where, *fileset_name, *client_name, *bootstrap, *regexwhere;
43    char *restore_client_name, *comment;
44    const char *replace;
45    char *when, *verify_job_name, *catalog_name;
46    char *previous_job_name;
47    char *since;
48    char *plugin_options;
49    const char *verify_list;
50    JOB *job;
51    JOB *verify_job;
52    JOB *previous_job;
53    USTORE *store;
54    CLIENT *client;
55    FILESET *fileset;
56    POOL *pool;
57    CAT *catalog;
58    int Priority;
59    int files;
60    bool cloned;
61    bool mod;
62    int spool_data;
63    bool spool_data_set;
64
65    /* Methods */
66    run_ctx() { memset(this, 0, sizeof(run_ctx)); 
67                store = new USTORE; };
68    ~run_ctx() { delete store; };
69 };
70
71 /* Forward referenced subroutines */
72 static void select_job_level(UAContext *ua, JCR *jcr);
73 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, 
74                 const char *verify_list, char *jid, const char *replace,
75                 char *client_name);
76 static void select_where_regexp(UAContext *ua, JCR *jcr);
77 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc);
78 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc);
79 static int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc);
80
81 /* Imported variables */
82 extern struct s_kw ReplaceOptions[];
83
84 /*
85  * For Backup and Verify Jobs
86  *     run [job=]<job-name> level=<level-name>
87  *
88  * For Restore Jobs
89  *     run <job-name> 
90  *
91  *  Returns: 0 on error
92  *           JobId if OK
93  *
94  */
95 int run_cmd(UAContext *ua, const char *cmd)
96 {
97    JCR *jcr = NULL;
98    run_ctx rc;
99    int status;
100
101    if (!open_client_db(ua)) {
102       return 1;
103    }
104
105    if (!scan_command_line_arguments(ua, rc)) {
106       return 0;
107    }
108
109    if (find_arg(ua, NT_("fdcalled")) > 0) {
110       jcr->file_bsock = dup_bsock(ua->UA_sock);
111       ua->quit = true;
112    }
113
114    /*
115     * Create JCR to run job.  NOTE!!! after this point, free_jcr()
116     *  before returning.
117     */
118    if (!jcr) {
119       jcr = new_jcr(sizeof(JCR), dird_free_jcr);
120       set_jcr_defaults(jcr, rc.job);
121       jcr->unlink_bsr = ua->jcr->unlink_bsr;    /* copy unlink flag from caller */
122       ua->jcr->unlink_bsr = false;
123    }
124    /* Transfer JobIds to new restore Job */
125    if (ua->jcr->JobIds) {
126       jcr->JobIds = ua->jcr->JobIds;
127       ua->jcr->JobIds = NULL;
128    }
129
130 try_again:
131    if (!reset_restore_context(ua, jcr, rc)) {
132       goto bail_out;
133    }
134
135
136    /* Run without prompting? */
137    if (ua->batch || find_arg(ua, NT_("yes")) > 0) {
138       goto start_job;
139    }
140
141    /*
142     * Prompt User to see if all run job parameters are correct, and
143     *   allow him to modify them.
144     */
145    if (!display_job_parameters(ua, jcr, rc.job, rc.verify_list, rc.jid, rc.replace,
146         rc.client_name)) {
147       goto bail_out;
148    }
149
150    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
151       goto bail_out;
152    }
153
154    if (strncasecmp(ua->cmd, ".mod ", 5) == 0 || 
155        (strncasecmp(ua->cmd, "mod ", 4) == 0 && strlen(ua->cmd) > 6)) {
156       parse_ua_args(ua);
157       rc.mod = true;
158       if (!scan_command_line_arguments(ua, rc)) {
159          return 0;
160       }
161       goto try_again;
162    }
163
164    /* Allow the user to modify the settings */
165    status = modify_job_parameters(ua, jcr, rc);
166    switch (status) {
167    case 0:
168       goto try_again;
169    case 1:
170       break;
171    case -1:
172       goto bail_out;
173    }
174
175
176    if (ua->cmd[0] == 0 || strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
177       JobId_t JobId;
178       Dmsg1(800, "Calling run_job job=%x\n", jcr->job);
179
180 start_job:
181       Dmsg3(100, "JobId=%u using pool %s priority=%d\n", (int)jcr->JobId, 
182             jcr->pool->name(), jcr->JobPriority);
183       Dmsg1(900, "Running a job; its spool_data = %d\n", jcr->spool_data);
184       JobId = run_job(jcr);
185       Dmsg4(100, "JobId=%u NewJobId=%d using pool %s priority=%d\n", (int)jcr->JobId, 
186             JobId, jcr->pool->name(), jcr->JobPriority);
187       free_jcr(jcr);                  /* release jcr */
188       if (JobId == 0) {
189          ua->error_msg(_("Job failed.\n"));
190       } else {
191          char ed1[50];
192          ua->send_msg(_("Job queued. JobId=%s\n"), edit_int64(JobId, ed1));
193       }
194       return JobId;
195    }
196
197 bail_out:
198    ua->send_msg(_("Job not run.\n"));
199    free_jcr(jcr);
200    return 0;                       /* do not run */
201 }
202
203 int modify_job_parameters(UAContext *ua, JCR *jcr, run_ctx &rc)
204 {
205    int i, opt;
206    /*
207     * At user request modify parameters of job to be run.
208     */
209    if (ua->cmd[0] != 0 && strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
210       FILE *fd;
211
212       start_prompt(ua, _("Parameters to modify:\n"));
213       add_prompt(ua, _("Level"));            /* 0 */
214       add_prompt(ua, _("Storage"));          /* 1 */
215       add_prompt(ua, _("Job"));              /* 2 */
216       add_prompt(ua, _("FileSet"));          /* 3 */
217       if (jcr->getJobType() == JT_RESTORE) {
218          add_prompt(ua, _("Restore Client"));   /* 4 */
219       } else {
220          add_prompt(ua, _("Client"));        /* 4 */
221       }
222       add_prompt(ua, _("When"));             /* 5 */
223       add_prompt(ua, _("Priority"));         /* 6 */
224       if (jcr->getJobType() == JT_BACKUP ||
225           jcr->getJobType() == JT_COPY ||
226           jcr->getJobType() == JT_MIGRATE ||
227           jcr->getJobType() == JT_VERIFY) {
228          add_prompt(ua, _("Pool"));          /* 7 */
229          if (jcr->getJobType() == JT_VERIFY) {
230             add_prompt(ua, _("Verify Job"));  /* 8 */
231          }
232       } else if (jcr->getJobType() == JT_RESTORE) {
233          add_prompt(ua, _("Bootstrap"));     /* 7 */
234          add_prompt(ua, _("Where"));         /* 8 */
235          add_prompt(ua, _("File Relocation"));/* 9 */    
236          add_prompt(ua, _("Replace"));       /* 10 */
237          add_prompt(ua, _("JobId"));         /* 11 */
238       }
239       if (jcr->getJobType() == JT_BACKUP || jcr->getJobType() == JT_RESTORE) {
240          add_prompt(ua, _("Plugin Options")); /* 12 */
241       }
242       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
243       case 0:
244          /* Level */
245          select_job_level(ua, jcr);
246          goto try_again;
247       case 1:
248          /* Storage */
249          rc.store->store = select_storage_resource(ua);
250          if (rc.store->store) {
251             pm_strcpy(rc.store->store_source, _("user selection"));
252             set_rwstorage(jcr, rc.store);
253             goto try_again;
254          }
255          break;
256       case 2:
257          /* Job */
258          rc.job = select_job_resource(ua);
259          if (rc.job) {
260             jcr->job = rc.job;
261             set_jcr_defaults(jcr, rc.job);
262             goto try_again;
263          }
264          break;
265       case 3:
266          /* FileSet */
267          rc.fileset = select_fileset_resource(ua);
268          if (rc.fileset) {
269             jcr->fileset = rc.fileset;
270             goto try_again;
271          }
272          break;
273       case 4:
274          /* Client */
275          rc.client = select_client_resource(ua);
276          if (rc.client) {
277             jcr->client = rc.client;
278             goto try_again;
279          }
280          break;
281       case 5:
282          /* When */
283          if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
284             break;
285          }
286          if (ua->cmd[0] == 0) {
287             jcr->sched_time = time(NULL);
288          } else {
289             jcr->sched_time = str_to_utime(ua->cmd);
290             if (jcr->sched_time == 0) {
291                ua->send_msg(_("Invalid time, using current time.\n"));
292                jcr->sched_time = time(NULL);
293             }
294          }
295          goto try_again;
296       case 6:
297          /* Priority */
298          if (!get_pint(ua, _("Enter new Priority: "))) {
299             break;
300          }
301          if (ua->pint32_val == 0) {
302             ua->send_msg(_("Priority must be a positive integer.\n"));
303          } else {
304             jcr->JobPriority = ua->pint32_val;
305          }
306          goto try_again;
307       case 7: 
308          /* Pool or Bootstrap depending on JobType */
309          if (jcr->getJobType() == JT_BACKUP ||
310              jcr->getJobType() == JT_COPY ||
311              jcr->getJobType() == JT_MIGRATE ||
312              jcr->getJobType() == JT_VERIFY) {      /* Pool */
313             rc.pool = select_pool_resource(ua);
314             if (rc.pool) {
315                jcr->pool = rc.pool;
316                Dmsg1(100, "Set new pool=%s\n", jcr->pool->name());
317                goto try_again;
318             }
319             break;
320          }
321
322          /* Bootstrap */
323          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
324             break;
325          }
326          if (jcr->RestoreBootstrap) {
327             free(jcr->RestoreBootstrap);
328             jcr->RestoreBootstrap = NULL;
329          }
330          if (ua->cmd[0] != 0) {
331             jcr->RestoreBootstrap = bstrdup(ua->cmd);
332             fd = fopen(jcr->RestoreBootstrap, "rb");
333             if (!fd) {
334                berrno be;
335                ua->send_msg(_("Warning cannot open %s: ERR=%s\n"),
336                   jcr->RestoreBootstrap, be.bstrerror());
337                free(jcr->RestoreBootstrap);
338                jcr->RestoreBootstrap = NULL;
339             } else {
340                fclose(fd);
341             }
342          }
343          goto try_again;
344       case 8:
345          /* Verify Job */
346          if (jcr->getJobType() == JT_VERIFY) {
347             rc.verify_job = select_job_resource(ua);
348             if (rc.verify_job) {
349               jcr->verify_job = rc.verify_job;
350             }
351             goto try_again;
352          }
353          /* Where */
354          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
355             break;
356          }
357          if (jcr->RegexWhere) { /* cannot use regexwhere and where */
358             free(jcr->RegexWhere);
359             jcr->RegexWhere = NULL;
360          }
361          if (jcr->where) {
362             free(jcr->where);
363             jcr->where = NULL;
364          }
365          if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
366             ua->cmd[0] = 0;
367          }
368          jcr->where = bstrdup(ua->cmd);
369          goto try_again;
370       case 9: 
371          /* File relocation */
372          select_where_regexp(ua, jcr);
373          goto try_again;
374       case 10:
375          /* Replace */
376          start_prompt(ua, _("Replace:\n"));
377          for (i=0; ReplaceOptions[i].name; i++) {
378             add_prompt(ua, ReplaceOptions[i].name);
379          }
380          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
381          if (opt >=  0) {
382             rc.replace = ReplaceOptions[opt].name;
383             jcr->replace = ReplaceOptions[opt].token;
384          }
385          goto try_again;
386       case 11:
387          /* JobId */
388          rc.jid = NULL;                  /* force reprompt */
389          jcr->RestoreJobId = 0;
390          if (jcr->RestoreBootstrap) {
391             ua->send_msg(_("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
392          }
393          goto try_again;
394       case 12:        
395          /* Plugin Options */
396          if (!get_cmd(ua, _("Please Plugin Options string: "))) {
397             break;
398          }
399          if (jcr->plugin_options) {
400             free(jcr->plugin_options);
401             jcr->plugin_options = NULL;
402          }
403          jcr->plugin_options = bstrdup(ua->cmd);
404          goto try_again;
405       case -1:                        /* error or cancel */
406          goto bail_out;
407       default:
408          goto try_again;
409       }
410       goto bail_out;
411    }
412    return 1;
413
414 bail_out:
415    return -1;
416
417 try_again:
418    return 0;
419 }
420
421 /*
422  * Reset the restore context. 
423  * This subroutine can be called multiple times, so it
424  *  must keep any prior settings.
425  */
426 static bool reset_restore_context(UAContext *ua, JCR *jcr, run_ctx &rc)
427 {
428    int i;
429
430    jcr->verify_job = rc.verify_job;
431    jcr->previous_job = rc.previous_job;
432    jcr->pool = rc.pool;
433    if (jcr->pool != jcr->job->pool) {
434       pm_strcpy(jcr->pool_source, _("User input"));
435    }
436    set_rwstorage(jcr, rc.store);
437    jcr->client = rc.client;
438    pm_strcpy(jcr->client_name, rc.client->name());
439    jcr->fileset = rc.fileset;
440    jcr->ExpectedFiles = rc.files;
441    if (rc.catalog) {
442       jcr->catalog = rc.catalog;
443       pm_strcpy(jcr->catalog_source, _("User input"));
444    }
445
446    pm_strcpy(jcr->comment, rc.comment);
447
448    if (rc.where) {
449       if (jcr->where) {
450          free(jcr->where);
451       }
452       jcr->where = bstrdup(rc.where);
453       rc.where = NULL;
454    }
455
456    if (rc.regexwhere) {
457       if (jcr->RegexWhere) {
458          free(jcr->RegexWhere);
459       }
460       jcr->RegexWhere = bstrdup(rc.regexwhere);       
461       rc.regexwhere = NULL;
462    }
463
464    if (rc.when) {
465       jcr->sched_time = str_to_utime(rc.when);
466       if (jcr->sched_time == 0) {
467          ua->send_msg(_("Invalid time, using current time.\n"));
468          jcr->sched_time = time(NULL);
469       }
470       rc.when = NULL;
471    }
472
473    if (rc.bootstrap) {
474       if (jcr->RestoreBootstrap) {
475          free(jcr->RestoreBootstrap);
476       }
477       jcr->RestoreBootstrap = bstrdup(rc.bootstrap);
478       rc.bootstrap = NULL;
479    }
480
481    if (rc.plugin_options) {
482       if (jcr->plugin_options) {
483          free(jcr->plugin_options);
484       }
485       jcr->plugin_options = bstrdup(rc.plugin_options);
486       rc.plugin_options = NULL;
487    }
488
489
490    if (rc.replace) {
491       jcr->replace = 0;
492       for (i=0; ReplaceOptions[i].name; i++) {
493          if (strcasecmp(rc.replace, ReplaceOptions[i].name) == 0) {
494             jcr->replace = ReplaceOptions[i].token;
495          }
496       }
497       if (!jcr->replace) {
498          ua->send_msg(_("Invalid replace option: %s\n"), rc.replace);
499          return false;
500       }
501    } else if (rc.job->replace) {
502       jcr->replace = rc.job->replace;
503    } else {
504       jcr->replace = REPLACE_ALWAYS;
505    }
506    rc.replace = NULL;
507
508    if (rc.Priority) {
509       jcr->JobPriority = rc.Priority;
510       rc.Priority = 0;
511    }
512
513    if (rc.since) {
514       if (!jcr->stime) {
515          jcr->stime = get_pool_memory(PM_MESSAGE);
516       }
517       pm_strcpy(jcr->stime, rc.since);
518       rc.since = NULL;
519    }
520
521    if (rc.cloned) {
522       jcr->cloned = rc.cloned;
523       rc.cloned = false;
524    }
525
526
527    /* If pool changed, update migration write storage */
528    if (jcr->is_JobType(JT_MIGRATE) || jcr->is_JobType(JT_COPY) ||
529       (jcr->is_JobType(JT_BACKUP) && jcr->is_JobLevel(L_VIRTUAL_FULL))) {
530       if (!set_migration_wstorage(jcr, rc.pool)) {
531          return false;
532       }
533    }
534    rc.replace = ReplaceOptions[0].name;
535    for (i=0; ReplaceOptions[i].name; i++) {
536       if (ReplaceOptions[i].token == jcr->replace) {
537          rc.replace = ReplaceOptions[i].name;
538       }
539    }
540    if (rc.level_name) {
541       if (!get_level_from_name(jcr, rc.level_name)) {
542          ua->send_msg(_("Level \"%s\" not valid.\n"), rc.level_name);
543          return false;
544       }
545       rc.level_name = NULL;
546    }
547    if (rc.jid) {
548       /* Note, this is also MigrateJobId and a VerifyJobId */
549       jcr->RestoreJobId = str_to_int64(rc.jid);
550       rc.jid = 0;
551    }
552    return true;
553 }
554
555 static void select_where_regexp(UAContext *ua, JCR *jcr)
556 {
557    alist *regs;
558    char *strip_prefix, *add_prefix, *add_suffix, *rwhere;
559    strip_prefix = add_suffix = rwhere = add_prefix = NULL;
560
561 try_again_reg:
562    ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s\n"),
563                 NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix));
564
565    start_prompt(ua, _("This will replace your current Where value\n"));
566    add_prompt(ua, _("Strip prefix"));                /* 0 */
567    add_prompt(ua, _("Add prefix"));                  /* 1 */
568    add_prompt(ua, _("Add file suffix"));             /* 2 */
569    add_prompt(ua, _("Enter a regexp"));              /* 3 */
570    add_prompt(ua, _("Test filename manipulation"));  /* 4 */
571    add_prompt(ua, _("Use this ?"));                  /* 5 */
572    
573    switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
574    case 0:
575       /* Strip prefix */
576       if (get_cmd(ua, _("Please enter path prefix to strip: "))) {
577          if (strip_prefix) bfree(strip_prefix);
578          strip_prefix = bstrdup(ua->cmd);
579       }
580       
581       goto try_again_reg;
582    case 1:
583       /* Add prefix */
584       if (get_cmd(ua, _("Please enter path prefix to add (/ for none): "))) {
585          if (IsPathSeparator(ua->cmd[0]) && ua->cmd[1] == '\0') {
586             ua->cmd[0] = 0;
587          }
588
589          if (add_prefix) bfree(add_prefix);
590          add_prefix = bstrdup(ua->cmd);
591       }
592       goto try_again_reg;
593    case 2:
594       /* Add suffix */
595       if (get_cmd(ua, _("Please enter file suffix to add: "))) {
596          if (add_suffix) bfree(add_suffix);
597          add_suffix = bstrdup(ua->cmd);
598       }      
599       goto try_again_reg;
600    case 3:
601       /* Add rwhere */
602       if (get_cmd(ua, _("Please enter a valid regexp (!from!to!): "))) {
603          if (rwhere) bfree(rwhere);
604          rwhere = bstrdup(ua->cmd);
605       }
606       
607       goto try_again_reg;      
608    case 4:
609       /* Test regexp */ 
610       char *result;
611       char *regexp;
612       
613       if (rwhere && rwhere[0] != '\0') {
614          regs = get_bregexps(rwhere);
615          ua->send_msg(_("regexwhere=%s\n"), NPRT(rwhere));
616       } else {
617          int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
618          regexp = (char *) bmalloc (len * sizeof(char));
619          bregexp_build_where(regexp, len, strip_prefix, add_prefix, add_suffix);
620          regs = get_bregexps(regexp);
621          ua->send_msg(_("strip_prefix=%s add_prefix=%s add_suffix=%s result=%s\n"),
622                       NPRT(strip_prefix), NPRT(add_prefix), NPRT(add_suffix), NPRT(regexp));
623          
624          bfree(regexp);
625       }
626
627       if (!regs) {
628          ua->send_msg(_("Cannot use your regexp\n"));
629          goto try_again_reg;
630       }
631       ua->send_msg(_("Enter a period (.) to stop this test\n"));
632       while (get_cmd(ua, _("Please enter filename to test: "))) {
633          apply_bregexps(ua->cmd, regs, &result);
634          ua->send_msg(_("%s -> %s\n"), ua->cmd, result);
635       }
636       free_bregexps(regs);
637       delete regs;
638       goto try_again_reg;
639
640    case 5:
641       /* OK */
642       break;
643    case -1:                        /* error or cancel */
644       goto bail_out_reg;
645    default:
646       goto try_again_reg;
647    }
648
649    /* replace the existing where */
650    if (jcr->where) {
651       bfree(jcr->where);
652       jcr->where = NULL;
653    }
654
655    /* replace the existing regexwhere */
656    if (jcr->RegexWhere) {
657       bfree(jcr->RegexWhere);
658       jcr->RegexWhere = NULL;
659    }
660
661    if (rwhere) {
662       jcr->RegexWhere = bstrdup(rwhere);
663    } else if (strip_prefix || add_prefix || add_suffix) {
664       int len = bregexp_get_build_where_size(strip_prefix, add_prefix, add_suffix);
665       jcr->RegexWhere = (char *) bmalloc(len*sizeof(char));
666       bregexp_build_where(jcr->RegexWhere, len, strip_prefix, add_prefix, add_suffix);
667    }
668
669    regs = get_bregexps(jcr->RegexWhere);
670    if (regs) {
671       free_bregexps(regs);
672       delete regs;
673    } else {
674       if (jcr->RegexWhere) {
675          bfree(jcr->RegexWhere);
676          jcr->RegexWhere = NULL;
677       }
678       ua->send_msg(_("Cannot use your regexp.\n"));
679    }
680
681 bail_out_reg:
682    if (strip_prefix) bfree(strip_prefix);
683    if (add_prefix)   bfree(add_prefix);
684    if (add_suffix)   bfree(add_suffix);
685    if (rwhere)       bfree(rwhere);
686 }
687
688 static void select_job_level(UAContext *ua, JCR *jcr)
689 {
690    if (jcr->getJobType() == JT_BACKUP) {
691       start_prompt(ua, _("Levels:\n"));
692 //    add_prompt(ua, _("Base"));
693       add_prompt(ua, _("Full"));
694       add_prompt(ua, _("Incremental"));
695       add_prompt(ua, _("Differential"));
696       add_prompt(ua, _("Since"));
697       add_prompt(ua, _("VirtualFull"));
698       switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
699 //    case 0:
700 //       jcr->JobLevel = L_BASE;
701 //       break;
702       case 0:
703          jcr->setJobLevel(L_FULL);
704          break;
705       case 1:
706          jcr->setJobLevel(L_INCREMENTAL);
707          break;
708       case 2:
709          jcr->setJobLevel(L_DIFFERENTIAL);
710          break;
711       case 3:
712          jcr->setJobLevel(L_SINCE);
713          break;
714       case 4:
715          jcr->setJobLevel(L_VIRTUAL_FULL);
716          break;
717       default:
718          break;
719       }
720    } else if (jcr->getJobType() == JT_VERIFY) {
721       start_prompt(ua, _("Levels:\n"));
722       add_prompt(ua, _("Initialize Catalog"));
723       add_prompt(ua, _("Verify Catalog"));
724       add_prompt(ua, _("Verify Volume to Catalog"));
725       add_prompt(ua, _("Verify Disk to Catalog"));
726       add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
727       switch (do_prompt(ua, "",  _("Select level"), NULL, 0)) {
728       case 0:
729          jcr->setJobLevel(L_VERIFY_INIT);
730          break;
731       case 1:
732          jcr->setJobLevel(L_VERIFY_CATALOG);
733          break;
734       case 2:
735          jcr->setJobLevel(L_VERIFY_VOLUME_TO_CATALOG);
736          break;
737       case 3:
738          jcr->setJobLevel(L_VERIFY_DISK_TO_CATALOG);
739          break;
740       case 4:
741          jcr->setJobLevel(L_VERIFY_DATA);
742          break;
743       default:
744          break;
745       }
746    } else {
747       ua->warning_msg(_("Level not appropriate for this Job. Cannot be changed.\n"));
748    }
749    return;
750 }
751
752 static bool display_job_parameters(UAContext *ua, JCR *jcr, JOB *job, const char *verify_list,
753    char *jid, const char *replace, char *client_name) 
754 {
755    char ec1[30];
756    char dt[MAX_TIME_LENGTH];
757
758    Dmsg1(800, "JobType=%c\n", jcr->getJobType());
759    switch (jcr->getJobType()) {
760    case JT_ADMIN:
761       if (ua->api) {
762          ua->signal(BNET_RUN_CMD);   
763          ua->send_msg("Type: Admin\n"
764                      "Title: Run Admin Job\n"
765                      "JobName:  %s\n"
766                      "FileSet:  %s\n"
767                      "Client:   %s\n"
768                      "Storage:  %s\n"
769                      "When:     %s\n"
770                      "Priority: %d\n",
771                  job->name(),
772                  jcr->fileset->name(),
773                  NPRT(jcr->client->name()),
774                  jcr->wstore?jcr->wstore->name():"*None*",
775                  bstrutime(dt, sizeof(dt), jcr->sched_time),
776                  jcr->JobPriority);
777       } else {
778          ua->send_msg(_("Run Admin Job\n"
779                      "JobName:  %s\n"
780                      "FileSet:  %s\n"
781                      "Client:   %s\n"
782                      "Storage:  %s\n"
783                      "When:     %s\n"
784                      "Priority: %d\n"),
785                  job->name(),
786                  jcr->fileset->name(),
787                  NPRT(jcr->client->name()),
788                  jcr->wstore?jcr->wstore->name():"*None*",
789                  bstrutime(dt, sizeof(dt), jcr->sched_time),
790                  jcr->JobPriority);
791       }
792       jcr->setJobLevel(L_FULL);
793       break;
794    case JT_BACKUP:
795    case JT_VERIFY:
796       if (jcr->getJobType() == JT_BACKUP) {
797          if (ua->api) {
798             ua->signal(BNET_RUN_CMD);   
799             ua->send_msg("Type: Backup\n"
800                         "Title: Run Backup Job\n"
801                         "JobName:  %s\n"
802                         "Level:    %s\n"
803                         "Client:   %s\n"
804                         "FileSet:  %s\n"
805                         "Pool:     %s\n"
806                         "Storage:  %s\n"
807                         "When:     %s\n"
808                         "Priority: %d\n"
809                         "%s%s%s",
810                  job->name(),
811                  level_to_str(jcr->getJobLevel()),
812                  jcr->client->name(),
813                  jcr->fileset->name(),
814                  NPRT(jcr->pool->name()),
815                  jcr->wstore?jcr->wstore->name():"*None*",
816                  bstrutime(dt, sizeof(dt), jcr->sched_time),
817                  jcr->JobPriority,
818                  jcr->plugin_options?"Plugin Options: ":"",
819                  jcr->plugin_options?jcr->plugin_options:"",
820                  jcr->plugin_options?"\n":"");
821          } else {
822             ua->send_msg(_("Run Backup job\n"
823                         "JobName:  %s\n"
824                         "Level:    %s\n"
825                         "Client:   %s\n"
826                         "FileSet:  %s\n"
827                         "Pool:     %s (From %s)\n"
828                         "Storage:  %s (From %s)\n"
829                         "When:     %s\n"
830                         "Priority: %d\n"
831                         "%s%s%s"),
832                  job->name(),
833                  level_to_str(jcr->getJobLevel()),
834                  jcr->client->name(),
835                  jcr->fileset->name(),
836                  NPRT(jcr->pool->name()), jcr->pool_source,
837                  jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
838                  bstrutime(dt, sizeof(dt), jcr->sched_time),
839                  jcr->JobPriority,
840                  jcr->plugin_options?"Plugin Options: ":"",
841                  jcr->plugin_options?jcr->plugin_options:"",
842                  jcr->plugin_options?"\n":"");
843          }
844       } else {  /* JT_VERIFY */
845          JOB_DBR jr;
846          const char *Name;
847          if (jcr->verify_job) {
848             Name = jcr->verify_job->name();
849          } else if (jcr->RestoreJobId) { /* Display job name if jobid requested */
850             memset(&jr, 0, sizeof(jr));
851             jr.JobId = jcr->RestoreJobId;
852             if (!db_get_job_record(jcr, ua->db, &jr)) {
853                ua->error_msg(_("Could not get job record for selected JobId. ERR=%s"),
854                     db_strerror(ua->db));
855                return false;
856             }
857             Name = jr.Job;
858          } else {
859             Name = "";
860          }
861          if (!verify_list) {
862             verify_list = job->WriteVerifyList;
863          }
864          if (!verify_list) {
865             verify_list = "";
866          }
867          if (ua->api) {
868             ua->signal(BNET_RUN_CMD);   
869             ua->send_msg("Type: Verify\n"
870                         "Title: Run Verify Job\n"
871                         "JobName:     %s\n"
872                         "Level:       %s\n"
873                         "Client:      %s\n"
874                         "FileSet:     %s\n"
875                         "Pool:        %s (From %s)\n"
876                         "Storage:     %s (From %s)\n"
877                         "Verify Job:  %s\n"
878                         "Verify List: %s\n"
879                         "When:        %s\n"
880                         "Priority:    %d\n",
881               job->name(),
882               level_to_str(jcr->getJobLevel()),
883               jcr->client->name(),
884               jcr->fileset->name(),
885               NPRT(jcr->pool->name()), jcr->pool_source,
886               jcr->rstore->name(), jcr->rstore_source,
887               Name,
888               verify_list,
889               bstrutime(dt, sizeof(dt), jcr->sched_time),
890               jcr->JobPriority);
891          } else {
892             ua->send_msg(_("Run Verify Job\n"
893                         "JobName:     %s\n"
894                         "Level:       %s\n"
895                         "Client:      %s\n"
896                         "FileSet:     %s\n"
897                         "Pool:        %s (From %s)\n"
898                         "Storage:     %s (From %s)\n"
899                         "Verify Job:  %s\n"
900                         "Verify List: %s\n"
901                         "When:        %s\n"
902                         "Priority:    %d\n"),
903               job->name(),
904               level_to_str(jcr->getJobLevel()),
905               jcr->client->name(),
906               jcr->fileset->name(),
907               NPRT(jcr->pool->name()), jcr->pool_source,
908               jcr->rstore->name(), jcr->rstore_source,
909               Name,
910               verify_list,
911               bstrutime(dt, sizeof(dt), jcr->sched_time),
912               jcr->JobPriority);
913          }
914       }
915       break;
916    case JT_RESTORE:
917       if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
918          if (jid) {
919             jcr->RestoreJobId = str_to_int64(jid);
920          } else {
921             if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
922                return false;
923             }
924             jcr->RestoreJobId = ua->int64_val;
925          }
926       }
927       jcr->setJobLevel(L_FULL);      /* default level */
928       Dmsg1(800, "JobId to restore=%d\n", jcr->RestoreJobId);
929       if (jcr->RestoreJobId == 0) {
930          /* RegexWhere is take before RestoreWhere */
931          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
932             if (ua->api) {
933                ua->signal(BNET_RUN_CMD);   
934                ua->send_msg("Type: Restore\n"
935                         "Title: Run Restore Job\n"
936                         "JobName:         %s\n"
937                         "Bootstrap:       %s\n"
938                         "RegexWhere:      %s\n"
939                         "Replace:         %s\n"
940                         "FileSet:         %s\n"
941                         "Backup Client:   %s\n"
942                         "Restore Client:  %s\n"
943                         "Storage:         %s\n"
944                         "When:            %s\n"
945                         "Catalog:         %s\n"
946                         "Priority:        %d\n"
947                         "Plugin Options:  %s\n",
948                  job->name(),
949                  NPRT(jcr->RestoreBootstrap), 
950                  jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
951                  replace,
952                  jcr->fileset->name(),
953                  client_name,
954                  jcr->client->name(),
955                  jcr->rstore->name(),
956                  bstrutime(dt, sizeof(dt), jcr->sched_time),
957                  jcr->catalog->name(),
958                  jcr->JobPriority,
959                  NPRT(jcr->plugin_options));
960             } else {
961                ua->send_msg(_("Run Restore job\n"
962                         "JobName:         %s\n"
963                         "Bootstrap:       %s\n"
964                         "RegexWhere:      %s\n"
965                         "Replace:         %s\n"
966                         "FileSet:         %s\n"
967                         "Backup Client:   %s\n"
968                         "Restore Client:  %s\n"
969                         "Storage:         %s\n"
970                         "When:            %s\n"
971                         "Catalog:         %s\n"
972                         "Priority:        %d\n"
973                         "Plugin Options:  %s\n"),
974                  job->name(),
975                  NPRT(jcr->RestoreBootstrap), 
976                  jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere,
977                  replace,
978                  jcr->fileset->name(),
979                  client_name,
980                  jcr->client->name(),
981                  jcr->rstore->name(),
982                  bstrutime(dt, sizeof(dt), jcr->sched_time),
983                  jcr->catalog->name(),
984                  jcr->JobPriority,
985                  NPRT(jcr->plugin_options));
986             }
987          } else {
988             if (ua->api) {
989                ua->signal(BNET_RUN_CMD);   
990                ua->send_msg("Type: Restore\n"
991                         "Title: Run Restore job\n"
992                         "JobName:         %s\n"
993                         "Bootstrap:       %s\n"
994                         "Where:           %s\n"
995                         "Replace:         %s\n"
996                         "FileSet:         %s\n"
997                         "Backup Client:   %s\n"
998                         "Restore Client:  %s\n"
999                         "Storage:         %s\n"
1000                         "When:            %s\n"
1001                         "Catalog:         %s\n"
1002                         "Priority:        %d\n"
1003                         "Plugin Options:  %s\n",
1004                  job->name(),
1005                  NPRT(jcr->RestoreBootstrap), 
1006                  jcr->where?jcr->where:NPRT(job->RestoreWhere), 
1007                  replace,
1008                  jcr->fileset->name(),
1009                  client_name,
1010                  jcr->client->name(),
1011                  jcr->rstore->name(),
1012                  bstrutime(dt, sizeof(dt), jcr->sched_time),
1013                  jcr->catalog->name(),
1014                  jcr->JobPriority,
1015                  NPRT(jcr->plugin_options));
1016             } else {
1017                ua->send_msg(_("Run Restore job\n"
1018                         "JobName:         %s\n"
1019                         "Bootstrap:       %s\n"
1020                         "Where:           %s\n"
1021                         "Replace:         %s\n"
1022                         "FileSet:         %s\n"
1023                         "Backup Client:   %s\n"
1024                         "Restore Client:  %s\n"
1025                         "Storage:         %s\n"
1026                         "When:            %s\n"
1027                         "Catalog:         %s\n"
1028                         "Priority:        %d\n"
1029                         "Plugin Options:  %s\n"),
1030                  job->name(),
1031                  NPRT(jcr->RestoreBootstrap), 
1032                  jcr->where?jcr->where:NPRT(job->RestoreWhere), 
1033                  replace,
1034                  jcr->fileset->name(),
1035                  client_name,
1036                  jcr->client->name(),
1037                  jcr->rstore->name(),
1038                  bstrutime(dt, sizeof(dt), jcr->sched_time),
1039                  jcr->catalog->name(),
1040                  jcr->JobPriority,
1041                  NPRT(jcr->plugin_options));
1042             }
1043          }
1044
1045       } else {
1046          /* ***FIXME*** This needs to be fixed for bat */
1047          if (ua->api) ua->signal(BNET_RUN_CMD);   
1048          ua->send_msg(_("Run Restore job\n"
1049                         "JobName:    %s\n"
1050                         "Bootstrap:  %s\n"),
1051                       job->name(),
1052                       NPRT(jcr->RestoreBootstrap));
1053                       
1054          /* RegexWhere is take before RestoreWhere */
1055          if (jcr->RegexWhere || (job->RegexWhere && !jcr->where)) {
1056             ua->send_msg(_("RegexWhere: %s\n"),
1057                          jcr->RegexWhere?jcr->RegexWhere:job->RegexWhere);
1058          } else {
1059             ua->send_msg(_("Where:      %s\n"),
1060                          jcr->where?jcr->where:NPRT(job->RestoreWhere));
1061          }
1062
1063          ua->send_msg(_("Replace:         %s\n"
1064                         "Client:          %s\n"
1065                         "Storage:         %s\n"
1066                         "JobId:           %s\n"
1067                         "When:            %s\n"
1068                         "Catalog:         %s\n"
1069                         "Priority:        %d\n"
1070                         "Plugin Options:  %s\n"),
1071               replace,
1072               jcr->client->name(),
1073               jcr->rstore->name(),
1074               jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1),
1075               bstrutime(dt, sizeof(dt), jcr->sched_time),
1076               jcr->catalog->name(),
1077               jcr->JobPriority,
1078               NPRT(jcr->plugin_options));
1079       }
1080       break;
1081    case JT_COPY:
1082    case JT_MIGRATE:
1083       char *prt_type;
1084       jcr->setJobLevel(L_FULL);      /* default level */
1085       if (ua->api) {
1086          ua->signal(BNET_RUN_CMD);
1087          if (jcr->getJobType() == JT_COPY) {
1088             prt_type = (char *)"Type: Copy\nTitle: Run Copy Job\n";
1089          } else {
1090             prt_type = (char *)"Type: Migration\nTitle: Run Migration Job\n";
1091          }
1092          ua->send_msg("%s"
1093                      "JobName:       %s\n"
1094                      "Bootstrap:     %s\n"
1095                      "Client:        %s\n"
1096                      "FileSet:       %s\n"
1097                      "Pool:          %s\n"
1098                      "Read Storage:  %s\n"
1099                      "Write Storage: %s\n"
1100                      "JobId:         %s\n"
1101                      "When:          %s\n"
1102                      "Catalog:       %s\n"
1103                      "Priority:      %d\n",
1104            prt_type,
1105            job->name(),
1106            NPRT(jcr->RestoreBootstrap),
1107            jcr->client->name(),
1108            jcr->fileset->name(),
1109            NPRT(jcr->pool->name()),
1110            jcr->rstore->name(),
1111            jcr->wstore?jcr->wstore->name():"*None*",
1112            jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1113            bstrutime(dt, sizeof(dt), jcr->sched_time),
1114            jcr->catalog->name(),
1115            jcr->JobPriority);
1116       } else {
1117          if (jcr->getJobType() == JT_COPY) {
1118             prt_type = _("Run Copy job\n");
1119          } else {
1120             prt_type = _("Run Migration job\n");
1121          }
1122          ua->send_msg("%s"
1123                      "JobName:       %s\n"
1124                      "Bootstrap:     %s\n"
1125                      "Client:        %s\n"
1126                      "FileSet:       %s\n"
1127                      "Pool:          %s (From %s)\n"
1128                      "Read Storage:  %s (From %s)\n"
1129                      "Write Storage: %s (From %s)\n"
1130                      "JobId:         %s\n"
1131                      "When:          %s\n"
1132                      "Catalog:       %s\n"
1133                      "Priority:      %d\n",
1134            prt_type,
1135            job->name(),
1136            NPRT(jcr->RestoreBootstrap),
1137            jcr->client->name(),
1138            jcr->fileset->name(),
1139            NPRT(jcr->pool->name()), jcr->pool_source,
1140            jcr->rstore->name(), jcr->rstore_source,
1141            jcr->wstore?jcr->wstore->name():"*None*", jcr->wstore_source,
1142            jcr->MigrateJobId==0?"*None*":edit_uint64(jcr->MigrateJobId, ec1),
1143            bstrutime(dt, sizeof(dt), jcr->sched_time),
1144            jcr->catalog->name(),
1145            jcr->JobPriority);
1146       }
1147       break;
1148    default:
1149       ua->error_msg(_("Unknown Job Type=%d\n"), jcr->getJobType());
1150       return false;
1151    }
1152    return true;
1153 }
1154
1155
1156 static bool scan_command_line_arguments(UAContext *ua, run_ctx &rc)
1157 {
1158    bool kw_ok;
1159    int i, j;
1160    static const char *kw[] = {        /* command line arguments */
1161       "job",                          /*  Used in a switch() */
1162       "jobid",                        /* 1 */
1163       "client",                       /* 2 */
1164       "fd",
1165       "fileset",                      /* 4 */
1166       "level",                        /* 5 */
1167       "storage",                      /* 6 */
1168       "sd",                           /* 7 */
1169       "regexwhere",                   /* 8 where string as a bregexp */
1170       "where",                        /* 9 */
1171       "bootstrap",                    /* 10 */
1172       "replace",                      /* 11 */
1173       "when",                         /* 12 */
1174       "priority",                     /* 13 */
1175       "yes",          /* 14  -- if you change this change YES_POS too */
1176       "verifyjob",                    /* 15 */
1177       "files",                        /* 16 number of files to restore */
1178       "catalog",                      /* 17 override catalog */
1179       "since",                        /* 18 since */
1180       "cloned",                       /* 19 cloned */
1181       "verifylist",                   /* 20 verify output list */
1182       "migrationjob",                 /* 21 migration job name */
1183       "pool",                         /* 22 */
1184       "backupclient",                 /* 23 */
1185       "restoreclient",                /* 24 */
1186       "pluginoptions",                /* 25 */
1187       "spooldata",                    /* 26 */
1188       "comment",                      /* 27 */
1189       NULL};
1190
1191 #define YES_POS 14
1192
1193    rc.catalog_name = NULL;
1194    rc.job_name = NULL;
1195    rc.pool_name = NULL;
1196    rc.store_name = NULL;
1197    rc.client_name = NULL;
1198    rc.restore_client_name = NULL;
1199    rc.fileset_name = NULL;
1200    rc.verify_job_name = NULL;
1201    rc.previous_job_name = NULL;
1202    rc.spool_data_set = 0;
1203    rc.comment = NULL;
1204
1205    for (i=1; i<ua->argc; i++) {
1206       Dmsg2(800, "Doing arg %d = %s\n", i, ua->argk[i]);
1207       kw_ok = false;
1208       /* Keep looking until we find a good keyword */
1209       for (j=0; !kw_ok && kw[j]; j++) {
1210          if (strcasecmp(ua->argk[i], kw[j]) == 0) {
1211             /* Note, yes and run have no value, so do not fail */
1212             if (!ua->argv[i] && j != YES_POS /*yes*/) {
1213                ua->send_msg(_("Value missing for keyword %s\n"), ua->argk[i]);
1214                return false;
1215             }
1216             Dmsg1(800, "Got keyword=%s\n", NPRT(kw[j]));
1217             switch (j) {
1218             case 0: /* job */
1219                if (rc.job_name) {
1220                   ua->send_msg(_("Job name specified twice.\n"));
1221                   return false;
1222                }
1223                rc.job_name = ua->argv[i];
1224                kw_ok = true;
1225                break;
1226             case 1: /* JobId */
1227                if (rc.jid && !rc.mod) {
1228                   ua->send_msg(_("JobId specified twice.\n"));
1229                   return false;
1230                }
1231                rc.jid = ua->argv[i];
1232                kw_ok = true;
1233                break;
1234             case 2: /* client */
1235             case 3: /* fd */
1236                if (rc.client_name) {
1237                   ua->send_msg(_("Client specified twice.\n"));
1238                   return false;
1239                }
1240                rc.client_name = ua->argv[i];
1241                kw_ok = true;
1242                break;
1243             case 4: /* fileset */
1244                if (rc.fileset_name) {
1245                   ua->send_msg(_("FileSet specified twice.\n"));
1246                   return false;
1247                }
1248                rc.fileset_name = ua->argv[i];
1249                kw_ok = true;
1250                break;
1251             case 5: /* level */
1252                if (rc.level_name) {
1253                   ua->send_msg(_("Level specified twice.\n"));
1254                   return false;
1255                }
1256                rc.level_name = ua->argv[i];
1257                kw_ok = true;
1258                break;
1259             case 6: /* storage */
1260             case 7: /* sd */
1261                if (rc.store_name) {
1262                   ua->send_msg(_("Storage specified twice.\n"));
1263                   return false;
1264                }
1265                rc.store_name = ua->argv[i];
1266                kw_ok = true;
1267                break;
1268             case 8: /* regexwhere */
1269                 if ((rc.regexwhere || rc.where) && !rc.mod) {
1270                   ua->send_msg(_("RegexWhere or Where specified twice.\n"));
1271                   return false;
1272                }
1273                rc.regexwhere = ua->argv[i];
1274                if (!acl_access_ok(ua, Where_ACL, rc.regexwhere)) {
1275                   ua->send_msg(_("No authorization for \"regexwhere\" specification.\n"));
1276                   return false;
1277                }
1278                kw_ok = true;
1279                break;
1280            case 9: /* where */
1281                if ((rc.where || rc.regexwhere) && !rc.mod) {
1282                   ua->send_msg(_("Where or RegexWhere specified twice.\n"));
1283                   return false;
1284                }
1285                rc.where = ua->argv[i];
1286                if (!acl_access_ok(ua, Where_ACL, rc.where)) {
1287                   ua->send_msg(_("No authoriztion for \"where\" specification.\n"));
1288                   return false;
1289                }
1290                kw_ok = true;
1291                break;
1292             case 10: /* bootstrap */
1293                if (rc.bootstrap && !rc.mod) {
1294                   ua->send_msg(_("Bootstrap specified twice.\n"));
1295                   return false;
1296                }
1297                rc.bootstrap = ua->argv[i];
1298                kw_ok = true;
1299                break;
1300             case 11: /* replace */
1301                if (rc.replace && !rc.mod) {
1302                   ua->send_msg(_("Replace specified twice.\n"));
1303                   return false;
1304                }
1305                rc.replace = ua->argv[i];
1306                kw_ok = true;
1307                break;
1308             case 12: /* When */
1309                if (rc.when && !rc.mod) {
1310                   ua->send_msg(_("When specified twice.\n"));
1311                   return false;
1312                }
1313                rc.when = ua->argv[i];
1314                kw_ok = true;
1315                break;
1316             case 13:  /* Priority */
1317                if (rc.Priority && !rc.mod) {
1318                   ua->send_msg(_("Priority specified twice.\n"));
1319                   return false;
1320                }
1321                rc.Priority = atoi(ua->argv[i]);
1322                if (rc.Priority <= 0) {
1323                   ua->send_msg(_("Priority must be positive nonzero setting it to 10.\n"));
1324                   rc.Priority = 10;
1325                }
1326                kw_ok = true;
1327                break;
1328             case 14: /* yes */
1329                kw_ok = true;
1330                break;
1331             case 15: /* Verify Job */
1332                if (rc.verify_job_name) {
1333                   ua->send_msg(_("Verify Job specified twice.\n"));
1334                   return false;
1335                }
1336                rc.verify_job_name = ua->argv[i];
1337                kw_ok = true;
1338                break;
1339             case 16: /* files */
1340                rc.files = atoi(ua->argv[i]);
1341                kw_ok = true;
1342                break;
1343
1344             case 17: /* catalog */
1345                rc.catalog_name = ua->argv[i];
1346                kw_ok = true;
1347                break;
1348
1349             case 18: /* since */
1350                rc.since = ua->argv[i];
1351                kw_ok = true; 
1352                break;
1353
1354             case 19: /* cloned */
1355                rc. cloned = true;
1356                kw_ok = true;
1357                break;
1358
1359             case 20: /* write verify list output */
1360                rc.verify_list = ua->argv[i];
1361                kw_ok = true;
1362                break;
1363             case 21: /* Migration Job */
1364                if (rc.previous_job_name) {
1365                   ua->send_msg(_("Migration Job specified twice.\n"));
1366                   return false;
1367                }
1368                rc.previous_job_name = ua->argv[i];
1369                kw_ok = true;
1370                break;
1371             case 22: /* pool */
1372                if (rc.pool_name) {
1373                   ua->send_msg(_("Pool specified twice.\n"));
1374                   return false;
1375                }
1376                rc.pool_name = ua->argv[i];
1377                kw_ok = true;
1378                break;
1379             case 23: /* backupclient */
1380                if (rc.client_name) {
1381                   ua->send_msg(_("Client specified twice.\n"));
1382                   return 0;
1383                }
1384                rc.client_name = ua->argv[i];
1385                kw_ok = true;
1386                break;
1387             case 24: /* restoreclient */
1388                if (rc.restore_client_name && !rc.mod) {
1389                   ua->send_msg(_("Restore Client specified twice.\n"));
1390                   return false;
1391                }
1392                rc.restore_client_name = ua->argv[i];
1393                kw_ok = true;
1394                break;
1395             case 25: /* pluginoptions */
1396                ua->send_msg(_("Plugin Options not yet implemented.\n"));
1397                return false;
1398                if (rc.plugin_options) {
1399                   ua->send_msg(_("Plugin Options specified twice.\n"));
1400                   return false;
1401                }
1402                rc.plugin_options = ua->argv[i];
1403                if (!acl_access_ok(ua, PluginOptions_ACL, rc.plugin_options)) {
1404                   ua->send_msg(_("No authoriztion for \"PluginOptions\" specification.\n"));
1405                   return false;
1406                }
1407                kw_ok = true;
1408                break;
1409             case 26: /* spooldata */
1410                if (rc.spool_data_set) {
1411                   ua->send_msg(_("Spool flag specified twice.\n"));
1412                   return false;
1413                }
1414                if (is_yesno(ua->argv[i], &rc.spool_data)) {
1415                   rc.spool_data_set = 1;
1416                   kw_ok = true;
1417                } else {
1418                   ua->send_msg(_("Invalid spooldata flag.\n"));
1419                }
1420                break;
1421             case 27: /* comment */
1422                rc.comment = ua->argv[i];
1423                kw_ok = true;
1424             default:
1425                break;
1426             }
1427          } /* end strcase compare */
1428       } /* end keyword loop */
1429       /*
1430        * End of keyword for loop -- if not found, we got a bogus keyword
1431        */
1432       if (!kw_ok) {
1433          Dmsg1(800, "%s not found\n", ua->argk[i]);
1434          /*
1435           * Special case for Job Name, it can be the first
1436           * keyword that has no value.
1437           */
1438          if (!rc.job_name && !ua->argv[i]) {
1439             rc.job_name = ua->argk[i];   /* use keyword as job name */
1440             Dmsg1(800, "Set jobname=%s\n", rc.job_name);
1441          } else {
1442             ua->send_msg(_("Invalid keyword: %s\n"), ua->argk[i]);
1443             return false;
1444          }
1445       }
1446    } /* end argc loop */
1447              
1448    Dmsg0(800, "Done scan.\n");
1449    if (rc.comment) {
1450       if (!is_comment_legal(ua, rc.comment)) {
1451          return false;
1452       }
1453    }
1454    if (rc.catalog_name) {
1455        rc.catalog = GetCatalogResWithName(rc.catalog_name);
1456        if (rc.catalog == NULL) {
1457             ua->error_msg(_("Catalog \"%s\" not found\n"), rc.catalog_name);
1458            return false;
1459        }
1460        if (!acl_access_ok(ua, Catalog_ACL, rc.catalog->name())) {
1461           ua->error_msg(_("No authorization. Catalog \"%s\".\n"), rc.catalog->name());
1462           return false;
1463        }
1464    }
1465    Dmsg1(800, "Using catalog=%s\n", NPRT(rc.catalog_name));
1466
1467    if (rc.job_name) {
1468       /* Find Job */
1469       rc.job = GetJobResWithName(rc.job_name);
1470       if (!rc.job) {
1471          if (*rc.job_name != 0) {
1472             ua->send_msg(_("Job \"%s\" not found\n"), rc.job_name);
1473          }
1474          rc.job = select_job_resource(ua);
1475       } else {
1476          Dmsg1(800, "Found job=%s\n", rc.job_name);
1477       }
1478    } else if (!rc.job) {
1479       ua->send_msg(_("A job name must be specified.\n"));
1480       rc.job = select_job_resource(ua);
1481    }
1482    if (!rc.job) {
1483       return false;
1484    } else if (!acl_access_ok(ua, Job_ACL, rc.job->name())) {
1485       ua->error_msg( _("No authorization. Job \"%s\".\n"), rc.job->name());
1486       return false;
1487    }
1488
1489    if (rc.pool_name) {
1490       rc.pool = GetPoolResWithName(rc.pool_name);
1491       if (!rc.pool) {
1492          if (*rc.pool_name != 0) {
1493             ua->warning_msg(_("Pool \"%s\" not found.\n"), rc.pool_name);
1494          }
1495          rc.pool = select_pool_resource(ua);
1496       }
1497    } else if (!rc.pool) {
1498       rc.pool = rc.job->pool;             /* use default */
1499    }
1500    if (!rc.pool) {
1501       return false;
1502    } else if (!acl_access_ok(ua, Pool_ACL, rc.pool->name())) {
1503       ua->error_msg(_("No authorization. Pool \"%s\".\n"), rc.pool->name());
1504       return false;
1505    }
1506    Dmsg1(100, "Using pool %s\n", rc.pool->name());
1507
1508    if (rc.spool_data_set) {
1509       rc.job->spool_data = rc.spool_data;
1510    }
1511    Dmsg1(900, "Spooling data: %s\n", (rc.job->spool_data ? "Yes" : "No"));
1512
1513    if (rc.store_name) {
1514       rc.store->store = GetStoreResWithName(rc.store_name);
1515       pm_strcpy(rc.store->store_source, _("command line"));
1516       if (!rc.store->store) {
1517          if (*rc.store_name != 0) {
1518             ua->warning_msg(_("Storage \"%s\" not found.\n"), rc.store_name);
1519          }
1520          rc.store->store = select_storage_resource(ua);
1521          pm_strcpy(rc.store->store_source, _("user selection"));
1522       }
1523    } else if (!rc.store->store) {
1524       get_job_storage(rc.store, rc.job, NULL);      /* use default */
1525    }
1526    if (!rc.store->store) {
1527       ua->error_msg(_("No storage specified.\n"));
1528       return false;
1529    } else if (!acl_access_ok(ua, Storage_ACL, rc.store->store->name())) {
1530       ua->error_msg(_("No authorization. Storage \"%s\".\n"),
1531                rc.store->store->name());
1532       return false;
1533    }
1534    Dmsg1(800, "Using storage=%s\n", rc.store->store->name());
1535
1536    if (rc.client_name) {
1537       rc.client = GetClientResWithName(rc.client_name);
1538       if (!rc.client) {
1539          if (*rc.client_name != 0) {
1540             ua->warning_msg(_("Client \"%s\" not found.\n"), rc.client_name);
1541          }
1542          rc.client = select_client_resource(ua);
1543       }
1544    } else if (!rc.client) {
1545       rc.client = rc.job->client;           /* use default */
1546    }
1547    if (!rc.client) {
1548       return false;
1549    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1550       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1551                rc.client->name());
1552       return false;
1553    }
1554    Dmsg1(800, "Using client=%s\n", rc.client->name());
1555
1556    if (rc.restore_client_name) {
1557       rc.client = GetClientResWithName(rc.restore_client_name);
1558       if (!rc.client) {
1559          if (*rc.restore_client_name != 0) {
1560             ua->warning_msg(_("Restore Client \"%s\" not found.\n"), rc.restore_client_name);
1561          }
1562          rc.client = select_client_resource(ua);
1563       }
1564    } else if (!rc.client) {
1565       rc.client = rc.job->client;           /* use default */
1566    }
1567    if (!rc.client) {
1568       return false;
1569    } else if (!acl_access_ok(ua, Client_ACL, rc.client->name())) {
1570       ua->error_msg(_("No authorization. Client \"%s\".\n"),
1571                rc.client->name());
1572       return false;
1573    }
1574    Dmsg1(800, "Using restore client=%s\n", rc.client->name());
1575
1576
1577    if (rc.fileset_name) {
1578       rc.fileset = GetFileSetResWithName(rc.fileset_name);
1579       if (!rc.fileset) {
1580          ua->send_msg(_("FileSet \"%s\" not found.\n"), rc.fileset_name);
1581          rc.fileset = select_fileset_resource(ua);
1582       }
1583    } else if (!rc.fileset) {
1584       rc.fileset = rc.job->fileset;           /* use default */
1585    }
1586    if (!rc.fileset) {
1587       return false;
1588    } else if (!acl_access_ok(ua, FileSet_ACL, rc.fileset->name())) {
1589       ua->send_msg(_("No authorization. FileSet \"%s\".\n"),
1590                rc.fileset->name());
1591       return false;
1592    }
1593
1594    if (rc.verify_job_name) {
1595       rc.verify_job = GetJobResWithName(rc.verify_job_name);
1596       if (!rc.verify_job) {
1597          ua->send_msg(_("Verify Job \"%s\" not found.\n"), rc.verify_job_name);
1598          rc.verify_job = select_job_resource(ua);
1599       }
1600    } else if (!rc.verify_job) {
1601       rc.verify_job = rc.job->verify_job;
1602    }
1603
1604    if (rc.previous_job_name) {
1605       rc.previous_job = GetJobResWithName(rc.previous_job_name);
1606       if (!rc.previous_job) {
1607          ua->send_msg(_("Migration Job \"%s\" not found.\n"), rc.previous_job_name);
1608          rc.previous_job = select_job_resource(ua);
1609       }
1610    } else {
1611       rc.previous_job = rc.job->verify_job;
1612    }
1613    return true;
1614 }