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