3 * Bacula Director -- User Agent Prompt and Selection code
5 * Kern Sibbald, October MMI
10 Bacula® - The Network Backup Solution
12 Copyright (C) 2001-2006 Free Software Foundation Europe e.V.
14 The main author of Bacula is Kern Sibbald, with contributions from
15 many others, a complete list can be found in the file AUTHORS.
16 This program is Free Software; you can redistribute it and/or
17 modify it under the terms of version two of the GNU General Public
18 License as published by the Free Software Foundation plus additions
19 that are listed in the file LICENSE.
21 This program is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received a copy of the GNU General Public License
27 along with this program; if not, write to the Free Software
28 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
31 Bacula® is a registered trademark of John Walker.
32 The licensor of Bacula is the Free Software Foundation Europe
33 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
34 Switzerland, email:ftf@fsfeurope.org.
40 /* Imported variables */
41 extern struct s_jl joblevels[];
45 * Confirm a retention period
47 int confirm_retention(UAContext *ua, utime_t *ret, const char *msg)
52 int yes_in_arg = find_arg(ua, NT_("yes"));
55 bsendmsg(ua, _("The current %s retention period is: %s\n"),
56 msg, edit_utime(*ret, ed1, sizeof(ed1)));
57 if (yes_in_arg != -1) {
60 if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) {
63 if (strcasecmp(ua->cmd, _("mod")) == 0) {
64 if (!get_cmd(ua, _("Enter new retention period: "))) {
67 if (!duration_to_utime(ua->cmd, ret)) {
68 bsendmsg(ua, _("Invalid period.\n"));
73 if (is_yesno(ua->cmd, &val)) {
74 return val; /* is 1 for yes, 0 for no */
81 * Given a list of keywords, find the first one
82 * that is in the argument list.
83 * Returns: -1 if not found
84 * index into list (base 0) on success
86 int find_arg_keyword(UAContext *ua, const char **list)
88 for (int i=1; i<ua->argc; i++) {
89 for(int j=0; list[j]; j++) {
90 if (strcasecmp(list[j], ua->argk[i]) == 0) {
99 * Given one keyword, find the first one that
100 * is in the argument list.
101 * Returns: argk index (always gt 0)
104 int find_arg(UAContext *ua, const char *keyword)
106 for (int i=1; i<ua->argc; i++) {
107 if (strcasecmp(keyword, ua->argk[i]) == 0) {
115 * Given a single keyword, find it in the argument list, but
116 * it must have a value
117 * Returns: -1 if not found or no value
118 * list index (base 0) on success
120 int find_arg_with_value(UAContext *ua, const char *keyword)
122 for (int i=1; i<ua->argc; i++) {
123 if (strcasecmp(keyword, ua->argk[i]) == 0) {
135 * Given a list of keywords, prompt the user
138 * Returns: -1 on failure
139 * index into list (base 0) on success
141 int do_keyword_prompt(UAContext *ua, const char *msg, const char **list)
144 start_prompt(ua, _("You have the following choices:\n"));
145 for (i=0; list[i]; i++) {
146 add_prompt(ua, list[i]);
148 return do_prompt(ua, "", msg, NULL, 0);
153 * Select a Storage resource from prompt list
155 STORE *select_storage_resource(UAContext *ua)
157 char name[MAX_NAME_LENGTH];
160 start_prompt(ua, _("The defined Storage resources are:\n"));
162 foreach_res(store, R_STORAGE) {
163 if (acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
164 add_prompt(ua, store->hdr.name);
168 if (do_prompt(ua, _("Storage"), _("Select Storage resource"), name, sizeof(name)) < 0) {
171 store = (STORE *)GetResWithName(R_STORAGE, name);
176 * Select a FileSet resource from prompt list
178 FILESET *select_fileset_resource(UAContext *ua)
180 char name[MAX_NAME_LENGTH];
183 start_prompt(ua, _("The defined FileSet resources are:\n"));
185 foreach_res(fs, R_FILESET) {
186 if (acl_access_ok(ua, FileSet_ACL, fs->hdr.name)) {
187 add_prompt(ua, fs->hdr.name);
191 if (do_prompt(ua, _("FileSet"), _("Select FileSet resource"), name, sizeof(name)) < 0) {
194 fs = (FILESET *)GetResWithName(R_FILESET, name);
200 * Get a catalog resource from prompt list
202 CAT *get_catalog_resource(UAContext *ua)
204 char name[MAX_NAME_LENGTH];
208 for (i=1; i<ua->argc; i++) {
209 if (strcasecmp(ua->argk[i], NT_("catalog")) == 0 && ua->argv[i]) {
210 if (acl_access_ok(ua, Catalog_ACL, ua->argv[i])) {
211 catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
217 start_prompt(ua, _("The defined Catalog resources are:\n"));
219 foreach_res(catalog, R_CATALOG) {
220 if (acl_access_ok(ua, Catalog_ACL, catalog->hdr.name)) {
221 add_prompt(ua, catalog->hdr.name);
225 if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) {
228 catalog = (CAT *)GetResWithName(R_CATALOG, name);
235 * Select a Job resource from prompt list
237 JOB *select_job_resource(UAContext *ua)
239 char name[MAX_NAME_LENGTH];
242 start_prompt(ua, _("The defined Job resources are:\n"));
244 foreach_res(job, R_JOB) {
245 if (acl_access_ok(ua, Job_ACL, job->hdr.name)) {
246 add_prompt(ua, job->hdr.name);
250 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
253 job = (JOB *)GetResWithName(R_JOB, name);
258 * Select a Restore Job resource from prompt list
260 JOB *select_restore_job_resource(UAContext *ua)
262 char name[MAX_NAME_LENGTH];
265 start_prompt(ua, _("The defined Restore Job resources are:\n"));
267 foreach_res(job, R_JOB) {
268 if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->hdr.name)) {
269 add_prompt(ua, job->hdr.name);
273 if (do_prompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
276 job = (JOB *)GetResWithName(R_JOB, name);
283 * Select a client resource from prompt list
285 CLIENT *select_client_resource(UAContext *ua)
287 char name[MAX_NAME_LENGTH];
290 start_prompt(ua, _("The defined Client resources are:\n"));
292 foreach_res(client, R_CLIENT) {
293 if (acl_access_ok(ua, Client_ACL, client->hdr.name)) {
294 add_prompt(ua, client->hdr.name);
298 if (do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name)) < 0) {
301 client = (CLIENT *)GetResWithName(R_CLIENT, name);
306 * Get client resource, start by looking for
307 * client=<client-name>
308 * if we don't find the keyword, we prompt the user.
310 CLIENT *get_client_resource(UAContext *ua)
312 CLIENT *client = NULL;
315 for (i=1; i<ua->argc; i++) {
316 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
317 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
318 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
321 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
325 bsendmsg(ua, _("Error: Client resource %s does not exist.\n"), ua->argv[i]);
329 return select_client_resource(ua);
332 /* Scan what the user has entered looking for:
334 * client=<client-name>
336 * if error or not found, put up a list of client DBRs
339 * returns: 0 on error
340 * 1 on success and fills in CLIENT_DBR
342 int get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
346 if (cr->Name[0]) { /* If name already supplied */
347 if (db_get_client_record(ua->jcr, ua->db, cr)) {
350 bsendmsg(ua, _("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
352 for (i=1; i<ua->argc; i++) {
353 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
354 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
355 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
358 bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
359 if (!db_get_client_record(ua->jcr, ua->db, cr)) {
360 bsendmsg(ua, _("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
361 db_strerror(ua->db));
368 if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
375 * Select a Client record from the catalog
376 * Returns 1 on success
379 int select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
382 char name[MAX_NAME_LENGTH];
388 if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
389 bsendmsg(ua, _("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
392 if (num_clients <= 0) {
393 bsendmsg(ua, _("No clients defined. You must run a job before using this command.\n"));
397 start_prompt(ua, _("Defined Clients:\n"));
398 for (i=0; i < num_clients; i++) {
399 ocr.ClientId = ids[i];
400 if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
401 !acl_access_ok(ua, Client_ACL, ocr.Name)) {
404 add_prompt(ua, ocr.Name);
407 if (do_prompt(ua, _("Client"), _("Select the Client"), name, sizeof(name)) < 0) {
410 memset(&ocr, 0, sizeof(ocr));
411 bstrncpy(ocr.Name, name, sizeof(ocr.Name));
413 if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
414 bsendmsg(ua, _("Could not find Client \"%s\": ERR=%s"), name, db_strerror(ua->db));
417 memcpy(cr, &ocr, sizeof(ocr));
423 /* Scan what the user has entered looking for:
427 * if error or not found, put up a list of pool DBRs
430 * returns: false on error
431 * true on success and fills in POOL_DBR
433 bool get_pool_dbr(UAContext *ua, POOL_DBR *pr)
435 if (pr->Name[0]) { /* If name already supplied */
436 if (db_get_pool_record(ua->jcr, ua->db, pr) &&
437 acl_access_ok(ua, Pool_ACL, pr->Name)) {
440 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
442 if (!select_pool_dbr(ua, pr)) { /* try once more */
449 * Select a Pool record from the catalog
451 bool select_pool_dbr(UAContext *ua, POOL_DBR *pr)
454 char name[MAX_NAME_LENGTH];
458 for (i=1; i<ua->argc; i++) {
459 if (strcasecmp(ua->argk[i], NT_("pool")) == 0 && ua->argv[i] &&
460 acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
461 bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
462 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
463 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
464 db_strerror(ua->db));
473 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
474 bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
477 if (num_pools <= 0) {
478 bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n"));
482 start_prompt(ua, _("Defined Pools:\n"));
483 for (i=0; i < num_pools; i++) {
485 if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
486 !acl_access_ok(ua, Pool_ACL, opr.Name)) {
489 add_prompt(ua, opr.Name);
492 if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
495 memset(&opr, 0, sizeof(opr));
496 bstrncpy(opr.Name, name, sizeof(opr.Name));
498 if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
499 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
502 memcpy(pr, &opr, sizeof(opr));
507 * Select a Pool and a Media (Volume) record from the database
509 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
512 if (!select_media_dbr(ua, mr)) {
515 memset(pr, 0, sizeof(POOL_DBR));
516 pr->PoolId = mr->PoolId;
517 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
518 bsendmsg(ua, "%s", db_strerror(ua->db));
521 if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
522 bsendmsg(ua, _("No access to Pool \"%s\"\n"), pr->Name);
528 /* Select a Media (Volume) record from the database */
529 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
533 memset(mr, 0, sizeof(MEDIA_DBR));
535 i = find_arg_with_value(ua, "volume");
537 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
539 if (mr->VolumeName[0] == 0) {
541 memset(&pr, 0, sizeof(pr));
542 /* Get the pool from pool=<pool-name> */
543 if (!get_pool_dbr(ua, &pr)) {
546 mr->PoolId = pr.PoolId;
547 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
548 if (!get_cmd(ua, _("Enter MediaId or Volume name: "))) {
551 if (is_a_number(ua->cmd)) {
552 mr->MediaId = str_to_int64(ua->cmd);
554 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
558 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
559 bsendmsg(ua, "%s", db_strerror(ua->db));
567 * Select a pool resource from prompt list
569 POOL *select_pool_resource(UAContext *ua)
571 char name[MAX_NAME_LENGTH];
574 start_prompt(ua, _("The defined Pool resources are:\n"));
576 foreach_res(pool, R_POOL) {
577 if (acl_access_ok(ua, Pool_ACL, pool->hdr.name)) {
578 add_prompt(ua, pool->hdr.name);
582 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
585 pool = (POOL *)GetResWithName(R_POOL, name);
591 * If you are thinking about using it, you
592 * probably want to use select_pool_dbr()
593 * or get_pool_dbr() above.
595 POOL *get_pool_resource(UAContext *ua)
600 i = find_arg_with_value(ua, "pool");
601 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
602 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
606 bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
608 return select_pool_resource(ua);
612 * List all jobs and ask user to select one
614 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
616 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
617 if (!get_pint(ua, _("Enter the JobId to select: "))) {
620 jr->JobId = ua->int64_val;
621 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
622 bsendmsg(ua, "%s", db_strerror(ua->db));
630 /* Scan what the user has entered looking for:
634 * if error or not found, put up a list of Jobs
637 * returns: 0 on error
638 * JobId on success and fills in JOB_DBR
640 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
644 for (i=1; i<ua->argc; i++) {
645 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
647 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
648 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
649 jr->JobId = str_to_int64(ua->argv[i]);
654 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
655 bsendmsg(ua, _("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
656 db_strerror(ua->db));
666 for (i=1; i<ua->argc; i++) {
667 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
668 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
670 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
674 if (!select_job_dbr(ua, jr)) { /* try once more */
681 * Implement unique set of prompts
683 void start_prompt(UAContext *ua, const char *msg)
685 if (ua->max_prompts == 0) {
686 ua->max_prompts = 10;
687 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
690 ua->prompt[0] = bstrdup(msg);
694 * Add to prompts -- keeping them unique
696 void add_prompt(UAContext *ua, const char *prompt)
699 if (ua->num_prompts == ua->max_prompts) {
700 ua->max_prompts *= 2;
701 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
704 for (i=1; i < ua->num_prompts; i++) {
705 if (strcmp(ua->prompt[i], prompt) == 0) {
709 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
713 * Display prompts and get user's choice
715 * Returns: -1 on error
716 * index base 0 on success, and choice
717 * is copied to prompt if not NULL
718 * prompt is set to the chosen prompt item string
720 int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt)
723 char pmsg[MAXSTRING];
728 if (ua->num_prompts == 2) {
731 bstrncpy(prompt, ua->prompt[1], max_prompt);
733 bsendmsg(ua, _("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
736 /* If running non-interactive, bail out */
738 bsendmsg(ua, _("Cannot select %s in batch mode.\n"), automsg);
742 // bnet_sig(ua->UA_sock, BNET_START_SELECT);
743 bsendmsg(ua, ua->prompt[0]);
744 for (i=1; i < ua->num_prompts; i++) {
745 bsendmsg(ua, "%6d: %s\n", i, ua->prompt[i]);
747 // bnet_sig(ua->UA_sock, BNET_END_SELECT);
750 /* First item is the prompt string, not the items */
751 if (ua->num_prompts == 1) {
752 bsendmsg(ua, _("Selection is empty!\n"));
753 item = -1; /* list is empty ! */
756 if (ua->num_prompts == 2) {
758 bsendmsg(ua, _("Item 1 selected automatically.\n"));
760 bstrncpy(prompt, ua->prompt[1], max_prompt);
764 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
766 /* Either a . or an @ will get you out of the loop */
767 if (!get_pint(ua, pmsg)) {
768 item = -1; /* error */
769 bsendmsg(ua, _("Selection aborted, nothing done.\n"));
772 item = ua->pint32_val;
773 if (item < 1 || item >= ua->num_prompts) {
774 bsendmsg(ua, _("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
778 bstrncpy(prompt, ua->prompt[item], max_prompt);
784 for (i=0; i < ua->num_prompts; i++) {
788 return item>0 ? item-1 : item;
793 * We scan what the user has entered looking for
794 * storage=<storage-resource>
797 * ? (prompt him with storage list)
798 * <some-error> (prompt him with storage list)
800 * If use_default is set, we assume that any keyword without a value
801 * is the name of the Storage resource wanted.
803 STORE *get_storage_resource(UAContext *ua, bool use_default)
805 char *store_name = NULL;
812 for (i=1; i<ua->argc; i++) {
813 if (use_default && !ua->argv[i]) {
814 /* Ignore slots, scan and barcode(s) keywords */
815 if (strcasecmp("scan", ua->argk[i]) == 0 ||
816 strcasecmp("barcode", ua->argk[i]) == 0 ||
817 strcasecmp("barcodes", ua->argk[i]) == 0 ||
818 strcasecmp("slots", ua->argk[i]) == 0) {
821 /* Default argument is storage */
823 bsendmsg(ua, _("Storage name given twice.\n"));
826 store_name = ua->argk[i];
827 if (*store_name == '?') {
832 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
833 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
834 store_name = ua->argv[i];
837 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
838 jobid = str_to_int64(ua->argv[i]);
840 bsendmsg(ua, _("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
843 if (!(jcr=get_jcr_by_id(jobid))) {
844 bsendmsg(ua, _("JobId %s is not running.\n"), edit_int64(jobid, ed1));
851 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
852 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
854 bsendmsg(ua, _("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
857 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
858 bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]);
864 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
866 bsendmsg(ua, _("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
869 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
870 bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]);
879 if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
883 if (!store && store_name && store_name[0] != 0) {
884 store = (STORE *)GetResWithName(R_STORAGE, store_name);
886 bsendmsg(ua, _("Storage resource \"%s\": not found\n"), store_name);
889 if (store && !acl_access_ok(ua, Storage_ACL, store->hdr.name)) {
892 /* No keywords found, so present a selection list */
894 store = select_storage_resource(ua);
899 /* Get drive that we are working with for this storage */
900 int get_storage_drive(UAContext *ua, STORE *store)
903 /* Get drive for autochanger if possible */
904 i = find_arg_with_value(ua, "drive");
906 drive = atoi(ua->argv[i]);
907 } else if (store && store->autochanger) {
908 /* If our structure is not set ask SD for # drives */
909 if (store->drives == 0) {
910 store->drives = get_num_drives_from_SD(ua);
912 /* If only one drive, default = 0 */
913 if (store->drives == 1) {
916 /* Ask user to enter drive number */
918 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
919 drive = -1; /* None */
921 drive = atoi(ua->cmd);
928 /* Get slot that we are working with for this storage */
929 int get_storage_slot(UAContext *ua, STORE *store)
932 /* Get slot for autochanger if possible */
933 i = find_arg_with_value(ua, "slot");
935 slot = atoi(ua->argv[i]);
936 } else if (store && store->autochanger) {
937 /* Ask user to enter slot number */
939 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
940 slot = -1; /* None */
942 slot = atoi(ua->cmd);
951 * Scan looking for mediatype=
953 * if not found or error, put up selection list
955 * Returns: 0 on error
956 * 1 on success, MediaType is set
958 int get_media_type(UAContext *ua, char *MediaType, int max_media)
963 i = find_arg_with_value(ua, "mediatype");
965 bstrncpy(MediaType, ua->argv[i], max_media);
969 start_prompt(ua, _("Media Types defined in conf file:\n"));
971 foreach_res(store, R_STORAGE) {
972 add_prompt(ua, store->media_type);
975 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
978 bool get_level_from_name(JCR *jcr, const char *level_name)
980 /* Look up level name and pull code */
982 for (int i=0; joblevels[i].level_name; i++) {
983 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
984 jcr->JobLevel = joblevels[i].level;