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