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