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