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