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