2 Bacula® - The Network Backup Solution
4 Copyright (C) 2001-2009 Free Software Foundation Europe e.V.
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 three of the GNU Affero General Public
10 License as published by the Free Software Foundation and included
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.
18 You should have received a copy of the GNU Affero 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
23 Bacula® is a registered trademark of Kern Sibbald.
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.
30 * Bacula Director -- User Agent Prompt and Selection code
32 * Kern Sibbald, October MMI
39 /* Imported variables */
40 extern struct s_jl joblevels[];
44 * Confirm a retention period
46 int confirm_retention(UAContext *ua, utime_t *ret, const char *msg)
51 int yes_in_arg = find_arg(ua, NT_("yes"));
54 ua->info_msg(_("The current %s retention period is: %s\n"),
55 msg, edit_utime(*ret, ed1, sizeof(ed1)));
56 if (yes_in_arg != -1) {
59 if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) {
62 if (strcasecmp(ua->cmd, _("mod")) == 0) {
63 if (!get_cmd(ua, _("Enter new retention period: "))) {
66 if (!duration_to_utime(ua->cmd, ret)) {
67 ua->error_msg(_("Invalid period.\n"));
72 if (is_yesno(ua->cmd, &val)) {
73 return val; /* is 1 for yes, 0 for no */
80 * Given a list of keywords, find the first one
81 * that is in the argument list.
82 * Returns: -1 if not found
83 * index into list (base 0) on success
85 int find_arg_keyword(UAContext *ua, const char **list)
87 for (int i=1; i<ua->argc; i++) {
88 for(int j=0; list[j]; j++) {
89 if (strcasecmp(list[j], ua->argk[i]) == 0) {
98 * Given one keyword, find the first one that
99 * is in the argument list.
100 * Returns: argk index (always gt 0)
103 int find_arg(UAContext *ua, const char *keyword)
105 for (int i=1; i<ua->argc; i++) {
106 if (strcasecmp(keyword, ua->argk[i]) == 0) {
114 * Given a single keyword, find it in the argument list, but
115 * it must have a value
116 * Returns: -1 if not found or no value
117 * list index (base 0) on success
119 int find_arg_with_value(UAContext *ua, const char *keyword)
121 for (int i=1; i<ua->argc; i++) {
122 if (strcasecmp(keyword, ua->argk[i]) == 0) {
134 * Given a list of keywords, prompt the user
137 * Returns: -1 on failure
138 * index into list (base 0) on success
140 int do_keyword_prompt(UAContext *ua, const char *msg, const char **list)
143 start_prompt(ua, _("You have the following choices:\n"));
144 for (i=0; list[i]; i++) {
145 add_prompt(ua, list[i]);
147 return do_prompt(ua, "", msg, NULL, 0);
152 * Select a Storage resource from prompt list
154 STORE *select_storage_resource(UAContext *ua)
156 char name[MAX_NAME_LENGTH];
159 start_prompt(ua, _("The defined Storage resources are:\n"));
161 foreach_res(store, R_STORAGE) {
162 if (acl_access_ok(ua, Storage_ACL, store->name())) {
163 add_prompt(ua, store->name());
167 if (do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name)) < 0) {
170 store = (STORE *)GetResWithName(R_STORAGE, name);
175 * Select a FileSet resource from prompt list
177 FILESET *select_fileset_resource(UAContext *ua)
179 char name[MAX_NAME_LENGTH];
182 start_prompt(ua, _("The defined FileSet resources are:\n"));
184 foreach_res(fs, R_FILESET) {
185 if (acl_access_ok(ua, FileSet_ACL, fs->name())) {
186 add_prompt(ua, fs->name());
190 if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) {
193 fs = (FILESET *)GetResWithName(R_FILESET, name);
199 * Get a catalog resource from prompt list
201 CAT *get_catalog_resource(UAContext *ua)
203 char name[MAX_NAME_LENGTH];
207 for (i=1; i<ua->argc; i++) {
208 if (strcasecmp(ua->argk[i], NT_("catalog")) == 0 && ua->argv[i]) {
209 if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
210 catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
215 if (ua->gui && !catalog) {
217 catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
220 ua->error_msg(_("Could not find a Catalog resource\n"));
222 } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
223 ua->error_msg(_("You must specify a \"use <catalog-name>\" command before continuing.\n"));
229 start_prompt(ua, _("The defined Catalog resources are:\n"));
231 foreach_res(catalog, R_CATALOG) {
232 if (acl_access_ok(ua, Catalog_ACL, catalog->name())) {
233 add_prompt(ua, catalog->name());
237 if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) {
240 catalog = (CAT *)GetResWithName(R_CATALOG, name);
247 * Select a job to enable or disable
249 JOB *select_enable_disable_job_resource(UAContext *ua, bool enable)
251 char name[MAX_NAME_LENGTH];
255 start_prompt(ua, _("The defined Job resources are:\n"));
256 foreach_res(job, R_JOB) {
257 if (!acl_access_ok(ua, Job_ACL, job->name())) {
260 if (job->enabled == enable) { /* Already enabled/disabled? */
261 continue; /* yes, skip */
263 add_prompt(ua, job->name());
266 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
269 job = (JOB *)GetResWithName(R_JOB, name);
274 * Select a Job resource from prompt list
276 JOB *select_job_resource(UAContext *ua)
278 char name[MAX_NAME_LENGTH];
281 start_prompt(ua, _("The defined Job resources are:\n"));
283 foreach_res(job, R_JOB) {
284 if (acl_access_ok(ua, Job_ACL, job->name())) {
285 add_prompt(ua, job->name());
289 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
292 job = (JOB *)GetResWithName(R_JOB, name);
297 * Select a Restore Job resource from argument or prompt
299 JOB *get_restore_job(UAContext *ua)
302 int i = find_arg_with_value(ua, "restore_job");
303 if (i >= 0 && acl_access_ok(ua, Job_ACL, ua->argv[i])) {
304 job = (JOB *)GetResWithName(R_JOB, ua->argv[i]);
305 if (job && job->JobType == JT_RESTORE) {
308 ua->error_msg(_("Error: Restore Job resource \"%s\" does not exist.\n"),
311 return select_restore_job_resource(ua);
315 * Select a Restore Job resource from prompt list
317 JOB *select_restore_job_resource(UAContext *ua)
319 char name[MAX_NAME_LENGTH];
322 start_prompt(ua, _("The defined Restore Job resources are:\n"));
324 foreach_res(job, R_JOB) {
325 if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->name())) {
326 add_prompt(ua, job->name());
330 if (do_prompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
333 job = (JOB *)GetResWithName(R_JOB, name);
340 * Select a client resource from prompt list
342 CLIENT *select_client_resource(UAContext *ua)
344 char name[MAX_NAME_LENGTH];
347 start_prompt(ua, _("The defined Client resources are:\n"));
349 foreach_res(client, R_CLIENT) {
350 if (acl_access_ok(ua, Client_ACL, client->name())) {
351 add_prompt(ua, client->name());
355 if (do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name)) < 0) {
358 client = (CLIENT *)GetResWithName(R_CLIENT, name);
363 * Get client resource, start by looking for
364 * client=<client-name>
365 * if we don't find the keyword, we prompt the user.
367 CLIENT *get_client_resource(UAContext *ua)
369 CLIENT *client = NULL;
372 for (i=1; i<ua->argc; i++) {
373 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
374 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
375 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
378 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
382 ua->error_msg(_("Error: Client resource %s does not exist.\n"), ua->argv[i]);
386 return select_client_resource(ua);
389 /* Scan what the user has entered looking for:
391 * client=<client-name>
393 * if error or not found, put up a list of client DBRs
396 * returns: 0 on error
397 * 1 on success and fills in CLIENT_DBR
399 bool get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
403 if (cr->Name[0]) { /* If name already supplied */
404 if (db_get_client_record(ua->jcr, ua->db, cr)) {
407 ua->error_msg(_("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
409 for (i=1; i<ua->argc; i++) {
410 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
411 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
412 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
415 bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
416 if (!db_get_client_record(ua->jcr, ua->db, cr)) {
417 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
418 db_strerror(ua->db));
425 if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
432 * Select a Client record from the catalog
433 * Returns 1 on success
436 bool select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
439 char name[MAX_NAME_LENGTH];
445 if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
446 ua->error_msg(_("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
449 if (num_clients <= 0) {
450 ua->error_msg(_("No clients defined. You must run a job before using this command.\n"));
454 start_prompt(ua, _("Defined Clients:\n"));
455 for (i=0; i < num_clients; i++) {
456 ocr.ClientId = ids[i];
457 if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
458 !acl_access_ok(ua, Client_ACL, ocr.Name)) {
461 add_prompt(ua, ocr.Name);
464 if (do_prompt(ua, _("Client"), _("Select the Client"), name, sizeof(name)) < 0) {
467 memset(&ocr, 0, sizeof(ocr));
468 bstrncpy(ocr.Name, name, sizeof(ocr.Name));
470 if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
471 ua->error_msg(_("Could not find Client \"%s\": ERR=%s"), name, db_strerror(ua->db));
474 memcpy(cr, &ocr, sizeof(ocr));
478 /* Scan what the user has entered looking for:
482 * where argk can be : pool, recyclepool, scratchpool, nextpool etc..
484 * if error or not found, put up a list of pool DBRs
487 * returns: false on error
488 * true on success and fills in POOL_DBR
490 bool get_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
492 if (pr->Name[0]) { /* If name already supplied */
493 if (db_get_pool_record(ua->jcr, ua->db, pr) &&
494 acl_access_ok(ua, Pool_ACL, pr->Name)) {
497 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
499 if (!select_pool_dbr(ua, pr, argk)) { /* try once more */
506 * Select a Pool record from catalog
507 * argk can be pool, recyclepool, scratchpool etc..
509 bool select_pool_dbr(UAContext *ua, POOL_DBR *pr, const char *argk)
512 char name[MAX_NAME_LENGTH];
516 for (i=1; i<ua->argc; i++) {
517 if (strcasecmp(ua->argk[i], argk) == 0 && ua->argv[i] &&
518 acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
519 bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
520 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
521 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
522 db_strerror(ua->db));
531 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
532 ua->error_msg(_("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
535 if (num_pools <= 0) {
536 ua->error_msg(_("No pools defined. Use the \"create\" command to create one.\n"));
540 start_prompt(ua, _("Defined Pools:\n"));
541 if (bstrcmp(argk, NT_("recyclepool"))) {
542 add_prompt(ua, _("*None*"));
544 for (i=0; i < num_pools; i++) {
546 if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
547 !acl_access_ok(ua, Pool_ACL, opr.Name)) {
550 add_prompt(ua, opr.Name);
553 if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
557 memset(&opr, 0, sizeof(opr));
558 /* *None* is only returned when selecting a recyclepool, and in that case
559 * the calling code is only interested in opr.Name, so then we can leave
562 if (!bstrcmp(name, _("*None*"))) {
563 bstrncpy(opr.Name, name, sizeof(opr.Name));
565 if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
566 ua->error_msg(_("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
571 memcpy(pr, &opr, sizeof(opr));
576 * Select a Pool and a Media (Volume) record from the database
578 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
581 if (!select_media_dbr(ua, mr)) {
584 memset(pr, 0, sizeof(POOL_DBR));
585 pr->PoolId = mr->PoolId;
586 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
587 ua->error_msg("%s", db_strerror(ua->db));
590 if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
591 ua->error_msg(_("No access to Pool \"%s\"\n"), pr->Name);
597 /* Select a Media (Volume) record from the database */
598 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
603 POOLMEM *err = get_pool_memory(PM_FNAME);
604 memset(mr, 0, sizeof(MEDIA_DBR));
606 i = find_arg_with_value(ua, "volume");
608 if (is_name_valid(ua->argv[i], &err)) {
609 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
614 if (mr->VolumeName[0] == 0) {
616 memset(&pr, 0, sizeof(pr));
617 /* Get the pool from pool=<pool-name> */
618 if (!get_pool_dbr(ua, &pr)) {
621 mr->PoolId = pr.PoolId;
622 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
623 if (!get_cmd(ua, _("Enter *MediaId or Volume name: "))) {
626 if (ua->cmd[0] == '*' && is_a_number(ua->cmd+1)) {
627 mr->MediaId = str_to_int64(ua->cmd+1);
628 } else if (is_name_valid(ua->cmd, &err)) {
629 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
635 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
636 pm_strcpy(err, db_strerror(ua->db));
643 ua->error_msg("%s", err);
645 free_pool_memory(err);
651 * Select a pool resource from prompt list
653 POOL *select_pool_resource(UAContext *ua)
655 char name[MAX_NAME_LENGTH];
658 start_prompt(ua, _("The defined Pool resources are:\n"));
660 foreach_res(pool, R_POOL) {
661 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
662 add_prompt(ua, pool->name());
666 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
669 pool = (POOL *)GetResWithName(R_POOL, name);
675 * If you are thinking about using it, you
676 * probably want to use select_pool_dbr()
677 * or get_pool_dbr() above.
679 POOL *get_pool_resource(UAContext *ua)
684 i = find_arg_with_value(ua, "pool");
685 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
686 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
690 ua->error_msg(_("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
692 return select_pool_resource(ua);
696 * List all jobs and ask user to select one
698 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
700 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
701 if (!get_pint(ua, _("Enter the JobId to select: "))) {
704 jr->JobId = ua->int64_val;
705 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
706 ua->error_msg("%s", db_strerror(ua->db));
714 /* Scan what the user has entered looking for:
718 * if error or not found, put up a list of Jobs
721 * returns: 0 on error
722 * JobId on success and fills in JOB_DBR
724 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
728 for (i=1; i<ua->argc; i++) {
729 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
731 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
732 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
733 jr->JobId = str_to_int64(ua->argv[i]);
738 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
739 ua->error_msg(_("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
740 db_strerror(ua->db));
750 for (i=1; i<ua->argc; i++) {
751 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
752 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
754 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
758 if (!select_job_dbr(ua, jr)) { /* try once more */
765 * Implement unique set of prompts
767 void start_prompt(UAContext *ua, const char *msg)
769 if (ua->max_prompts == 0) {
770 ua->max_prompts = 10;
771 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
774 ua->prompt[0] = bstrdup(msg);
778 * Add to prompts -- keeping them unique
780 void add_prompt(UAContext *ua, const char *prompt)
783 if (ua->num_prompts == ua->max_prompts) {
784 ua->max_prompts *= 2;
785 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
788 for (i=1; i < ua->num_prompts; i++) {
789 if (strcmp(ua->prompt[i], prompt) == 0) {
793 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
797 * Display prompts and get user's choice
799 * Returns: -1 on error
800 * index base 0 on success, and choice
801 * is copied to prompt if not NULL
802 * prompt is set to the chosen prompt item string
804 int do_prompt(UAContext *ua, const char *automsg, const char *msg,
805 char *prompt, int max_prompt)
808 char pmsg[MAXSTRING];
809 BSOCK *user = ua->UA_sock;
814 if (ua->num_prompts == 2) {
817 bstrncpy(prompt, ua->prompt[1], max_prompt);
819 ua->send_msg(_("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
822 /* If running non-interactive, bail out */
824 /* First print the choices he wanted to make */
825 ua->send_msg(ua->prompt[0]);
826 for (i=1; i < ua->num_prompts; i++) {
827 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
829 /* Now print error message */
830 ua->send_msg(_("Your request has multiple choices for \"%s\". Selection is not possible in batch mode.\n"), automsg);
834 if (ua->api) user->signal(BNET_START_SELECT);
835 ua->send_msg(ua->prompt[0]);
836 for (i=1; i < ua->num_prompts; i++) {
838 ua->send_msg("%s", ua->prompt[i]);
840 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
843 if (ua->api) user->signal(BNET_END_SELECT);
846 /* First item is the prompt string, not the items */
847 if (ua->num_prompts == 1) {
848 ua->error_msg(_("Selection list for \"%s\" is empty!\n"), automsg);
849 item = -1; /* list is empty ! */
852 if (ua->num_prompts == 2) {
854 ua->send_msg(_("Automatically selected: %s\n"), ua->prompt[1]);
856 bstrncpy(prompt, ua->prompt[1], max_prompt);
860 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
862 /* Either a . or an @ will get you out of the loop */
863 if (ua->api) user->signal(BNET_SELECT_INPUT);
864 if (!get_pint(ua, pmsg)) {
865 item = -1; /* error */
866 ua->info_msg(_("Selection aborted, nothing done.\n"));
869 item = ua->pint32_val;
870 if (item < 1 || item >= ua->num_prompts) {
871 ua->warning_msg(_("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
875 bstrncpy(prompt, ua->prompt[item], max_prompt);
881 for (i=0; i < ua->num_prompts; i++) {
885 return item>0 ? item-1 : item;
890 * We scan what the user has entered looking for
891 * storage=<storage-resource>
894 * ? (prompt him with storage list)
895 * <some-error> (prompt him with storage list)
897 * If use_default is set, we assume that any keyword without a value
898 * is the name of the Storage resource wanted.
900 STORE *get_storage_resource(UAContext *ua, bool use_default)
902 char *store_name = NULL;
909 for (i=1; i<ua->argc; i++) {
910 if (use_default && !ua->argv[i]) {
911 /* Ignore slots, scan and barcode(s) keywords */
912 if (strcasecmp("scan", ua->argk[i]) == 0 ||
913 strcasecmp("barcode", ua->argk[i]) == 0 ||
914 strcasecmp("barcodes", ua->argk[i]) == 0 ||
915 strcasecmp("slots", ua->argk[i]) == 0) {
918 /* Default argument is storage */
920 ua->error_msg(_("Storage name given twice.\n"));
923 store_name = ua->argk[i];
924 if (*store_name == '?') {
929 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
930 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
931 store_name = ua->argv[i];
934 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
935 jobid = str_to_int64(ua->argv[i]);
937 ua->error_msg(_("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
940 if (!(jcr=get_jcr_by_id(jobid))) {
941 ua->error_msg(_("JobId %s is not running.\n"), edit_int64(jobid, ed1));
948 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
949 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
951 ua->error_msg(_("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
954 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
955 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
961 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
963 ua->error_msg(_("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
966 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
967 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
976 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
980 if (!store && store_name && store_name[0] != 0) {
981 store = (STORE *)GetResWithName(R_STORAGE, store_name);
983 ua->error_msg(_("Storage resource \"%s\": not found\n"), store_name);
986 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
989 /* No keywords found, so present a selection list */
991 store = select_storage_resource(ua);
996 /* Get drive that we are working with for this storage */
997 int get_storage_drive(UAContext *ua, STORE *store)
1000 /* Get drive for autochanger if possible */
1001 i = find_arg_with_value(ua, "drive");
1003 drive = atoi(ua->argv[i]);
1004 } else if (store && store->autochanger) {
1005 /* If our structure is not set ask SD for # drives */
1006 if (store->drives == 0) {
1007 store->drives = get_num_drives_from_SD(ua);
1009 /* If only one drive, default = 0 */
1010 if (store->drives == 1) {
1013 /* Ask user to enter drive number */
1015 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
1016 drive = -1; /* None */
1018 drive = atoi(ua->cmd);
1025 /* Get slot that we are working with for this storage */
1026 int get_storage_slot(UAContext *ua, STORE *store)
1029 /* Get slot for autochanger if possible */
1030 i = find_arg_with_value(ua, "slot");
1032 slot = atoi(ua->argv[i]);
1033 } else if (store && store->autochanger) {
1034 /* Ask user to enter slot number */
1036 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
1037 slot = -1; /* None */
1039 slot = atoi(ua->cmd);
1048 * Scan looking for mediatype=
1050 * if not found or error, put up selection list
1052 * Returns: 0 on error
1053 * 1 on success, MediaType is set
1055 int get_media_type(UAContext *ua, char *MediaType, int max_media)
1060 i = find_arg_with_value(ua, "mediatype");
1062 bstrncpy(MediaType, ua->argv[i], max_media);
1066 start_prompt(ua, _("Media Types defined in conf file:\n"));
1068 foreach_res(store, R_STORAGE) {
1069 add_prompt(ua, store->media_type);
1072 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
1075 bool get_level_from_name(JCR *jcr, const char *level_name)
1077 /* Look up level name and pull code */
1079 for (int i=0; joblevels[i].level_name; i++) {
1080 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
1081 jcr->set_JobLevel(joblevels[i].level);
1089 /* Get a running job
1090 * "reason" is used in user messages
1091 * can be: cancel, limit, ...
1092 * Returns: NULL on error
1093 * JCR on success (should be free_jcr() after)
1095 JCR *select_running_job(UAContext *ua, const char *reason)
1100 char JobName[MAX_NAME_LENGTH];
1103 for (i=1; i<ua->argc; i++) {
1104 if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
1106 JobId = str_to_int64(ua->argv[i]);
1110 if (!(jcr=get_jcr_by_id(JobId))) {
1111 ua->error_msg(_("JobId %s is not running. Use Job name to %s inactive jobs.\n"), ua->argv[i], _(reason));
1115 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0) {
1119 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
1120 ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
1121 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
1122 bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
1125 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
1129 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
1130 ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
1131 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
1132 bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
1139 if (jcr->job && !acl_access_ok(ua, Job_ACL, jcr->job->name())) {
1140 ua->error_msg(_("Unauthorized command from this console.\n"));
1145 * If we still do not have a jcr,
1146 * throw up a list and ask the user to select one.
1149 int tjobs = 0; /* total # number jobs */
1150 /* Count Jobs running */
1152 if (jcr->JobId == 0) { /* this is us */
1155 tjobs++; /* count of all jobs */
1156 if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
1157 continue; /* skip not authorized */
1159 njobs++; /* count of authorized jobs */
1163 if (njobs == 0) { /* no authorized */
1165 ua->send_msg(_("No Jobs running.\n"));
1167 ua->send_msg(_("None of your jobs are running.\n"));
1172 start_prompt(ua, _("Select Job:\n"));
1175 if (jcr->JobId == 0) { /* this is us */
1178 if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
1179 continue; /* skip not authorized */
1181 bsnprintf(buf, sizeof(buf), _("JobId=%s Job=%s"), edit_int64(jcr->JobId, ed1), jcr->Job);
1182 add_prompt(ua, buf);
1185 bsnprintf(temp, sizeof(temp), _("Choose Job to %s"), _(reason));
1186 if (do_prompt(ua, _("Job"), temp, buf, sizeof(buf)) < 0) {
1189 if (!strcmp(reason, "cancel")) {
1190 if (ua->api && njobs == 1) {
1192 bsnprintf(nbuf, sizeof(nbuf), _("Cancel: %s\n\n%s"), buf,
1193 _("Confirm cancel?"));
1194 if (!get_yesno(ua, nbuf) || ua->pint32_val == 0) {
1199 if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) {
1205 sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName);
1206 jcr = get_jcr_by_full_name(JobName);
1208 ua->warning_msg(_("Job \"%s\" not found.\n"), JobName);