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