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)
602 POOLMEM *err = get_pool_memory(PM_FNAME);
605 memset(mr, 0, sizeof(MEDIA_DBR));
607 i = find_arg_with_value(ua, "volume");
609 if (is_name_valid(ua->argv[i], &err)) {
610 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
615 if (mr->VolumeName[0] == 0) {
617 memset(&pr, 0, sizeof(pr));
618 /* Get the pool from pool=<pool-name> */
619 if (!get_pool_dbr(ua, &pr)) {
622 mr->PoolId = pr.PoolId;
623 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
624 if (!get_cmd(ua, _("Enter *MediaId or Volume name: "))) {
627 if (ua->cmd[0] == '*' && is_a_number(ua->cmd+1)) {
628 mr->MediaId = str_to_int64(ua->cmd+1);
629 } else if (is_name_valid(ua->cmd, &err)) {
630 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
636 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
637 pm_strcpy(err, db_strerror(ua->db));
644 ua->error_msg("%s", err);
646 free_pool_memory(err);
652 * Select a pool resource from prompt list
654 POOL *select_pool_resource(UAContext *ua)
656 char name[MAX_NAME_LENGTH];
659 start_prompt(ua, _("The defined Pool resources are:\n"));
661 foreach_res(pool, R_POOL) {
662 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
663 add_prompt(ua, pool->name());
667 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
670 pool = (POOL *)GetResWithName(R_POOL, name);
676 * If you are thinking about using it, you
677 * probably want to use select_pool_dbr()
678 * or get_pool_dbr() above.
680 POOL *get_pool_resource(UAContext *ua)
685 i = find_arg_with_value(ua, "pool");
686 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
687 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
691 ua->error_msg(_("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
693 return select_pool_resource(ua);
697 * List all jobs and ask user to select one
699 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
701 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
702 if (!get_pint(ua, _("Enter the JobId to select: "))) {
705 jr->JobId = ua->int64_val;
706 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
707 ua->error_msg("%s", db_strerror(ua->db));
715 /* Scan what the user has entered looking for:
719 * if error or not found, put up a list of Jobs
722 * returns: 0 on error
723 * JobId on success and fills in JOB_DBR
725 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
729 for (i=1; i<ua->argc; i++) {
730 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
732 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
733 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
734 jr->JobId = str_to_int64(ua->argv[i]);
739 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
740 ua->error_msg(_("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
741 db_strerror(ua->db));
751 for (i=1; i<ua->argc; i++) {
752 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
753 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
755 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
759 if (!select_job_dbr(ua, jr)) { /* try once more */
766 * Implement unique set of prompts
768 void start_prompt(UAContext *ua, const char *msg)
770 if (ua->max_prompts == 0) {
771 ua->max_prompts = 10;
772 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
775 ua->prompt[0] = bstrdup(msg);
779 * Add to prompts -- keeping them unique
781 void add_prompt(UAContext *ua, const char *prompt)
784 if (ua->num_prompts == ua->max_prompts) {
785 ua->max_prompts *= 2;
786 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
789 for (i=1; i < ua->num_prompts; i++) {
790 if (strcmp(ua->prompt[i], prompt) == 0) {
794 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
798 * Display prompts and get user's choice
800 * Returns: -1 on error
801 * index base 0 on success, and choice
802 * is copied to prompt if not NULL
803 * prompt is set to the chosen prompt item string
805 int do_prompt(UAContext *ua, const char *automsg, const char *msg,
806 char *prompt, int max_prompt)
809 char pmsg[MAXSTRING];
810 BSOCK *user = ua->UA_sock;
815 if (ua->num_prompts == 2) {
818 bstrncpy(prompt, ua->prompt[1], max_prompt);
820 ua->send_msg(_("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
823 /* If running non-interactive, bail out */
825 /* First print the choices he wanted to make */
826 ua->send_msg(ua->prompt[0]);
827 for (i=1; i < ua->num_prompts; i++) {
828 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
830 /* Now print error message */
831 ua->send_msg(_("Your request has multiple choices for \"%s\". Selection is not possible in batch mode.\n"), automsg);
835 if (ua->api) user->signal(BNET_START_SELECT);
836 ua->send_msg(ua->prompt[0]);
837 for (i=1; i < ua->num_prompts; i++) {
839 ua->send_msg("%s", ua->prompt[i]);
841 ua->send_msg("%6d: %s\n", i, ua->prompt[i]);
844 if (ua->api) user->signal(BNET_END_SELECT);
847 /* First item is the prompt string, not the items */
848 if (ua->num_prompts == 1) {
849 ua->error_msg(_("Selection list for \"%s\" is empty!\n"), automsg);
850 item = -1; /* list is empty ! */
853 if (ua->num_prompts == 2) {
855 ua->send_msg(_("Automatically selected: %s\n"), ua->prompt[1]);
857 bstrncpy(prompt, ua->prompt[1], max_prompt);
861 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
863 /* Either a . or an @ will get you out of the loop */
864 if (ua->api) user->signal(BNET_SELECT_INPUT);
865 if (!get_pint(ua, pmsg)) {
866 item = -1; /* error */
867 ua->info_msg(_("Selection aborted, nothing done.\n"));
870 item = ua->pint32_val;
871 if (item < 1 || item >= ua->num_prompts) {
872 ua->warning_msg(_("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
876 bstrncpy(prompt, ua->prompt[item], max_prompt);
882 for (i=0; i < ua->num_prompts; i++) {
886 return item>0 ? item-1 : item;
891 * We scan what the user has entered looking for
892 * storage=<storage-resource>
895 * ? (prompt him with storage list)
896 * <some-error> (prompt him with storage list)
898 * If use_default is set, we assume that any keyword without a value
899 * is the name of the Storage resource wanted.
901 STORE *get_storage_resource(UAContext *ua, bool use_default)
903 char *store_name = NULL;
910 for (i=1; i<ua->argc; i++) {
911 if (use_default && !ua->argv[i]) {
912 /* Ignore slots, scan and barcode(s) keywords */
913 if (strcasecmp("scan", ua->argk[i]) == 0 ||
914 strcasecmp("barcode", ua->argk[i]) == 0 ||
915 strcasecmp("barcodes", ua->argk[i]) == 0 ||
916 strcasecmp("slots", ua->argk[i]) == 0) {
919 /* Default argument is storage */
921 ua->error_msg(_("Storage name given twice.\n"));
924 store_name = ua->argk[i];
925 if (*store_name == '?') {
930 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
931 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
932 store_name = ua->argv[i];
935 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
936 jobid = str_to_int64(ua->argv[i]);
938 ua->error_msg(_("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
941 if (!(jcr=get_jcr_by_id(jobid))) {
942 ua->error_msg(_("JobId %s is not running.\n"), edit_int64(jobid, ed1));
949 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
950 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
952 ua->error_msg(_("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
955 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
956 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
962 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
964 ua->error_msg(_("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
967 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
968 ua->error_msg(_("Job \"%s\" is not running.\n"), ua->argv[i]);
977 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
981 if (!store && store_name && store_name[0] != 0) {
982 store = (STORE *)GetResWithName(R_STORAGE, store_name);
984 ua->error_msg(_("Storage resource \"%s\": not found\n"), store_name);
987 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
990 /* No keywords found, so present a selection list */
992 store = select_storage_resource(ua);
997 /* Get drive that we are working with for this storage */
998 int get_storage_drive(UAContext *ua, STORE *store)
1001 /* Get drive for autochanger if possible */
1002 i = find_arg_with_value(ua, "drive");
1004 drive = atoi(ua->argv[i]);
1005 } else if (store && store->autochanger) {
1006 /* If our structure is not set ask SD for # drives */
1007 if (store->drives == 0) {
1008 store->drives = get_num_drives_from_SD(ua);
1010 /* If only one drive, default = 0 */
1011 if (store->drives == 1) {
1014 /* Ask user to enter drive number */
1016 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
1017 drive = -1; /* None */
1019 drive = atoi(ua->cmd);
1026 /* Get slot that we are working with for this storage */
1027 int get_storage_slot(UAContext *ua, STORE *store)
1030 /* Get slot for autochanger if possible */
1031 i = find_arg_with_value(ua, "slot");
1033 slot = atoi(ua->argv[i]);
1034 } else if (store && store->autochanger) {
1035 /* Ask user to enter slot number */
1037 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
1038 slot = -1; /* None */
1040 slot = atoi(ua->cmd);
1049 * Scan looking for mediatype=
1051 * if not found or error, put up selection list
1053 * Returns: 0 on error
1054 * 1 on success, MediaType is set
1056 int get_media_type(UAContext *ua, char *MediaType, int max_media)
1061 i = find_arg_with_value(ua, "mediatype");
1063 bstrncpy(MediaType, ua->argv[i], max_media);
1067 start_prompt(ua, _("Media Types defined in conf file:\n"));
1069 foreach_res(store, R_STORAGE) {
1070 add_prompt(ua, store->media_type);
1073 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
1076 bool get_level_from_name(JCR *jcr, const char *level_name)
1078 /* Look up level name and pull code */
1080 for (int i=0; joblevels[i].level_name; i++) {
1081 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
1082 jcr->setJobLevel(joblevels[i].level);