]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/job.c
Apply Bastian Friedrich's edit codes patch for the bpipe-fd plugin + his edit pool...
[bacula/bacula] / bacula / src / dird / job.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2000-2008 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version two of the GNU General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of John Walker.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *   Bacula Director Job processing routines
31  *
32  *     Kern Sibbald, October MM
33  *
34  *    Version $Id$
35  */
36
37 #include "bacula.h"
38 #include "dird.h"
39
40 /* Forward referenced subroutines */
41 static void *job_thread(void *arg);
42 static void job_monitor_watchdog(watchdog_t *self);
43 static void job_monitor_destructor(watchdog_t *self);
44 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr);
45 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr);
46
47 /* Imported subroutines */
48 extern void term_scheduler();
49 extern void term_ua_server();
50
51 /* Imported variables */
52
53 jobq_t job_queue;
54
55 void init_job_server(int max_workers)
56 {
57    int stat;
58    watchdog_t *wd;
59
60    if ((stat = jobq_init(&job_queue, max_workers, job_thread)) != 0) {
61       berrno be;
62       Emsg1(M_ABORT, 0, _("Could not init job queue: ERR=%s\n"), be.bstrerror(stat));
63    }
64    wd = new_watchdog();
65    wd->callback = job_monitor_watchdog;
66    wd->destructor = job_monitor_destructor;
67    wd->one_shot = false;
68    wd->interval = 60;
69    wd->data = new_control_jcr("*JobMonitor*", JT_SYSTEM);
70    register_watchdog(wd);
71 }
72
73 void term_job_server()
74 {
75    jobq_destroy(&job_queue);          /* ignore any errors */
76 }
77
78 /*
79  * Run a job -- typically called by the scheduler, but may also
80  *              be called by the UA (Console program).
81  *
82  *  Returns: 0 on failure
83  *           JobId on success
84  *
85  */
86 JobId_t run_job(JCR *jcr)
87 {
88    int stat;
89    if (setup_job(jcr)) {
90       Dmsg0(200, "Add jrc to work queue\n");
91       /* Queue the job to be run */
92       if ((stat = jobq_add(&job_queue, jcr)) != 0) {
93          berrno be;
94          Jmsg(jcr, M_FATAL, 0, _("Could not add job queue: ERR=%s\n"), be.bstrerror(stat));
95          return 0;
96       }
97       return jcr->JobId;
98    }
99    return 0;
100 }            
101
102 bool setup_job(JCR *jcr) 
103 {
104    int errstat;
105
106    jcr->lock();
107    sm_check(__FILE__, __LINE__, true);
108    init_msg(jcr, jcr->messages);
109
110    /* Initialize termination condition variable */
111    if ((errstat = pthread_cond_init(&jcr->term_wait, NULL)) != 0) {
112       berrno be;
113       Jmsg1(jcr, M_FATAL, 0, _("Unable to init job cond variable: ERR=%s\n"), be.bstrerror(errstat));
114       goto bail_out;
115    }
116    jcr->term_wait_inited = true;
117
118    create_unique_job_name(jcr, jcr->job->name());
119    set_jcr_job_status(jcr, JS_Created);
120    jcr->unlock();
121
122    /*
123     * Open database
124     */
125    Dmsg0(100, "Open database\n");
126    jcr->db=db_init(jcr, jcr->catalog->db_driver, jcr->catalog->db_name, 
127                    jcr->catalog->db_user,
128                    jcr->catalog->db_password, jcr->catalog->db_address,
129                    jcr->catalog->db_port, jcr->catalog->db_socket,
130                    jcr->catalog->mult_db_connections);
131    if (!jcr->db || !db_open_database(jcr, jcr->db)) {
132       Jmsg(jcr, M_FATAL, 0, _("Could not open database \"%s\".\n"),
133                  jcr->catalog->db_name);
134       if (jcr->db) {
135          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
136          db_close_database(jcr, jcr->db);
137       }
138       goto bail_out;
139    }
140    Dmsg0(150, "DB opened\n");
141
142    if (!jcr->fname) {
143       jcr->fname = get_pool_memory(PM_FNAME);
144    }
145    if (!jcr->pool_source) {
146       jcr->pool_source = get_pool_memory(PM_MESSAGE);
147       pm_strcpy(jcr->pool_source, _("unknown source"));
148    }
149    Dmsg2(500, "pool=%s (From %s)\n", jcr->pool->name(), jcr->pool_source);
150    if (jcr->JobType == JT_MIGRATE || jcr->JobType == JT_COPY) {
151       if (!jcr->rpool_source) {
152          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
153          pm_strcpy(jcr->rpool_source, _("unknown source"));
154       }
155    }
156
157    /*
158     * Create Job record
159     */
160    init_jcr_job_record(jcr);
161    if (!get_or_create_client_record(jcr)) {
162       goto bail_out;
163    }
164
165    if (!db_create_job_record(jcr, jcr->db, &jcr->jr)) {
166       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
167       goto bail_out;
168    }
169    jcr->JobId = jcr->jr.JobId;
170    Dmsg4(100, "Created job record JobId=%d Name=%s Type=%c Level=%c\n",
171        jcr->JobId, jcr->Job, jcr->jr.JobType, jcr->jr.JobLevel);
172
173    generate_daemon_event(jcr, "JobStart");
174
175    if (job_canceled(jcr)) {
176       goto bail_out;
177    }
178
179    /*
180     * Now, do pre-run stuff, like setting job level (Inc/diff, ...)
181     *  this allows us to setup a proper job start record for restarting
182     *  in case of later errors.
183     */
184    switch (jcr->JobType) {
185    case JT_BACKUP:
186       if (!do_backup_init(jcr)) {
187          backup_cleanup(jcr, JS_ErrorTerminated);
188       }
189       break;
190    case JT_VERIFY:
191       if (!do_verify_init(jcr)) {
192          verify_cleanup(jcr, JS_ErrorTerminated);
193       }
194       break;
195    case JT_RESTORE:
196       if (!do_restore_init(jcr)) {
197          restore_cleanup(jcr, JS_ErrorTerminated);
198       }
199       break;
200    case JT_ADMIN:
201       if (!do_admin_init(jcr)) {
202          admin_cleanup(jcr, JS_ErrorTerminated);
203       }
204       break;
205    case JT_COPY:
206    case JT_MIGRATE:
207       if (!do_migration_init(jcr)) { 
208          migration_cleanup(jcr, JS_ErrorTerminated);
209       }
210       break;
211    default:
212       Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
213       set_jcr_job_status(jcr, JS_ErrorTerminated);
214       break;
215    }
216
217    generate_job_event(jcr, "JobInit");
218    Dsm_check(1);
219    return true;
220
221 bail_out:
222    return false;
223 }
224
225 void update_job_end(JCR *jcr, int TermCode)
226 {
227    dequeue_messages(jcr);             /* display any queued messages */
228    set_jcr_job_status(jcr, TermCode);
229    update_job_end_record(jcr);
230 }
231
232 /*
233  * This is the engine called by jobq.c:jobq_add() when we were pulled
234  *  from the work queue.
235  *  At this point, we are running in our own thread and all
236  *    necessary resources are allocated -- see jobq.c
237  */
238 static void *job_thread(void *arg)
239 {
240    JCR *jcr = (JCR *)arg;
241
242    pthread_detach(pthread_self());
243    Dsm_check(1);
244
245    Dmsg0(200, "=====Start Job=========\n");
246    set_jcr_job_status(jcr, JS_Running);   /* this will be set only if no error */
247    jcr->start_time = time(NULL);      /* set the real start time */
248    jcr->jr.StartTime = jcr->start_time;
249
250    if (jcr->job->MaxStartDelay != 0 && jcr->job->MaxStartDelay <
251        (utime_t)(jcr->start_time - jcr->sched_time)) {
252       set_jcr_job_status(jcr, JS_Canceled);
253       Jmsg(jcr, M_FATAL, 0, _("Job canceled because max start delay time exceeded.\n"));
254    }
255
256    /* TODO : check if it is used somewhere */
257    if (jcr->job->RunScripts == NULL) {
258       Dmsg0(200, "Warning, job->RunScripts is empty\n");
259       jcr->job->RunScripts = New(alist(10, not_owned_by_alist));
260    }
261
262    if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
263       Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
264    }
265
266    /* Run any script BeforeJob on dird */
267    run_scripts(jcr, jcr->job->RunScripts, "BeforeJob");
268
269    if (job_canceled(jcr)) {
270       update_job_end(jcr, jcr->JobStatus);
271
272    } else {
273       /*
274        * We re-update the job start record so that the start
275        *  time is set after the run before job.  This avoids
276        *  that any files created by the run before job will
277        *  be saved twice.  They will be backed up in the current
278        *  job, but not in the next one unless they are changed.
279        *  Without this, they will be backed up in this job and
280        *  in the next job run because in that case, their date
281        *   is after the start of this run.
282        */
283       jcr->start_time = time(NULL);
284       jcr->jr.StartTime = jcr->start_time;
285       if (!db_update_job_start_record(jcr, jcr->db, &jcr->jr)) {
286          Jmsg(jcr, M_FATAL, 0, "%s", db_strerror(jcr->db));
287       }
288       generate_job_event(jcr, "JobRun");
289
290       switch (jcr->JobType) {
291       case JT_BACKUP:
292          if (do_backup(jcr)) {
293             do_autoprune(jcr);
294          } else {
295             backup_cleanup(jcr, JS_ErrorTerminated);
296          }
297          break;
298       case JT_VERIFY:
299          if (do_verify(jcr)) {
300             do_autoprune(jcr);
301          } else {
302             verify_cleanup(jcr, JS_ErrorTerminated);
303          }
304          break;
305       case JT_RESTORE:
306          if (do_restore(jcr)) {
307             do_autoprune(jcr);
308          } else {
309             restore_cleanup(jcr, JS_ErrorTerminated);
310          }
311          break;
312       case JT_ADMIN:
313          if (do_admin(jcr)) {
314             do_autoprune(jcr);
315          } else {
316             admin_cleanup(jcr, JS_ErrorTerminated);
317          }
318          break;
319       case JT_COPY:
320       case JT_MIGRATE:
321          if (do_migration(jcr)) {
322             do_autoprune(jcr);
323          } else {
324             migration_cleanup(jcr, JS_ErrorTerminated);
325          }
326          break;
327       default:
328          Pmsg1(0, _("Unimplemented job type: %d\n"), jcr->JobType);
329          break;
330       }
331    }
332
333    run_scripts(jcr, jcr->job->RunScripts, "AfterJob");
334
335    /* Send off any queued messages */
336    if (jcr->msg_queue && jcr->msg_queue->size() > 0) {
337       dequeue_messages(jcr);
338    }
339
340    generate_daemon_event(jcr, "JobEnd");
341    Dmsg1(50, "======== End Job stat=%c ==========\n", jcr->JobStatus);
342    sm_check(__FILE__, __LINE__, true);
343    return NULL;
344 }
345
346
347 /*
348  * Cancel a job -- typically called by the UA (Console program), but may also
349  *              be called by the job watchdog.
350  *
351  *  Returns: true  if cancel appears to be successful
352  *           false on failure. Message sent to ua->jcr.
353  */
354 bool cancel_job(UAContext *ua, JCR *jcr)
355 {
356    BSOCK *sd, *fd;
357    char ed1[50];
358
359    set_jcr_job_status(jcr, JS_Canceled);
360
361    switch (jcr->JobStatus) {
362    case JS_Created:
363    case JS_WaitJobRes:
364    case JS_WaitClientRes:
365    case JS_WaitStoreRes:
366    case JS_WaitPriority:
367    case JS_WaitMaxJobs:
368    case JS_WaitStartTime:
369       ua->info_msg(_("JobId %s, Job %s marked to be canceled.\n"),
370               edit_uint64(jcr->JobId, ed1), jcr->Job);
371       jobq_remove(&job_queue, jcr); /* attempt to remove it from queue */
372       return true;
373
374    default:
375       /* Cancel File daemon */
376       if (jcr->file_bsock) {
377          ua->jcr->client = jcr->client;
378          if (!connect_to_file_daemon(ua->jcr, 10, FDConnectTimeout, 1)) {
379             ua->error_msg(_("Failed to connect to File daemon.\n"));
380             return 0;
381          }
382          Dmsg0(200, "Connected to file daemon\n");
383          fd = ua->jcr->file_bsock;
384          bnet_fsend(fd, "cancel Job=%s\n", jcr->Job);
385          while (bnet_recv(fd) >= 0) {
386             ua->send_msg("%s", fd->msg);
387          }
388          bnet_sig(fd, BNET_TERMINATE);
389          bnet_close(fd);
390          ua->jcr->file_bsock = NULL;
391       }
392
393       /* Cancel Storage daemon */
394       if (jcr->store_bsock) {
395          if (!ua->jcr->wstorage) {
396             if (jcr->rstorage) {
397                copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
398             } else {
399                copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
400             }
401          } else {
402             USTORE store;
403             if (jcr->rstorage) {
404                store.store = jcr->rstore;
405             } else {
406                store.store = jcr->wstore;
407             }
408             set_wstorage(ua->jcr, &store);
409          }
410
411          if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
412             ua->error_msg(_("Failed to connect to Storage daemon.\n"));
413             return false;
414          }
415          Dmsg0(200, "Connected to storage daemon\n");
416          sd = ua->jcr->store_bsock;
417          sd->fsend("cancel Job=%s\n", jcr->Job);
418          while (sd->recv() >= 0) {
419             ua->send_msg("%s", sd->msg);
420          }
421          sd->signal(BNET_TERMINATE);
422          sd->close();
423          ua->jcr->store_bsock = NULL;
424       }
425    }
426
427    return true;
428 }
429
430 void cancel_storage_daemon_job(JCR *jcr)
431 {
432    UAContext *ua = new_ua_context(jcr);
433    JCR *control_jcr = new_control_jcr("*JobCancel*", JT_SYSTEM);
434    BSOCK *sd;
435
436    ua->jcr = control_jcr;
437    if (jcr->store_bsock) {
438       if (!ua->jcr->wstorage) {
439          if (jcr->rstorage) {
440             copy_wstorage(ua->jcr, jcr->rstorage, _("Job resource")); 
441          } else {
442             copy_wstorage(ua->jcr, jcr->wstorage, _("Job resource")); 
443          }
444       } else {
445          USTORE store;
446          if (jcr->rstorage) {
447             store.store = jcr->rstore;
448          } else {
449             store.store = jcr->wstore;
450          }
451          set_wstorage(ua->jcr, &store);
452       }
453
454       if (!connect_to_storage_daemon(ua->jcr, 10, SDConnectTimeout, 1)) {
455          goto bail_out;
456       }
457       Dmsg0(200, "Connected to storage daemon\n");
458       sd = ua->jcr->store_bsock;
459       sd->fsend("cancel Job=%s\n", jcr->Job);
460       while (sd->recv() >= 0) {
461       }
462       sd->signal(BNET_TERMINATE);
463       sd->close();
464       ua->jcr->store_bsock = NULL;
465    }
466 bail_out:
467    free_jcr(control_jcr);
468    free_ua_context(ua);
469 }
470
471 static void job_monitor_destructor(watchdog_t *self)
472 {
473    JCR *control_jcr = (JCR *)self->data;
474
475    free_jcr(control_jcr);
476 }
477
478 static void job_monitor_watchdog(watchdog_t *self)
479 {
480    JCR *control_jcr, *jcr;
481
482    control_jcr = (JCR *)self->data;
483
484    Dsm_check(1);
485    Dmsg1(800, "job_monitor_watchdog %p called\n", self);
486
487    foreach_jcr(jcr) {
488       bool cancel = false;
489
490       if (jcr->JobId == 0 || job_canceled(jcr)) {
491          Dmsg2(800, "Skipping JCR=%p Job=%s\n", jcr, jcr->Job);
492          continue;
493       }
494
495       /* check MaxWaitTime */
496       if (job_check_maxwaittime(control_jcr, jcr)) {
497          set_jcr_job_status(jcr, JS_Canceled);
498          Jmsg(jcr, M_FATAL, 0, _("Max wait time exceeded. Job canceled.\n"));
499          cancel = true;
500       /* check MaxRunTime */
501       } else if (job_check_maxruntime(control_jcr, jcr)) {
502          set_jcr_job_status(jcr, JS_Canceled);
503          Jmsg(jcr, M_FATAL, 0, _("Max run time exceeded. Job canceled.\n"));
504          cancel = true;
505       }
506
507       if (cancel) {
508          Dmsg3(800, "Cancelling JCR %p jobid %d (%s)\n", jcr, jcr->JobId, jcr->Job);
509          UAContext *ua = new_ua_context(jcr);
510          ua->jcr = control_jcr;
511          cancel_job(ua, jcr);
512          free_ua_context(ua);
513          Dmsg2(800, "Have cancelled JCR %p Job=%d\n", jcr, jcr->JobId);
514       }
515
516    }
517    /* Keep reference counts correct */
518    endeach_jcr(jcr);
519 }
520
521 /*
522  * Check if the maxwaittime has expired and it is possible
523  *  to cancel the job.
524  */
525 static bool job_check_maxwaittime(JCR *control_jcr, JCR *jcr)
526 {
527    bool cancel = false;
528    JOB *job = jcr->job;
529
530    if (job_canceled(jcr)) {
531       return false;                /* already canceled */
532    }
533    if (job->MaxWaitTime == 0 && job->FullMaxWaitTime == 0 &&
534        job->IncMaxWaitTime == 0 && job->DiffMaxWaitTime == 0) {
535       return false;
536    } 
537    if (jcr->JobLevel == L_FULL && job->FullMaxWaitTime != 0 &&
538          (watchdog_time - jcr->start_time) >= job->FullMaxWaitTime) {
539       cancel = true;
540    } else if (jcr->JobLevel == L_DIFFERENTIAL && job->DiffMaxWaitTime != 0 &&
541          (watchdog_time - jcr->start_time) >= job->DiffMaxWaitTime) {
542       cancel = true;
543    } else if (jcr->JobLevel == L_INCREMENTAL && job->IncMaxWaitTime != 0 &&
544          (watchdog_time - jcr->start_time) >= job->IncMaxWaitTime) {
545       cancel = true;
546    } else if (job->MaxWaitTime != 0 &&
547          (watchdog_time - jcr->start_time) >= job->MaxWaitTime) {
548       cancel = true;
549    }
550
551    return cancel;
552 }
553
554 /*
555  * Check if maxruntime has expired and if the job can be
556  *   canceled.
557  */
558 static bool job_check_maxruntime(JCR *control_jcr, JCR *jcr)
559 {
560    if (jcr->job->MaxRunTime == 0 || job_canceled(jcr) || jcr->JobStatus == JS_Created) {
561       return false;
562    }
563    if ((watchdog_time - jcr->start_time) < jcr->job->MaxRunTime) {
564       Dmsg3(200, "Job %p (%s) with MaxRunTime %d not expired\n",
565             jcr, jcr->Job, jcr->job->MaxRunTime);
566       return false;
567    }
568
569    return true;
570 }
571
572 /*
573  * Get or create a Pool record with the given name.
574  * Returns: 0 on error
575  *          poolid if OK
576  */
577 DBId_t get_or_create_pool_record(JCR *jcr, char *pool_name)
578 {
579    POOL_DBR pr;
580
581    memset(&pr, 0, sizeof(pr));
582    bstrncpy(pr.Name, pool_name, sizeof(pr.Name));
583    Dmsg1(110, "get_or_create_pool=%s\n", pool_name);
584
585    while (!db_get_pool_record(jcr, jcr->db, &pr)) { /* get by Name */
586       /* Try to create the pool */
587       if (create_pool(jcr, jcr->db, jcr->pool, POOL_OP_CREATE) < 0) {
588          Jmsg(jcr, M_FATAL, 0, _("Pool \"%s\" not in database. ERR=%s"), pr.Name,
589             db_strerror(jcr->db));
590          return 0;
591       } else {
592          Jmsg(jcr, M_INFO, 0, _("Created database record for Pool \"%s\".\n"), pr.Name);
593       }
594    }
595    return pr.PoolId;
596 }
597
598 /*
599  * Check for duplicate jobs.
600  *  Returns: true  if current job should continue
601  *           false if current job should terminate
602  */
603 bool allow_duplicate_job(JCR *jcr)
604 {
605    JOB *job = jcr->job;
606    JCR *djcr;                /* possible duplicate */
607
608    if (job->AllowDuplicateJobs) {
609       return true;
610    }
611    if (!job->AllowHigherDuplicates) {
612       foreach_jcr(djcr) {
613          if (strcmp(job->name(), djcr->job->name()) == 0) {
614             bool cancel_queued = false;
615             if (job->DuplicateJobProximity > 0) {
616                time_t now = time(NULL);
617                if ((now - djcr->start_time) > job->DuplicateJobProximity) {
618                   continue;               /* not really a duplicate */
619                }
620             }
621             /* Cancel */
622             if (!(job->CancelQueuedDuplicates || job->CancelRunningDuplicates)) {
623                /* Zap current job */
624                Jmsg(jcr, M_FATAL, 0, _("Duplicate job not allowed.\n"));
625                return false;
626             }
627             /* If CancelQueuedDuplicates is set do so only if job is queued */
628             if (job->CancelQueuedDuplicates) {
629                 switch (djcr->JobStatus) {
630                 case JS_Created:
631                 case JS_WaitJobRes:
632                 case JS_WaitClientRes:
633                 case JS_WaitStoreRes:
634                 case JS_WaitPriority:
635                 case JS_WaitMaxJobs:
636                 case JS_WaitStartTime:
637                    cancel_queued = true;
638                    break;
639                 default:
640                    break;
641                 }
642             }
643             if (cancel_queued || job->CancelRunningDuplicates) {
644                UAContext *ua = new_ua_context(djcr);
645                char ec1[50];
646                Jmsg(jcr, M_INFO, 0, _("Cancelling duplicate JobId=%s.\n"), 
647                   edit_uint64(djcr->JobId, ec1));
648                ua->jcr = djcr;
649                cancel_job(ua, djcr);
650                free_ua_context(ua);
651                Dmsg2(800, "Have cancelled JCR %p Job=%d\n", djcr, djcr->JobId);
652             }
653          }
654       }
655    }
656    return true;   
657 }
658
659 void apply_pool_overrides(JCR *jcr)
660 {
661    bool pool_override = false;
662
663    if (jcr->run_pool_override) {
664       pm_strcpy(jcr->pool_source, _("Run pool override"));
665    }
666    /*
667     * Apply any level related Pool selections
668     */
669    switch (jcr->JobLevel) {
670    case L_FULL:
671       if (jcr->full_pool) {
672          jcr->pool = jcr->full_pool;
673          pool_override = true;
674          if (jcr->run_full_pool_override) {
675             pm_strcpy(jcr->pool_source, _("Run FullPool override"));
676          } else {
677             pm_strcpy(jcr->pool_source, _("Job FullPool override"));
678          }
679       }
680       break;
681    case L_INCREMENTAL:
682       if (jcr->inc_pool) {
683          jcr->pool = jcr->inc_pool;
684          pool_override = true;
685          if (jcr->run_inc_pool_override) {
686             pm_strcpy(jcr->pool_source, _("Run IncPool override"));
687          } else {
688             pm_strcpy(jcr->pool_source, _("Job IncPool override"));
689          }
690       }
691       break;
692    case L_DIFFERENTIAL:
693       if (jcr->diff_pool) {
694          jcr->pool = jcr->diff_pool;
695          pool_override = true;
696          if (jcr->run_diff_pool_override) {
697             pm_strcpy(jcr->pool_source, _("Run DiffPool override"));
698          } else {
699             pm_strcpy(jcr->pool_source, _("Job DiffPool override"));
700          }
701       }
702       break;
703    }
704    /* Update catalog if pool overridden */
705    if (pool_override && jcr->pool->catalog) {
706       jcr->catalog = jcr->pool->catalog;
707       pm_strcpy(jcr->catalog_source, _("Pool resource"));
708    }
709 }
710
711
712 /*
713  * Get or create a Client record for this Job
714  */
715 bool get_or_create_client_record(JCR *jcr)
716 {
717    CLIENT_DBR cr;
718
719    memset(&cr, 0, sizeof(cr));
720    bstrncpy(cr.Name, jcr->client->hdr.name, sizeof(cr.Name));
721    cr.AutoPrune = jcr->client->AutoPrune;
722    cr.FileRetention = jcr->client->FileRetention;
723    cr.JobRetention = jcr->client->JobRetention;
724    if (!jcr->client_name) {
725       jcr->client_name = get_pool_memory(PM_NAME);
726    }
727    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
728    if (!db_create_client_record(jcr, jcr->db, &cr)) {
729       Jmsg(jcr, M_FATAL, 0, _("Could not create Client record. ERR=%s\n"),
730          db_strerror(jcr->db));
731       return false;
732    }
733    jcr->jr.ClientId = cr.ClientId;
734    if (cr.Uname[0]) {
735       if (!jcr->client_uname) {
736          jcr->client_uname = get_pool_memory(PM_NAME);
737       }
738       pm_strcpy(jcr->client_uname, cr.Uname);
739    }
740    Dmsg2(100, "Created Client %s record %d\n", jcr->client->hdr.name,
741       jcr->jr.ClientId);
742    return true;
743 }
744
745 bool get_or_create_fileset_record(JCR *jcr)
746 {
747    FILESET_DBR fsr;
748    /*
749     * Get or Create FileSet record
750     */
751    memset(&fsr, 0, sizeof(FILESET_DBR));
752    bstrncpy(fsr.FileSet, jcr->fileset->hdr.name, sizeof(fsr.FileSet));
753    if (jcr->fileset->have_MD5) {
754       struct MD5Context md5c;
755       unsigned char digest[MD5HashSize];
756       memcpy(&md5c, &jcr->fileset->md5c, sizeof(md5c));
757       MD5Final(digest, &md5c);
758       /*
759        * Keep the flag (last arg) set to false otherwise old FileSets will
760        * get new MD5 sums and the user will get Full backups on everything
761        */
762       bin_to_base64(fsr.MD5, sizeof(fsr.MD5), (char *)digest, MD5HashSize, false);
763       bstrncpy(jcr->fileset->MD5, fsr.MD5, sizeof(jcr->fileset->MD5));
764    } else {
765       Jmsg(jcr, M_WARNING, 0, _("FileSet MD5 digest not found.\n"));
766    }
767    if (!jcr->fileset->ignore_fs_changes ||
768        !db_get_fileset_record(jcr, jcr->db, &fsr)) {
769       if (!db_create_fileset_record(jcr, jcr->db, &fsr)) {
770          Jmsg(jcr, M_ERROR, 0, _("Could not create FileSet \"%s\" record. ERR=%s\n"),
771             fsr.FileSet, db_strerror(jcr->db));
772          return false;
773       }
774    }
775    jcr->jr.FileSetId = fsr.FileSetId;
776    bstrncpy(jcr->FSCreateTime, fsr.cCreateTime, sizeof(jcr->FSCreateTime));
777    Dmsg2(119, "Created FileSet %s record %u\n", jcr->fileset->hdr.name,
778       jcr->jr.FileSetId);
779    return true;
780 }
781
782 void init_jcr_job_record(JCR *jcr)
783 {
784    jcr->jr.SchedTime = jcr->sched_time;
785    jcr->jr.StartTime = jcr->start_time;
786    jcr->jr.EndTime = 0;               /* perhaps rescheduled, clear it */
787    jcr->jr.JobType = jcr->JobType;
788    jcr->jr.JobLevel = jcr->JobLevel;
789    jcr->jr.JobStatus = jcr->JobStatus;
790    jcr->jr.JobId = jcr->JobId;
791    bstrncpy(jcr->jr.Name, jcr->job->name(), sizeof(jcr->jr.Name));
792    bstrncpy(jcr->jr.Job, jcr->Job, sizeof(jcr->jr.Job));
793 }
794
795 /*
796  * Write status and such in DB
797  */
798 void update_job_end_record(JCR *jcr)
799 {
800    jcr->jr.EndTime = time(NULL);
801    jcr->end_time = jcr->jr.EndTime;
802    jcr->jr.JobId = jcr->JobId;
803    jcr->jr.JobStatus = jcr->JobStatus;
804    jcr->jr.JobFiles = jcr->JobFiles;
805    jcr->jr.JobBytes = jcr->JobBytes;
806    jcr->jr.VolSessionId = jcr->VolSessionId;
807    jcr->jr.VolSessionTime = jcr->VolSessionTime;
808    jcr->jr.JobErrors = jcr->Errors;
809    if (!db_update_job_end_record(jcr, jcr->db, &jcr->jr, jcr->job->stats_enabled)) {
810       Jmsg(jcr, M_WARNING, 0, _("Error updating job record. %s"),
811          db_strerror(jcr->db));
812    }
813 }
814
815 /*
816  * Takes base_name and appends (unique) current
817  *   date and time to form unique job name.
818  *
819  *  Note, the seconds are actually a sequence number. This
820  *   permits us to start a maximum fo 59 unique jobs a second, which
821  *   should be sufficient.
822  *
823  *  Returns: unique job name in jcr->Job
824  *    date/time in jcr->start_time
825  */
826 void create_unique_job_name(JCR *jcr, const char *base_name)
827 {
828    /* Job start mutex */
829    static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
830    static time_t last_start_time = 0;
831    static int seq = 0;
832    time_t now;
833    struct tm tm;
834    char dt[MAX_TIME_LENGTH];
835    char name[MAX_NAME_LENGTH];
836    char *p;
837
838    /* Guarantee unique start time -- maximum one per second, and
839     * thus unique Job Name
840     */
841    P(mutex);                          /* lock creation of jobs */
842    now = time(NULL);
843    seq++;
844    if (seq > 59) {                    /* wrap as if it is seconds */
845       seq = 0;
846       while (now == last_start_time) {
847          bmicrosleep(0, 500000);
848          now = time(NULL);
849       }
850    }
851    last_start_time = now;
852    V(mutex);                          /* allow creation of jobs */
853    jcr->start_time = now;
854    /* Form Unique JobName */
855    (void)localtime_r(&now, &tm);
856    /* Use only characters that are permitted in Windows filenames */
857    strftime(dt, sizeof(dt), "%Y-%m-%d_%H.%M", &tm);
858    bstrncpy(name, base_name, sizeof(name));
859    name[sizeof(name)-22] = 0;          /* truncate if too long */
860    bsnprintf(jcr->Job, sizeof(jcr->Job), "%s.%s.%02d", name, dt, seq); /* add date & time */
861    /* Convert spaces into underscores */
862    for (p=jcr->Job; *p; p++) {
863       if (*p == ' ') {
864          *p = '_';
865       }
866    }
867 }
868
869 /* Called directly from job rescheduling */
870 void dird_free_jcr_pointers(JCR *jcr)
871 {
872    if (jcr->sd_auth_key) {
873       free(jcr->sd_auth_key);
874       jcr->sd_auth_key = NULL;
875    }
876    if (jcr->where) {
877       free(jcr->where);
878       jcr->where = NULL;
879    }
880    if (jcr->file_bsock) {
881       Dmsg0(200, "Close File bsock\n");
882       bnet_close(jcr->file_bsock);
883       jcr->file_bsock = NULL;
884    }
885    if (jcr->store_bsock) {
886       Dmsg0(200, "Close Store bsock\n");
887       bnet_close(jcr->store_bsock);
888       jcr->store_bsock = NULL;
889    }
890    if (jcr->fname) {
891       Dmsg0(200, "Free JCR fname\n");
892       free_pool_memory(jcr->fname);
893       jcr->fname = NULL;
894    }
895    if (jcr->RestoreBootstrap) {
896       free(jcr->RestoreBootstrap);
897       jcr->RestoreBootstrap = NULL;
898    }
899    if (jcr->client_uname) {
900       free_pool_memory(jcr->client_uname);
901       jcr->client_uname = NULL;
902    }
903    if (jcr->attr) {
904       free_pool_memory(jcr->attr);
905       jcr->attr = NULL;
906    }
907    if (jcr->ar) {
908       free(jcr->ar);
909       jcr->ar = NULL;
910    }
911 }
912
913 /*
914  * Free the Job Control Record if no one is still using it.
915  *  Called from main free_jcr() routine in src/lib/jcr.c so
916  *  that we can do our Director specific cleanup of the jcr.
917  */
918 void dird_free_jcr(JCR *jcr)
919 {
920    Dmsg0(200, "Start dird free_jcr\n");
921
922    dird_free_jcr_pointers(jcr);
923    if (jcr->term_wait_inited) {
924       pthread_cond_destroy(&jcr->term_wait);
925       jcr->term_wait_inited = false;
926    }
927    if (jcr->db_batch && jcr->db_batch != jcr->db) {
928       db_close_database(jcr, jcr->db_batch);
929    }
930    jcr->db_batch = NULL;
931    if (jcr->db) {
932       db_close_database(jcr, jcr->db);
933       jcr->db = NULL;
934    }
935    if (jcr->stime) {
936       Dmsg0(200, "Free JCR stime\n");
937       free_pool_memory(jcr->stime);
938       jcr->stime = NULL;
939    }
940    if (jcr->fname) {
941       Dmsg0(200, "Free JCR fname\n");
942       free_pool_memory(jcr->fname);
943       jcr->fname = NULL;
944    }
945    if (jcr->pool_source) {
946       free_pool_memory(jcr->pool_source);
947       jcr->pool_source = NULL;
948    }
949    if (jcr->catalog_source) {
950       free_pool_memory(jcr->catalog_source);
951       jcr->catalog_source = NULL;
952    }
953    if (jcr->rpool_source) {
954       free_pool_memory(jcr->rpool_source);
955       jcr->rpool_source = NULL;
956    }
957    if (jcr->wstore_source) {
958       free_pool_memory(jcr->wstore_source);
959       jcr->wstore_source = NULL;
960    }
961    if (jcr->rstore_source) {
962       free_pool_memory(jcr->rstore_source);
963       jcr->rstore_source = NULL;
964    }
965
966    /* Delete lists setup to hold storage pointers */
967    free_rwstorage(jcr);
968
969    jcr->job_end_push.destroy();
970
971    if (jcr->JobId != 0)
972       write_state_file(director->working_directory, "bacula-dir", get_first_port_host_order(director->DIRaddrs));
973
974    Dmsg0(200, "End dird free_jcr\n");
975 }
976
977 /* 
978  * The Job storage definition must be either in the Job record
979  *  or in the Pool record.  The Pool record overrides the Job 
980  *  record.
981  */
982 void get_job_storage(USTORE *store, JOB *job, RUN *run) 
983 {
984    if (run && run->pool && run->pool->storage) {
985       store->store = (STORE *)run->pool->storage->first();
986       pm_strcpy(store->store_source, _("Run pool override"));
987       return;
988    }
989    if (run && run->storage) {
990       store->store = run->storage;
991       pm_strcpy(store->store_source, _("Run storage override"));
992       return;
993    }
994    if (job->pool->storage) {
995       store->store = (STORE *)job->pool->storage->first();
996       pm_strcpy(store->store_source, _("Pool resource"));
997    } else {
998       store->store = (STORE *)job->storage->first();
999       pm_strcpy(store->store_source, _("Job resource"));
1000    }
1001 }
1002
1003 /*
1004  * Set some defaults in the JCR necessary to
1005  * run. These items are pulled from the job
1006  * definition as defaults, but can be overridden
1007  * later either by the Run record in the Schedule resource,
1008  * or by the Console program.
1009  */
1010 void set_jcr_defaults(JCR *jcr, JOB *job)
1011 {
1012    jcr->job = job;
1013    jcr->JobType = job->JobType;
1014    jcr->JobStatus = JS_Created;
1015    switch (jcr->JobType) {
1016    case JT_ADMIN:
1017    case JT_RESTORE:
1018       jcr->JobLevel = L_NONE;
1019       break;
1020    case JT_COPY:
1021    case JT_MIGRATE:
1022       if (!jcr->rpool_source) {
1023          jcr->rpool_source = get_pool_memory(PM_MESSAGE);
1024          pm_strcpy(jcr->rpool_source, _("unknown source"));
1025       }
1026       /* Fall-through wanted */
1027    default:
1028       jcr->JobLevel = job->JobLevel;
1029       break;
1030    }
1031    if (!jcr->fname) {
1032       jcr->fname = get_pool_memory(PM_FNAME);
1033    }
1034    if (!jcr->pool_source) {
1035       jcr->pool_source = get_pool_memory(PM_MESSAGE);
1036       pm_strcpy(jcr->pool_source, _("unknown source"));
1037    }
1038    if (!jcr->catalog_source) {
1039       jcr->catalog_source = get_pool_memory(PM_MESSAGE);
1040       pm_strcpy(jcr->catalog_source, _("unknown source"));
1041    }
1042
1043    jcr->JobPriority = job->Priority;
1044    /* Copy storage definitions -- deleted in dir_free_jcr above */
1045    if (job->storage) {
1046       copy_rwstorage(jcr, job->storage, _("Job resource"));
1047    } else {
1048       copy_rwstorage(jcr, job->pool->storage, _("Pool resource"));
1049    }
1050    jcr->client = job->client;
1051    if (!jcr->client_name) {
1052       jcr->client_name = get_pool_memory(PM_NAME);
1053    }
1054    pm_strcpy(jcr->client_name, jcr->client->hdr.name);
1055    pm_strcpy(jcr->pool_source, _("Job resource"));
1056    jcr->pool = job->pool;
1057    jcr->full_pool = job->full_pool;
1058    jcr->inc_pool = job->inc_pool;
1059    jcr->diff_pool = job->diff_pool;
1060    if (job->pool->catalog) {
1061       jcr->catalog = job->pool->catalog;
1062       pm_strcpy(jcr->catalog_source, _("Pool resource"));
1063    } else {
1064       jcr->catalog = job->client->catalog;
1065       pm_strcpy(jcr->catalog_source, _("Client resource"));
1066    }
1067    jcr->fileset = job->fileset;
1068    jcr->messages = job->messages;
1069    jcr->spool_data = job->spool_data;
1070    jcr->spool_size = job->spool_size;
1071    jcr->write_part_after_job = job->write_part_after_job;
1072    jcr->accurate = job->accurate;
1073    if (jcr->RestoreBootstrap) {
1074       free(jcr->RestoreBootstrap);
1075       jcr->RestoreBootstrap = NULL;
1076    }
1077    /* This can be overridden by Console program */
1078    if (job->RestoreBootstrap) {
1079       jcr->RestoreBootstrap = bstrdup(job->RestoreBootstrap);
1080    }
1081    /* This can be overridden by Console program */
1082    jcr->verify_job = job->verify_job;
1083    /* If no default level given, set one */
1084    if (jcr->JobLevel == 0) {
1085       switch (jcr->JobType) {
1086       case JT_VERIFY:
1087          jcr->JobLevel = L_VERIFY_CATALOG;
1088          break;
1089       case JT_BACKUP:
1090          jcr->JobLevel = L_INCREMENTAL;
1091          break;
1092       case JT_RESTORE:
1093       case JT_ADMIN:
1094          jcr->JobLevel = L_NONE;
1095          break;
1096       default:
1097          jcr->JobLevel = L_FULL;
1098          break;
1099       }
1100    }
1101 }
1102
1103 /* 
1104  * Copy the storage definitions from an alist to the JCR
1105  */
1106 void copy_rwstorage(JCR *jcr, alist *storage, const char *where)
1107 {
1108    switch(jcr->JobType) {
1109    case JT_RESTORE:
1110    case JT_VERIFY:
1111    case JT_COPY:
1112    case JT_MIGRATE:
1113       copy_rstorage(jcr, storage, where);
1114       break;
1115    default:
1116       copy_wstorage(jcr, storage, where);
1117       break;
1118    }
1119 }
1120
1121
1122 /* Set storage override.  Releases any previous storage definition */
1123 void set_rwstorage(JCR *jcr, USTORE *store)
1124 {
1125    if (!store) {
1126       Jmsg(jcr, M_FATAL, 0, _("No storage specified.\n"));
1127       return;
1128    }
1129    switch(jcr->JobType) {
1130    case JT_RESTORE:
1131    case JT_VERIFY:
1132    case JT_COPY:
1133    case JT_MIGRATE:
1134       set_rstorage(jcr, store);
1135       break;
1136    default:
1137       set_wstorage(jcr, store);
1138       break;
1139    }
1140 }
1141
1142 void free_rwstorage(JCR *jcr)
1143 {
1144    free_rstorage(jcr);
1145    free_wstorage(jcr);
1146 }
1147
1148 /* 
1149  * Copy the storage definitions from an alist to the JCR
1150  */
1151 void copy_rstorage(JCR *jcr, alist *storage, const char *where)
1152 {
1153    if (storage) {
1154       STORE *st;
1155       if (jcr->rstorage) {
1156          delete jcr->rstorage;
1157       }
1158       jcr->rstorage = New(alist(10, not_owned_by_alist));
1159       foreach_alist(st, storage) {
1160          jcr->rstorage->append(st);
1161       }
1162       if (!jcr->rstore_source) {
1163          jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1164       }
1165       pm_strcpy(jcr->rstore_source, where);
1166       if (jcr->rstorage) {
1167          jcr->rstore = (STORE *)jcr->rstorage->first();
1168       }
1169    }
1170 }
1171
1172
1173 /* Set storage override.  Remove all previous storage */
1174 void set_rstorage(JCR *jcr, USTORE *store)
1175 {
1176    STORE *storage;
1177
1178    if (!store->store) {
1179       return;
1180    }
1181    if (jcr->rstorage) {
1182       free_rstorage(jcr);
1183    }
1184    if (!jcr->rstorage) {
1185       jcr->rstorage = New(alist(10, not_owned_by_alist));
1186    }
1187    jcr->rstore = store->store;
1188    if (!jcr->rstore_source) {
1189       jcr->rstore_source = get_pool_memory(PM_MESSAGE);
1190    }
1191    pm_strcpy(jcr->rstore_source, store->store_source);
1192    foreach_alist(storage, jcr->rstorage) {
1193       if (store->store == storage) {
1194          return;
1195       }
1196    }
1197    /* Store not in list, so add it */
1198    jcr->rstorage->prepend(store->store);
1199 }
1200
1201 void free_rstorage(JCR *jcr)
1202 {
1203    if (jcr->rstorage) {
1204       delete jcr->rstorage;
1205       jcr->rstorage = NULL;
1206    }
1207    jcr->rstore = NULL;
1208 }
1209
1210 /* 
1211  * Copy the storage definitions from an alist to the JCR
1212  */
1213 void copy_wstorage(JCR *jcr, alist *storage, const char *where)
1214 {
1215    if (storage) {
1216       STORE *st;
1217       if (jcr->wstorage) {
1218          delete jcr->wstorage;
1219       }
1220       jcr->wstorage = New(alist(10, not_owned_by_alist));
1221       foreach_alist(st, storage) {
1222          Dmsg1(100, "wstorage=%s\n", st->name());
1223          jcr->wstorage->append(st);
1224       }
1225       if (!jcr->wstore_source) {
1226          jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1227       }
1228       pm_strcpy(jcr->wstore_source, where);
1229       if (jcr->wstorage) {
1230          jcr->wstore = (STORE *)jcr->wstorage->first();
1231          Dmsg2(100, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1232       }
1233    }
1234 }
1235
1236
1237 /* Set storage override. Remove all previous storage */
1238 void set_wstorage(JCR *jcr, USTORE *store)
1239 {
1240    STORE *storage;
1241
1242    if (!store->store) {
1243       return;
1244    }
1245    if (jcr->wstorage) {
1246       free_wstorage(jcr);
1247    }
1248    if (!jcr->wstorage) {
1249       jcr->wstorage = New(alist(10, not_owned_by_alist));
1250    }
1251    jcr->wstore = store->store;
1252    if (!jcr->wstore_source) {
1253       jcr->wstore_source = get_pool_memory(PM_MESSAGE);
1254    }
1255    pm_strcpy(jcr->wstore_source, store->store_source);
1256    Dmsg2(50, "wstore=%s where=%s\n", jcr->wstore->name(), jcr->wstore_source);
1257    foreach_alist(storage, jcr->wstorage) {
1258       if (store->store == storage) {
1259          return;
1260       }
1261    }
1262    /* Store not in list, so add it */
1263    jcr->wstorage->prepend(store->store);
1264 }
1265
1266 void free_wstorage(JCR *jcr)
1267 {
1268    if (jcr->wstorage) {
1269       delete jcr->wstorage;
1270       jcr->wstorage = NULL;
1271    }
1272    jcr->wstore = NULL;
1273 }
1274
1275 char *job_code_callback_clones(JCR *jcr, const char* param) {
1276         if (param[0] == 'p') {
1277                 return jcr->pool->name();
1278         } else {
1279                 return NULL;
1280         }
1281 }
1282
1283 void create_clones(JCR *jcr)
1284 {
1285    /*
1286     * Fire off any clone jobs (run directives)
1287     */
1288    Dmsg2(900, "cloned=%d run_cmds=%p\n", jcr->cloned, jcr->job->run_cmds);
1289    if (!jcr->cloned && jcr->job->run_cmds) {
1290       char *runcmd;
1291       JOB *job = jcr->job;
1292       POOLMEM *cmd = get_pool_memory(PM_FNAME);
1293       UAContext *ua = new_ua_context(jcr);
1294       ua->batch = true;
1295       foreach_alist(runcmd, job->run_cmds) {
1296          cmd = edit_job_codes(jcr, cmd, runcmd, "", job_code_callback_clones);
1297          Mmsg(ua->cmd, "run %s cloned=yes", cmd);
1298          Dmsg1(900, "=============== Clone cmd=%s\n", ua->cmd);
1299          parse_ua_args(ua);                 /* parse command */
1300          int stat = run_cmd(ua, ua->cmd);
1301          if (stat == 0) {
1302             Jmsg(jcr, M_ERROR, 0, _("Could not start clone job.\n"));
1303          } else {
1304             Jmsg(jcr, M_INFO, 0, _("Clone JobId %d started.\n"), stat);
1305          }
1306       }
1307       free_ua_context(ua);
1308       free_pool_memory(cmd);
1309    }
1310 }
1311
1312 bool create_restore_bootstrap_file(JCR *jcr)
1313 {
1314    RESTORE_CTX rx;
1315    UAContext *ua;
1316    memset(&rx, 0, sizeof(rx));
1317    rx.bsr = new_bsr();
1318    rx.JobIds = (char *)"";                       
1319    rx.bsr->JobId = jcr->previous_jr.JobId;
1320    ua = new_ua_context(jcr);
1321    complete_bsr(ua, rx.bsr);
1322    rx.bsr->fi = new_findex();
1323    rx.bsr->fi->findex = 1;
1324    rx.bsr->fi->findex2 = jcr->previous_jr.JobFiles;
1325    jcr->ExpectedFiles = write_bsr_file(ua, rx);
1326    if (jcr->ExpectedFiles == 0) {
1327       free_ua_context(ua);
1328       free_bsr(rx.bsr);
1329       return false;
1330    }
1331    free_ua_context(ua);
1332    free_bsr(rx.bsr);
1333    jcr->needs_sd = true;
1334    return true;
1335 }
1336
1337 bool run_console_command(JCR *jcr, const char *cmd){
1338    UAContext *ua;
1339    bool ok;
1340
1341    ua = new_ua_context(jcr);
1342    Mmsg(ua->cmd, "%s", cmd);
1343    Dmsg1(100, "Console command: %s\n", ua->cmd);
1344    parse_ua_args(ua);
1345    ok= do_a_command(ua);
1346    free_ua_context(ua);
1347    return ok;
1348 }