]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_run.c
Fix watchdog deadlog + restore soft link bug
[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-2003 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, 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, *replace;
52    char *when, *verify_job_name;
53    int Priority = 0;
54    int i, j, opt;
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 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  -- ignore for now */
228                kw_ok = true;
229                break;
230
231             default:
232                break;
233             }
234          } /* end strcase compare */
235       } /* end keyword loop */
236       /*
237        * End of keyword for loop -- if not found, we got a bogus keyword
238        */
239       if (!kw_ok) {
240          Dmsg1(200, "%s not found\n", ua->argk[i]);
241          /*
242           * Special case for Job Name, it can be the first
243           * keyword that has no value.
244           */
245          if (!job_name && !ua->argv[i]) {
246             job_name = ua->argk[i];   /* use keyword as job name */
247             Dmsg1(200, "Set jobname=%s\n", job_name);
248          } else {
249             bsendmsg(ua, _("Invalid keyword: %s\n"), ua->argk[i]);
250             return 1;
251          }
252       }
253    } /* end argc loop */
254              
255    Dmsg0(200, "Done scan.\n");
256
257    if (job_name) {
258       /* Find Job */
259       job = (JOB *)GetResWithName(R_JOB, job_name);
260       if (!job) {
261          if (*job_name != 0) {
262             bsendmsg(ua, _("Job \"%s\" not found\n"), job_name);
263          }
264          job = select_job_resource(ua);
265       } else {
266          Dmsg1(200, "Found job=%s\n", job_name);
267       }
268    } else {
269       bsendmsg(ua, _("A job name must be specified.\n"));
270       job = select_job_resource(ua);
271    }
272    if (!job) {
273       return 1;
274    }
275
276    if (store_name) {
277       store = (STORE *)GetResWithName(R_STORAGE, store_name);
278       if (!store) {
279          if (*store_name != 0) {
280             bsendmsg(ua, _("Storage \"%s\" not found.\n"), store_name);
281          }
282          store = select_storage_resource(ua);
283       }
284    } else {
285       store = job->storage;           /* use default */
286    }
287    if (!store) {
288       return 1;
289    }
290
291
292    if (pool_name) {
293       pool = (POOL *)GetResWithName(R_POOL, pool_name);
294       if (!pool) {
295          if (*pool_name != 0) {
296             bsendmsg(ua, _("Pool \"%s\" not found.\n"), pool_name);
297          }
298          pool = select_pool_resource(ua);
299       }
300    } else {
301       pool = job->pool;             /* use default */
302    }
303    if (!pool) {
304       return 1;
305    }
306
307    if (client_name) {
308       client = (CLIENT *)GetResWithName(R_CLIENT, client_name);
309       if (!client) {
310          if (*client_name != 0) {
311             bsendmsg(ua, _("Client \"%s\" not found.\n"), client_name);
312          }
313          client = select_client_resource(ua);
314       }
315    } else {
316       client = job->client;           /* use default */
317    }
318    if (!client) {
319       return 1;
320    }
321
322    if (fileset_name) {
323       fileset = (FILESET *)GetResWithName(R_FILESET, fileset_name);
324       if (!fileset) {
325          bsendmsg(ua, _("FileSet \"%s\" not found.\n"), fileset_name);
326          fileset = select_fileset_resource(ua);
327       }
328    } else {
329       fileset = job->fileset;           /* use default */
330    }
331    if (!fileset) {
332       return 1;
333    }
334
335    if (verify_job_name) {
336       verify_job = (JOB *)GetResWithName(R_JOB, verify_job_name);
337       if (!verify_job) {
338          bsendmsg(ua, _("Verify Job \"%s\" not found.\n"), verify_job_name);
339          verify_job = select_job_resource(ua);
340       }
341    } else {
342       verify_job = job->verify_job;
343    }
344
345    /*
346     * Create JCR to run job.  NOTE!!! after this point, free_jcr()
347     *  before returning.
348     */
349    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
350    set_jcr_defaults(jcr, job);
351
352    jcr->store = store;
353    jcr->client = client;
354    jcr->fileset = fileset;
355    jcr->pool = pool;
356    if (where) {
357       if (jcr->where) {
358          free(jcr->where);
359       }
360       jcr->where = bstrdup(where);
361    }
362
363    if (when) {
364       jcr->sched_time = str_to_utime(when);
365       if (jcr->sched_time == 0) {
366          bsendmsg(ua, _("Invalid time, using current time.\n"));
367          jcr->sched_time = time(NULL);
368       }
369    }
370          
371    if (bootstrap) {
372       if (jcr->RestoreBootstrap) {
373          free(jcr->RestoreBootstrap);
374       }
375       jcr->RestoreBootstrap = bstrdup(bootstrap);
376    }
377
378    if (replace) {
379       jcr->replace = 0;
380       for (i=0; ReplaceOptions[i].name; i++) {
381          if (strcasecmp(replace, ReplaceOptions[i].name) == 0) {
382             jcr->replace = ReplaceOptions[i].token;
383          }
384       }
385       if (!jcr->replace) {
386          bsendmsg(ua, _("Invalid replace option: %s\n"), replace);
387          goto bail_out;
388       }
389    } else if (job->replace) {
390       jcr->replace = job->replace;
391    } else {
392       jcr->replace = REPLACE_ALWAYS;
393    }
394
395    if (Priority) {
396       jcr->JobPriority = Priority;
397    }
398
399 try_again:
400    replace = ReplaceOptions[0].name;
401    for (i=0; ReplaceOptions[i].name; i++) {
402       if (ReplaceOptions[i].token == jcr->replace) {
403          replace = ReplaceOptions[i].name;
404       }
405    }
406    if (level_name) {
407       /* Look up level name and pull code */
408       bool found = false;
409       for (i=0; joblevels[i].level_name; i++) {
410          if (strcasecmp(level_name, _(joblevels[i].level_name)) == 0) {
411             jcr->JobLevel = joblevels[i].level;
412             found = true;
413             break;
414          }
415       }
416       if (!found) { 
417          bsendmsg(ua, _("Level %s not valid.\n"), level_name);
418          goto bail_out;
419       }
420    }
421    level_name = NULL;
422    if (jid) {
423       jcr->RestoreJobId = atoi(jid);
424    }
425
426    /* Run without prompting? */
427    if (find_arg(ua, _("yes")) > 0) {
428       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
429       run_job(jcr);
430       free_jcr(jcr);                  /* release jcr */
431       bsendmsg(ua, _("Run command submitted.\n"));
432       return 1;
433    }
434
435    /*  
436     * Prompt User to see if all run job parameters are correct, and
437     *   allow him to modify them.
438     */
439    Dmsg1(20, "JobType=%c\n", jcr->JobType);
440    switch (jcr->JobType) {
441       char ec1[30];
442       char dt[MAX_TIME_LENGTH];
443    case JT_ADMIN:
444          bsendmsg(ua, _("Run %s job\n\
445 JobName:  %s\n\
446 FileSet:  %s\n\
447 Client:   %s\n\
448 Storage:  %s\n\
449 When:     %s\n\
450 Priority: %d\n"),
451                  _("Admin"),
452                  job->hdr.name,
453                  jcr->fileset->hdr.name,
454                  NPRT(jcr->client->hdr.name),
455                  NPRT(jcr->store->hdr.name), 
456                  bstrutime(dt, sizeof(dt), jcr->sched_time), 
457                  jcr->JobPriority);
458       jcr->JobLevel = L_FULL;
459       break;
460    case JT_BACKUP:
461    case JT_VERIFY:
462       if (jcr->JobType == JT_BACKUP) {
463          bsendmsg(ua, _("Run %s job\n\
464 JobName:  %s\n\
465 FileSet:  %s\n\
466 Level:    %s\n\
467 Client:   %s\n\
468 Storage:  %s\n\
469 Pool:     %s\n\
470 When:     %s\n\
471 Priority: %d\n"),
472                  _("Backup"),
473                  job->hdr.name,
474                  jcr->fileset->hdr.name,
475                  level_to_str(jcr->JobLevel),
476                  jcr->client->hdr.name,
477                  jcr->store->hdr.name,
478                  NPRT(jcr->pool->hdr.name), 
479                  bstrutime(dt, sizeof(dt), jcr->sched_time),
480                  jcr->JobPriority);
481       } else {  /* JT_VERIFY */
482          char *Name;
483          if (jcr->job->verify_job) {
484             Name = jcr->job->verify_job->hdr.name;
485          } else {
486             Name = "";
487          }
488          bsendmsg(ua, _("Run %s job\n\
489 JobName:     %s\n\
490 FileSet:     %s\n\
491 Level:       %s\n\
492 Client:      %s\n\
493 Storage:     %s\n\
494 Pool:        %s\n\
495 Verify Job:  %s\n\
496 When:        %s\n\
497 Priority:    %d\n"),
498               _("Verify"),
499               job->hdr.name,
500               jcr->fileset->hdr.name,
501               level_to_str(jcr->JobLevel),
502               jcr->client->hdr.name,
503               jcr->store->hdr.name,
504               NPRT(jcr->pool->hdr.name), 
505               Name,            
506               bstrutime(dt, sizeof(dt), jcr->sched_time),
507               jcr->JobPriority);
508       }
509       break;
510    case JT_RESTORE:
511       if (jcr->RestoreJobId == 0 && !jcr->RestoreBootstrap) {
512          if (jid) {
513             jcr->RestoreJobId = atoi(jid);
514          } else {
515             if (!get_pint(ua, _("Please enter a JobId for restore: "))) {
516                goto bail_out;
517             }  
518             jcr->RestoreJobId = ua->pint32_val;
519          }
520       }
521       jcr->JobLevel = L_FULL;      /* default level */
522       Dmsg1(20, "JobId to restore=%d\n", jcr->RestoreJobId);
523       if (jcr->RestoreJobId == 0) {
524          bsendmsg(ua, _("Run Restore job\n\
525 JobName:    %s\n\
526 Bootstrap:  %s\n\
527 Where:      %s\n\
528 Replace:    %s\n\
529 FileSet:    %s\n\
530 Client:     %s\n\
531 Storage:    %s\n\
532 When:       %s\n\
533 Priority:   %d\n"),
534               job->hdr.name,
535               NPRT(jcr->RestoreBootstrap),
536               jcr->where?jcr->where:NPRT(job->RestoreWhere),
537               replace,
538               jcr->fileset->hdr.name,
539               jcr->client->hdr.name,
540               jcr->store->hdr.name, 
541               bstrutime(dt, sizeof(dt), jcr->sched_time),
542               jcr->JobPriority);
543       } else {
544          bsendmsg(ua, _("Run Restore job\n\
545 JobName:    %s\n\
546 Bootstrap:  %s\n\
547 Where:      %s\n\
548 Replace:    %s\n\
549 FileSet:    %s\n\
550 Client:     %s\n\
551 Storage:    %s\n\
552 JobId:      %s\n\
553 When:       %s\n\
554 Priority:   %d\n"),
555               job->hdr.name,
556               NPRT(jcr->RestoreBootstrap),
557               jcr->where?jcr->where:NPRT(job->RestoreWhere),
558               replace,
559               jcr->fileset->hdr.name,
560               jcr->client->hdr.name,
561               jcr->store->hdr.name, 
562               jcr->RestoreJobId==0?"*None*":edit_uint64(jcr->RestoreJobId, ec1), 
563               bstrutime(dt, sizeof(dt), jcr->sched_time),
564               jcr->JobPriority);
565       }
566       break;
567    default:
568       bsendmsg(ua, _("Unknown Job Type=%d\n"), jcr->JobType);
569       goto bail_out;
570    }
571
572
573    if (!get_cmd(ua, _("OK to run? (yes/mod/no): "))) {
574       goto bail_out;
575    }
576    /*
577     * At user request modify parameters of job to be run.
578     */
579    if (ua->cmd[0] == 0) {
580       goto bail_out;
581    }
582    if (strncasecmp(ua->cmd, _("mod"), strlen(ua->cmd)) == 0) {
583       FILE *fd;
584
585       start_prompt(ua, _("Parameters to modify:\n"));
586       add_prompt(ua, _("Level"));            /* 0 */
587       add_prompt(ua, _("Storage"));          /* 1 */
588       add_prompt(ua, _("Job"));              /* 2 */
589       add_prompt(ua, _("FileSet"));          /* 3 */
590       add_prompt(ua, _("Client"));           /* 4 */
591       add_prompt(ua, _("When"));             /* 5 */
592       add_prompt(ua, _("Priority"));         /* 6 */
593       if (jcr->JobType == JT_BACKUP ||
594           jcr->JobType == JT_VERIFY) {
595          add_prompt(ua, _("Pool"));          /* 7 */
596          if (jcr->JobType == JT_VERIFY) {
597             add_prompt(ua, _("Verify Job"));  /* 8 */
598          }
599       } else if (jcr->JobType == JT_RESTORE) {
600          add_prompt(ua, _("Bootstrap"));     /* 7 */
601          add_prompt(ua, _("Where"));         /* 8 */
602          add_prompt(ua, _("Replace"));       /* 9 */
603          add_prompt(ua, _("JobId"));         /* 10 */
604       }
605       switch (do_prompt(ua, "", _("Select parameter to modify"), NULL, 0)) {
606       case 0:
607          /* Level */
608          if (jcr->JobType == JT_BACKUP) {
609             start_prompt(ua, _("Levels:\n"));
610             add_prompt(ua, _("Base"));
611             add_prompt(ua, _("Full"));
612             add_prompt(ua, _("Incremental"));
613             add_prompt(ua, _("Differential"));
614             add_prompt(ua, _("Since"));
615             switch (do_prompt(ua, "", _("Select level"), NULL, 0)) {
616             case 0:
617                jcr->JobLevel = L_BASE;
618                break;
619             case 1:
620                jcr->JobLevel = L_FULL;
621                break;
622             case 2:
623                jcr->JobLevel = L_INCREMENTAL;
624                break;
625             case 3:
626                jcr->JobLevel = L_DIFFERENTIAL;
627                break;
628             case 4:
629                jcr->JobLevel = L_SINCE;
630                break;
631             default:
632                break;
633             }
634             goto try_again;
635          } else if (jcr->JobType == JT_VERIFY) {
636             start_prompt(ua, _("Levels:\n"));
637             add_prompt(ua, _("Initialize Catalog"));
638             add_prompt(ua, _("Verify Catalog"));
639             add_prompt(ua, _("Verify Volume to Catalog"));
640             add_prompt(ua, _("Verify Disk to Catalog"));
641             add_prompt(ua, _("Verify Volume Data (not yet implemented)"));
642             switch (do_prompt(ua, "",  _("Select level"), NULL, 0)) {
643             case 0:
644                jcr->JobLevel = L_VERIFY_INIT;
645                break;
646             case 1:
647                jcr->JobLevel = L_VERIFY_CATALOG;
648                break;
649             case 2:
650                jcr->JobLevel = L_VERIFY_VOLUME_TO_CATALOG;
651                break;
652             case 3:
653                jcr->JobLevel = L_VERIFY_DISK_TO_CATALOG;
654                break;
655             case 4:
656                jcr->JobLevel = L_VERIFY_DATA;
657                break;
658             default:
659                break;
660             }
661             goto try_again;
662          } else {
663             bsendmsg(ua, _("Level not appropriate for this Job. Cannot be changed.\n"));
664          }
665          goto try_again;
666       case 1:
667          /* Storage */
668          store = select_storage_resource(ua);
669          if (store) {
670             jcr->store = store;
671             goto try_again;
672          }
673          break;
674       case 2:
675          /* Job */
676          job = select_job_resource(ua);
677          if (job) {
678             jcr->job = job;
679             set_jcr_defaults(jcr, job);
680             goto try_again;
681          }
682          break;
683       case 3:
684          /* FileSet */
685          fileset = select_fileset_resource(ua);
686          if (fileset) {
687             jcr->fileset = fileset;
688             goto try_again;
689          }      
690          break;
691       case 4:
692          /* Client */
693          client = select_client_resource(ua);
694          if (client) {
695             jcr->client = client;
696             goto try_again;
697          }
698          break;
699       case 5:
700          /* When */
701          if (!get_cmd(ua, _("Please enter desired start time as YYYY-MM-DD HH:MM:SS (return for now): "))) {
702             break;
703          }
704          if (ua->cmd[0] == 0) {
705             jcr->sched_time = time(NULL);
706          } else {
707             jcr->sched_time = str_to_utime(ua->cmd);
708             if (jcr->sched_time == 0) {
709                bsendmsg(ua, _("Invalid time, using current time.\n"));
710                jcr->sched_time = time(NULL);
711             }
712          }
713          goto try_again;
714       case 6:
715          /* Priority */
716          if (!get_pint(ua, _("Enter new Priority: "))) {
717             break;
718          }
719          if (ua->pint32_val == 0) {
720             bsendmsg(ua, _("Priority must be a positive integer.\n"));
721          } else {
722             jcr->JobPriority = ua->pint32_val;
723          }
724          goto try_again;
725       case 7:
726          /* Pool or Bootstrap depending on JobType */
727          if (jcr->JobType == JT_BACKUP ||
728              jcr->JobType == JT_VERIFY) {      /* Pool */
729             pool = select_pool_resource(ua);
730             if (pool) {
731                jcr->pool = pool;
732                goto try_again;
733             }
734             break;
735          }
736
737          /* Bootstrap */
738          if (!get_cmd(ua, _("Please enter the Bootstrap file name: "))) {
739             break;
740          }
741          if (jcr->RestoreBootstrap) {
742             free(jcr->RestoreBootstrap);
743             jcr->RestoreBootstrap = NULL;
744          }
745          if (ua->cmd[0] != 0) {
746             jcr->RestoreBootstrap = bstrdup(ua->cmd);
747             fd = fopen(jcr->RestoreBootstrap, "r");
748             if (!fd) {
749                bsendmsg(ua, _("Warning cannot open %s: ERR=%s\n"),
750                   jcr->RestoreBootstrap, strerror(errno));
751                free(jcr->RestoreBootstrap);
752                jcr->RestoreBootstrap = NULL;
753             } else {
754                fclose(fd);
755             }
756          }
757          goto try_again;
758       case 8:
759          /* Verify Job */
760          if (jcr->JobType == JT_VERIFY) {
761             JOB *job = select_job_resource(ua);
762             if (job) {
763                jcr->job->verify_job = job;
764             } else {
765                jcr->job->verify_job = NULL;
766             }
767             goto try_again;
768          }
769          /* Where */
770          if (!get_cmd(ua, _("Please enter path prefix for restore (/ for none): "))) {
771             break;
772          }
773          if (jcr->where) {
774             free(jcr->where);
775             jcr->where = NULL;
776          }
777          if (ua->cmd[0] == '/' && ua->cmd[1] == 0) {
778             ua->cmd[0] = 0;
779          }
780          jcr->where = bstrdup(ua->cmd);
781          goto try_again;
782       case 9:
783          /* Replace */
784          start_prompt(ua, _("Replace:\n"));
785          for (i=0; ReplaceOptions[i].name; i++) {
786             add_prompt(ua, ReplaceOptions[i].name);
787          }
788          opt = do_prompt(ua, "", _("Select replace option"), NULL, 0);
789          if (opt >=  0) {
790             jcr->replace = ReplaceOptions[opt].token;
791          }
792          goto try_again;
793       case 10:
794          /* JobId */
795          jid = NULL;                  /* force reprompt */
796          jcr->RestoreJobId = 0;
797          if (jcr->RestoreBootstrap) {
798             bsendmsg(ua, _("You must set the bootstrap file to NULL to be able to specify a JobId.\n"));
799          }
800          goto try_again;
801       default: 
802          goto try_again;
803       }
804       goto bail_out;
805    }
806
807    if (strncasecmp(ua->cmd, _("yes"), strlen(ua->cmd)) == 0) {
808       Dmsg1(200, "Calling run_job job=%x\n", jcr->job);
809       run_job(jcr);
810       free_jcr(jcr);                  /* release jcr */
811       bsendmsg(ua, _("Run command submitted.\n"));
812       return 1;
813    }
814
815 bail_out:
816    bsendmsg(ua, _("Job not run.\n"));
817    free_jcr(jcr);
818    return 0;                       /* do not run */
819 }