]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
- Apply Martin's patch for fixing console modifications to Verify Jobs.
[bacula/bacula] / bacula / src / dird / ua_run.c
1 /*
2  *
3  *   Bacula Director -- Run Command
4  *
5  *     Kern Sibbald, December MMI
6  *
7  *   Version $Id$
8  */
9
10 /*
11    Copyright (C) 2001-2004 Kern Sibbald and John Walker
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32
33 /* Imported subroutines */
34
35 /* Imported variables */
36 extern struct s_kw ReplaceOptions[];
37
38 /*
39  * For Backup and Verify Jobs
40  *     run [job=]<job-name> level=<level-name>
41  *
42  * For Restore Jobs
43  *     run <job-name> jobid=nn
44  *
45  */
46 int run_cmd(UAContext *ua, const char *cmd)
47 {
48    JCR *jcr;
49    char *job_name, *level_name, *jid, *store_name, *pool_name;
50    char *where, *fileset_name, *client_name, *bootstrap;
51    const char *replace;
52    char *when, *verify_job_name;
53    int Priority = 0;
54    int i, j, opt, files = 0;
55    bool kw_ok;
56    JOB *job = NULL;
57    JOB *verify_job = NULL;
58    STORE *store = NULL;
59    CLIENT *client = NULL;
60    FILESET *fileset = NULL;
61    POOL *pool = NULL;
62    static const char *kw[] = {        /* command line arguments */
63       N_("job"),                      /*  Used in a switch() */
64       N_("jobid"),                    /* 1 */
65       N_("client"),                   /* 2 */
66       N_("fd"), 
67       N_("fileset"),                  /* 4 */
68       N_("level"),                    /* 5 */
69       N_("storage"),                  /* 6 */
70       N_("sd"),                       /* 7 */
71       N_("pool"),                     /* 8 */
72       N_("where"),                    /* 9 */
73       N_("bootstrap"),                /* 10 */
74       N_("replace"),                  /* 11 */
75       N_("when"),                     /* 12 */
76       N_("priority"),                 /* 13 */
77       N_("yes"),          /* 14 -- if you change this change YES_POS too */
78       N_("verifyjob"),                /* 15 */
79       N_("files"),                    /* 16 number of files to restore */
80       NULL};
81
82 #define YES_POS 14
83
84    if (!open_db(ua)) {
85       return 1;
86    }
87
88    job_name = NULL;
89    level_name = NULL;
90    jid = NULL;
91    store_name = NULL;
92    pool_name = NULL;
93    where = NULL;
94    when = NULL;
95    client_name = NULL;
96    fileset_name = NULL;
97    bootstrap = NULL;
98    replace = NULL;
99    verify_job_name = NULL;
100
101    for (i=1; i<ua->argc; i++) {
102       Dmsg2(200, "Doing arg %d = %s\n", i, ua->argk[i]);
103       kw_ok = false;
104       /* Keep looking until we find a good keyword */
105       for (j=0; !kw_ok && kw[j]; j++) {
106          if (strcasecmp(ua->argk[i], _(kw[j])) == 0) {
107             /* Note, yes and run have no value, so do not err */
108             if (!ua->argv[i] && j != YES_POS /*yes*/) {  
109                bsendmsg(ua, _("Value missing for keyword %s\n"), ua->argk[i]);
110                return 1;
111             }
112             Dmsg1(200, "Got keyword=%s\n", kw[j]);
113             switch (j) {
114             case 0: /* job */
115                if (job_name) {
116                   bsendmsg(ua, _("Job name specified twice.\n"));
117                   return 1;
118                }
119                job_name = ua->argv[i];
120                kw_ok = true;
121                break;
122             case 1: /* JobId */
123                if (jid) {
124                   bsendmsg(ua, _("JobId specified twice.\n"));
125                   return 1;
126                }
127                jid = ua->argv[i];
128                kw_ok = true;
129                break;
130             case 2: /* client */
131             case 3: /* fd */
132                if (client_name) {
133                   bsendmsg(ua, _("Client specified twice.\n"));
134                   return 1;
135                }
136                client_name = ua->argv[i];
137                kw_ok = true;
138                break;
139             case 4: /* fileset */
140                if (fileset_name) {
141                   bsendmsg(ua, _("FileSet specified twice.\n"));
142                   return 1;
143                }
144                fileset_name = ua->argv[i];
145                kw_ok = true;
146                break;
147             case 5: /* level */
148                if (level_name) {
149                   bsendmsg(ua, _("Level specified twice.\n"));
150                   return 1;
151                }
152                level_name = ua->argv[i];
153                kw_ok = true;
154                break;
155             case 6: /* storage */
156             case 7: /* sd */
157                if (store_name) {
158                   bsendmsg(ua, _("Storage specified twice.\n"));
159                   return 1;
160                }
161                store_name = ua->argv[i];
162                kw_ok = true;
163                break;
164             case 8: /* pool */
165                if (pool_name) {
166                   bsendmsg(ua, _("Pool specified twice.\n"));
167                   return 1;
168                }
169                pool_name = ua->argv[i];
170                kw_ok = true;
171                break;
172             case 9: /* where */
173                if (where) {
174                   bsendmsg(ua, _("Where specified twice.\n"));
175                   return 1;
176                }
177                where = ua->argv[i];
178                kw_ok = true;
179                break;
180             case 10: /* bootstrap */
181                if (bootstrap) {
182                   bsendmsg(ua, _("Bootstrap specified twice.\n"));
183                   return 1;
184                }
185                bootstrap = ua->argv[i];
186                kw_ok = true;
187                break;
188             case 11: /* replace */
189                if (replace) {
190                   bsendmsg(ua, _("Replace specified twice.\n"));
191                   return 1;
192                }
193                replace = ua->argv[i];
194                kw_ok = true;
195                break;
196             case 12: /* When */
197                if (when) {
198                   bsendmsg(ua, _("When specified twice.\n"));
199                   return 1;
200                }
201                when = ua->argv[i];
202                kw_ok = true;
203                break;
204             case 13:  /* Priority */
205                if (Priority) {
206                   bsendmsg(ua, _("Priority specified twice.\n"));
207                   return 1;
208                }
209                Priority = atoi(ua->argv[i]);
210                if (Priority <= 0) {
211                   bsendmsg(ua, _("Priority must be positive nonzero setting it to 10.\n"));
212                   Priority = 10;
213                }
214                kw_ok = true;
215                break;
216             case 14: /* yes */
217                kw_ok = true;
218                break;
219             case 15: /* Verify Job */
220                if (verify_job_name) {
221                   bsendmsg(ua, _("Verify Job specified twice.\n"));
222                   return 1;
223                }
224                verify_job_name = ua->argv[i];
225                kw_ok = true;
226                break;
227             case 16: /* files */
228                files = atoi(ua->argv[i]);
229                kw_ok = true;
230                break;
231
232             default:
233                break;
234             }
235          } /* end strcase compare */
236       } /* end keyword loop */
237       /*
238        * End of keyword for loop -- if not found, we got a bogus keyword
239        */
240       if (!kw_ok) {
241          Dmsg1(200, "%s not found\n", ua->argk[i]);
242          /*
243           * Special case for Job Name, it can be the first
244           * keyword that has no value.
245           */
246          if (!job_name && !ua->argv[i]) {
247             job_name = ua->argk[i];   /* use keyword as job name */
248             Dmsg1(200, "Set jobname=%s\n", job_name);
249          } else {
250             bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
251             return 1;
252          }
253       }
254    } /* end argc loop */
255              
256    Dmsg0(200, "Done scan.\n");
257
258    if (job_name) {
259       /* Find Job */
260       job = (JOB *)GetResWithName(R_JOB, job_name);
261       if (!job) {
262          if (*job_name != 0) {
263             bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
264          }
265          job = select_job_resource(ua);
266       } else {
267          Dmsg1(200, "Found job=%s\n", job_name);
268       }
269    } else {
270       bsendmsg(ua, _("A job name must be specified.\n"));
271       job = select_job_resource(ua);
272    }
273    if (!job) {
274       return 1;
275    } else if (!acl_access_ok(ua, Job_ACL, job->hdr.name)) {
276       bsendmsg(ua, _("No authorization. Job \"%s\".\n"),
277          job->hdr.name);
278       return 1;
279    }
280
281    if (store_name) {
282       store = (STORE *)GetResWithName(R_STORAGE, store_name);
283       if (!store) {
284          if (*store_name != 0) {
285             bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
286          }
287          store = select_storage_resource(ua);
288       }
289    } else {
290       store = (STORE *)job->storage[0]->first();           /* use default */
291    }
292    if (!store) {
293       return 1;
294    } else if (!acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
295       bsendmsg(ua, _("No authorization. Storage \"%s\".\n"),
296                store->hdr.name);
297       return 1;
298    }
299
300    if (pool_name) {
301       pool = (POOL *)GetResWithName(R_POOL, pool_name);
302       if (!pool) {
303          if (*pool_name != 0) {
304             bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
305          }
306          pool = select_pool_resource(ua);
307       }
308    } else {
309       pool = job->pool;             /* use default */
310    }
311    if (!pool) {
312       return 1;
313    } else if (!acl_access_ok(ua, Pool_ACL, store->hdr.name)) {
314       bsendmsg(ua, _("No authorization. Pool \"%s\".\n"),
315                pool->hdr.name);
316       return 1;
317    }
318
319    if (client_name) {
320       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
321       if (!client) {
322          if (*client_name != 0) {
323             bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
324          }
325          client = select_client_resource(ua);
326       }
327    } else {
328       client = job->client;           /* use default */
329    }
330    if (!client) {
331       return 1;
332    } else if (!acl_access_ok(ua, Client_ACL, store->hdr.name)) {
333       bsendmsg(ua, _("No authorization. Client \"%s\".\n"),
334                client->hdr.name);
335       return 1;
336    }
337
338    if (fileset_name) {
339       fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
340       if (!fileset) {
341          bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
342          fileset = select_fileset_resource(ua);
343       }
344    } else {
345       fileset = job->fileset;           /* use default */
346    }
347    if (!fileset) {
348       return 1;
349    } else if (!acl_access_ok(ua, FileSet_ACL, store->hdr.name)) {
350       bsendmsg(ua, _("No authorization. FileSet \"%s\".\n"),
351                fileset->hdr.name);
352       return 1;
353    }
354
355    if (verify_job_name) {
356       verify_job = (JOB *)GetResWithName(R_JOB, verify_job_name);
357       if (!verify_job) {
358          bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name);
359          verify_job = select_job_resource(ua);
360       }
361    } else {
362       verify_job = job->verify_job;
363    }
364
365    /*
366     * Create JCR to run job.  NOTE!!! after this point, free_jcr()
367     *  before returning.
368     */
369    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
370    set_jcr_defaults(jcr, job);
371
372    jcr->verify_job = verify_job;
373    jcr->store = store;
374    jcr->client = client;
375    jcr->fileset = fileset;
376    jcr->pool = pool;
377    jcr->ExpectedFiles = files;
378    if (where) {
379       if (jcr->where) {
380          free(jcr->where);
381       }
382       jcr->where = bstrdup(where);
383    }
384
385    if (when) {
386       jcr->sched_time = str_to_utime(when);
387       if (jcr->sched_time == 0) {
388          bsendmsg(ua, _("Invalid time, using current time.\n"));
389          jcr->sched_time = time(NULL);
390       }
391    }
392          
393    if (bootstrap) {
394       if (jcr->RestoreBootstrap) {
395          free(jcr->RestoreBootstrap);
396       }
397       jcr->RestoreBootstrap = bstrdup(bootstrap);
398    }
399
400    if (replace) {
401       jcr->replace = 0;
402       for (i=0; ReplaceOptions[i].name; i++) {
403          if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
404             jcr->replace = ReplaceOptions[i].token;
405          }
406       }
407       if (!jcr->replace) {
408          bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
409          goto bail_out;
410       }
411    } else if (job->replace) {
412       jcr->replace = job->replace;
413    } else {
414       jcr->replace = REPLACE_ALWAYS;
415    }
416
417    if (Priority) {
418       jcr->JobPriority = Priority;
419    }
420       
421    if (find_arg(ua, _("fdcalled")) > 0) {
422       jcr->file_bsock = dup_bsock(ua->UA_sock);
423       ua->quit = true;
424    }
425
426 try_again:
427    replace = ReplaceOptions[0].name;
428    for (i=0; ReplaceOptions[i].name; i++) {
429       if (ReplaceOptions[i].token == jcr->replace) {
430          replace = ReplaceOptions[i].name;
431       }
432    }
433    if (level_name) {
434       if (!get_level_from_name(jcr, level_name)) {
435          bsendmsg(ua, _("Level %s not valid.\n"), level_name);
436          goto bail_out;
437       }
438    }
439    if (jid) {
440       jcr->RestoreJobId = atoi(jid);
441    }
442
443    /* Run without prompting? */
444    if (find_arg(ua, _("yes")) > 0) {
445       goto start_job;
446    }
447
448    /*  
449     * Prompt User to see if all run job parameters are correct, and
450     *   allow him to modify them.
451     */
452    Dmsg1(20, "JobType=%c\n", jcr->JobType);
453    switch (jcr->JobType) {
454       char ec1[30];
455       char dt[MAX_TIME_LENGTH];
456    case JT_ADMIN:
457          bsendmsg(ua, _("Run %s job\n\
458 JobName:  %s\n\
459 FileSet:  %s\n\
460 Client:   %s\n\
461 Storage:  %s\n\
462 When:     %s\n\
463 Priority: %d\n"),
464                  _("Admin"),
465                  job->hdr.name,
466                  jcr->fileset->hdr.name,
467                  NPRT(jcr->client->hdr.name),
468                  NPRT(jcr->store->hdr.name), 
469                  bstrutime(dt, sizeof(dt), jcr->sched_time), 
470                  jcr->JobPriority);
471       jcr->JobLevel = L_FULL;
472       break;
473    case JT_BACKUP:
474    case JT_VERIFY:
475       if (jcr->JobType == JT_BACKUP) {
476          bsendmsg(ua, _("Run %s job\n\
477 JobName:  %s\n\
478 FileSet:  %s\n\
479 Level:    %s\n\
480 Client:   %s\n\
481 Storage:  %s\n\
482 Pool:     %s\n\
483 When:     %s\n\
484 Priority: %d\n"),
485                  _("Backup"),
486                  job->hdr.name,
487                  jcr->fileset->hdr.name,
488                  level_to_str(jcr->JobLevel),
489                  jcr->client->hdr.name,
490                  jcr->store->hdr.name,
491                  NPRT(jcr->pool->hdr.name), 
492                  bstrutime(dt, sizeof(dt), jcr->sched_time),
493                  jcr->JobPriority);
494       } else {  /* JT_VERIFY */
495          const char *Name;
496          if (jcr->verify_job) {
497             Name = jcr->verify_job->hdr.name;
498          } else {
499             Name = "";
500          }
501          bsendmsg(ua, _("Run %s job\n\
502 JobName:     %s\n\
503 FileSet:     %s\n\
504 Level:       %s\n\
505 Client:      %s\n\
506 Storage:     %s\n\
507 Pool:        %s\n\
508 Verify Job:  %s\n\
509 When:        %s\n\
510 Priority:    %d\n"),
511               _("Verify"),
512               job->hdr.name,
513               jcr->fileset->hdr.name,
514               level_to_str(jcr->JobLevel),
515               jcr->client->hdr.name,
516               jcr->store->hdr.name,
517               NPRT(jcr->pool->hdr.name), 
518               Name,            
519               bstrutime(dt, sizeof(dt), jcr->sched_time),
520               jcr->JobPriority);
521       }
522       break;
523    case JT_RESTORE:
524       if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
525          if (jid) {
526             jcr->RestoreJobId = atoi(jid);
527          } else {
528             if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
529                goto bail_out;
530             }  
531             jcr->RestoreJobId = ua->pint32_val;
532          }
533       }
534       jcr->JobLevel = L_FULL;      /* default level */
535       Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
536       if (jcr->RestoreJobId == 0) {
537          bsendmsg(ua, _("Run Restore job\n\
538 JobName:    %s\n\
539 Bootstrap:  %s\n\
540 Where:      %s\n\
541 Replace:    %s\n\
542 FileSet:    %s\n\
543 Client:     %s\n\
544 Storage:    %s\n\
545 When:       %s\n\
546 Priority:   %d\n"),
547               job->hdr.name,
548               NPRT(jcr->RestoreBootstrap),
549               jcr->where?jcr->where:NPRT(job->RestoreWhere),
550               replace,
551               jcr->fileset->hdr.name,
552               jcr->client->hdr.name,
553               jcr->store->hdr.name, 
554               bstrutime(dt, sizeof(dt), jcr->sched_time),
555               jcr->JobPriority);
556       } else {
557          bsendmsg(ua, _("Run Restore job\n\
558 JobName:    %s\n\
559 Bootstrap:  %s\n\
560 Where:      %s\n\
561 Replace:    %s\n\
562 Client:     %s\n\
563 Storage:    %s\n\
564 JobId:      %s\n\
565 When:       %s\n\
566 Priority:   %d\n"),
567               job->hdr.name,
568               NPRT(jcr->RestoreBootstrap),
569               jcr->where?jcr->where:NPRT(job->RestoreWhere),
570               replace,
571               jcr->client->hdr.name,
572               jcr->store->hdr.name, 
573               jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), 
574               bstrutime(dt, sizeof(dt), jcr->sched_time),
575               jcr->JobPriority);
576       }
577       break;
578    default:
579       bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
580       goto bail_out;
581    }
582
583
584    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
585       goto bail_out;
586    }
587    /*
588     * At user request modify parameters of job to be run.
589     */
590    if (ua->cmd[0] == 0) {
591       goto bail_out;
592    }
593    if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
594       FILE *fd;
595
596       start_prompt(ua, _("Parameters to modify:\n"));
597       add_prompt(ua, _("Level"));            /* 0 */
598       add_prompt(ua, _("Storage"));          /* 1 */
599       add_prompt(ua, _("Job"));              /* 2 */
600       add_prompt(ua, _("FileSet"));          /* 3 */
601       add_prompt(ua, _("Client"));           /* 4 */
602       add_prompt(ua, _("When"));             /* 5 */
603       add_prompt(ua, _("Priority"));         /* 6 */
604       if (jcr->JobType == JT_BACKUP ||
605           jcr->JobType == JT_VERIFY) {
606          add_prompt(ua, _("Pool"));          /* 7 */
607          if (jcr->JobType == JT_VERIFY) {
608             add_prompt(ua, _("Verify Job"));  /* 8 */
609          }
610       } else if (jcr->JobType == JT_RESTORE) {
611          add_prompt(ua, _("Bootstrap"));     /* 7 */
612          add_prompt(ua, _("Where"));         /* 8 */
613          add_prompt(ua, _("Replace"));       /* 9 */
614          add_prompt(ua, _("JobId"));         /* 10 */
615       }
616       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
617       case 0:
618          /* Level */
619          if (jcr->JobType == JT_BACKUP) {
620             start_prompt(ua, _("Levels:\n"));
621             add_prompt(ua, _("Base"));
622             add_prompt(ua, _("Full"));
623             add_prompt(ua, _("Incremental"));
624             add_prompt(ua, _("Differential"));
625             add_prompt(ua, _("Since"));
626             switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
627             case 0:
628                jcr->JobLevel = L_BASE;
629                break;
630             case 1:
631                jcr->JobLevel = L_FULL;
632                break;
633             case 2:
634                jcr->JobLevel = L_INCREMENTAL;
635                break;
636             case 3:
637                jcr->JobLevel = L_DIFFERENTIAL;
638                break;
639             case 4:
640                jcr->JobLevel = L_SINCE;
641                break;
642             default:
643                break;
644             }
645             goto try_again;
646          } else if (jcr->JobType == JT_VERIFY) {
647             start_prompt(ua, _("Levels:\n"));
648             add_prompt(ua, _("Initialize Catalog"));
649             add_prompt(ua, _("Verify Catalog"));
650             add_prompt(ua, _("Verify Volume to Catalog"));
651             add_prompt(ua, _("Verify Disk to Catalog"));
652             add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
653             switch (do_prompt(ua, "",  _("Select level"), NULL, 0)) {
654             case 0:
655                jcr->JobLevel = L_VERIFY_INIT;
656                break;
657             case 1:
658                jcr->JobLevel = L_VERIFY_CATALOG;
659                break;
660             case 2:
661                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
662                break;
663             case 3:
664                jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
665                break;
666             case 4:
667                jcr->JobLevel = L_VERIFY_DATA;
668                break;
669             default:
670                break;
671             }
672             goto try_again;
673          } else {
674             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
675          }
676          goto try_again;
677       case 1:
678          /* Storage */
679          store = select_storage_resource(ua);
680          if (store) {
681             jcr->store = store;
682             goto try_again;
683          }
684          break;
685       case 2:
686          /* Job */
687          job = select_job_resource(ua);
688          if (job) {
689             jcr->job = job;
690             set_jcr_defaults(jcr, job);
691             goto try_again;
692          }
693          break;
694       case 3:
695          /* FileSet */
696          fileset = select_fileset_resource(ua);
697          if (fileset) {
698             jcr->fileset = fileset;
699             goto try_again;
700          }      
701          break;
702       case 4:
703          /* Client */
704          client = select_client_resource(ua);
705          if (client) {
706             jcr->client = client;
707             goto try_again;
708          }
709          break;
710       case 5:
711          /* When */
712          if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
713             break;
714          }
715          if (ua->cmd[0] == 0) {
716             jcr->sched_time = time(NULL);
717          } else {
718             jcr->sched_time = str_to_utime(ua->cmd);
719             if (jcr->sched_time == 0) {
720                bsendmsg(ua, _("Invalid time, using current time.\n"));
721                jcr->sched_time = time(NULL);
722             }
723          }
724          goto try_again;
725       case 6:
726          /* Priority */
727          if (!get_pint(ua, _("Enter new Priority: "))) {
728             break;
729          }
730          if (ua->pint32_val == 0) {
731             bsendmsg(ua, _("Priority must be a positive integer.\n"));
732          } else {
733             jcr->JobPriority = ua->pint32_val;
734          }
735          goto try_again;
736       case 7:
737          /* Pool or Bootstrap depending on JobType */
738          if (jcr->JobType == JT_BACKUP ||
739              jcr->JobType == JT_VERIFY) {      /* Pool */
740             pool = select_pool_resource(ua);
741             if (pool) {
742                jcr->pool = pool;
743                goto try_again;
744             }
745             break;
746          }
747
748          /* Bootstrap */
749          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
750             break;
751          }
752          if (jcr->RestoreBootstrap) {
753             free(jcr->RestoreBootstrap);
754             jcr->RestoreBootstrap = NULL;
755          }
756          if (ua->cmd[0] != 0) {
757             jcr->RestoreBootstrap = bstrdup(ua->cmd);
758             fd = fopen(jcr->RestoreBootstrap, "r");
759             if (!fd) {
760                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
761                   jcr->RestoreBootstrap, strerror(errno));
762                free(jcr->RestoreBootstrap);
763                jcr->RestoreBootstrap = NULL;
764             } else {
765                fclose(fd);
766             }
767          }
768          goto try_again;
769       case 8:
770          /* Verify Job */
771          if (jcr->JobType == JT_VERIFY) {
772             verify_job = select_job_resource(ua);
773             if (verify_job) {
774               jcr->verify_job = verify_job;
775             }
776             goto try_again;
777          }
778          /* Where */
779          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
780             break;
781          }
782          if (jcr->where) {
783             free(jcr->where);
784             jcr->where = NULL;
785          }
786          if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
787             ua->cmd[0] = 0;
788          }
789          jcr->where = bstrdup(ua->cmd);
790          goto try_again;
791       case 9:
792          /* Replace */
793          start_prompt(ua, _("Replace:\n"));
794          for (i=0; ReplaceOptions[i].name; i++) {
795             add_prompt(ua, ReplaceOptions[i].name);
796          }
797          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
798          if (opt >=  0) {
799             jcr->replace = ReplaceOptions[opt].token;
800          }
801          goto try_again;
802       case 10:
803          /* JobId */
804          jid = NULL;                  /* force reprompt */
805          jcr->RestoreJobId = 0;
806          if (jcr->RestoreBootstrap) {
807             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
808          }
809          goto try_again;
810       default: 
811          goto try_again;
812       }
813       goto bail_out;
814    }
815
816    if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
817       JobId_t JobId;
818       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
819 start_job:
820       JobId = run_job(jcr);
821       free_jcr(jcr);                  /* release jcr */
822       if (JobId == 0) {
823          bsendmsg(ua, _("Job failed.\n"));
824       } else {
825          bsendmsg(ua, _("Job started. JobId=%u\n"), JobId);
826       }
827       return 1;
828    }
829
830 bail_out:
831    bsendmsg(ua, _("Job not run.\n"));
832    free_jcr(jcr);
833    return 0;                       /* do not run */
834 }