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