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