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->name())) {
164 add_prompt(ua, store->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->name())) {
187 add_prompt(ua, fs->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]);
216 if (ua->gui && !catalog) {
218 catalog = (CAT *)GetNextRes(R_CATALOG, NULL);
221 bsendmsg(ua, _("Could not find a Catalog resource\n"));
223 } else if (!acl_access_ok(ua, Catalog_ACL, catalog->name())) {
224 bsendmsg(ua, _("You must specify a \"use <catalog-name>\" command before continuing.\n"));
230 start_prompt(ua, _("The defined Catalog resources are:\n"));
232 foreach_res(catalog, R_CATALOG) {
233 if (acl_access_ok(ua, Catalog_ACL, catalog->name())) {
234 add_prompt(ua, catalog->name());
238 if (do_prompt(ua, _("Catalog"), _("Select Catalog resource"), name, sizeof(name)) < 0) {
241 catalog = (CAT *)GetResWithName(R_CATALOG, name);
248 * Select a Job resource from prompt list
250 JOB *select_job_resource(UAContext *ua)
252 char name[MAX_NAME_LENGTH];
255 start_prompt(ua, _("The defined Job resources are:\n"));
257 foreach_res(job, R_JOB) {
258 if (acl_access_ok(ua, Job_ACL, job->name())) {
259 add_prompt(ua, job->name());
263 if (do_prompt(ua, _("Job"), _("Select Job resource"), name, sizeof(name)) < 0) {
266 job = (JOB *)GetResWithName(R_JOB, name);
271 * Select a Restore Job resource from prompt list
273 JOB *select_restore_job_resource(UAContext *ua)
275 char name[MAX_NAME_LENGTH];
278 start_prompt(ua, _("The defined Restore Job resources are:\n"));
280 foreach_res(job, R_JOB) {
281 if (job->JobType == JT_RESTORE && acl_access_ok(ua, Job_ACL, job->name())) {
282 add_prompt(ua, job->name());
286 if (do_prompt(ua, _("Job"), _("Select Restore Job"), name, sizeof(name)) < 0) {
289 job = (JOB *)GetResWithName(R_JOB, name);
296 * Select a client resource from prompt list
298 CLIENT *select_client_resource(UAContext *ua)
300 char name[MAX_NAME_LENGTH];
303 start_prompt(ua, _("The defined Client resources are:\n"));
305 foreach_res(client, R_CLIENT) {
306 if (acl_access_ok(ua, Client_ACL, client->name())) {
307 add_prompt(ua, client->name());
311 if (do_prompt(ua, _("Client"), _("Select Client (File daemon) resource"), name, sizeof(name)) < 0) {
314 client = (CLIENT *)GetResWithName(R_CLIENT, name);
319 * Get client resource, start by looking for
320 * client=<client-name>
321 * if we don't find the keyword, we prompt the user.
323 CLIENT *get_client_resource(UAContext *ua)
325 CLIENT *client = NULL;
328 for (i=1; i<ua->argc; i++) {
329 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
330 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
331 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
334 client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
338 bsendmsg(ua, _("Error: Client resource %s does not exist.\n"), ua->argv[i]);
342 return select_client_resource(ua);
345 /* Scan what the user has entered looking for:
347 * client=<client-name>
349 * if error or not found, put up a list of client DBRs
352 * returns: 0 on error
353 * 1 on success and fills in CLIENT_DBR
355 int get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
359 if (cr->Name[0]) { /* If name already supplied */
360 if (db_get_client_record(ua->jcr, ua->db, cr)) {
363 bsendmsg(ua, _("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
365 for (i=1; i<ua->argc; i++) {
366 if ((strcasecmp(ua->argk[i], NT_("client")) == 0 ||
367 strcasecmp(ua->argk[i], NT_("fd")) == 0) && ua->argv[i]) {
368 if (!acl_access_ok(ua, Client_ACL, ua->argv[i])) {
371 bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
372 if (!db_get_client_record(ua->jcr, ua->db, cr)) {
373 bsendmsg(ua, _("Could not find Client \"%s\": ERR=%s"), ua->argv[i],
374 db_strerror(ua->db));
381 if (!select_client_dbr(ua, cr)) { /* try once more by proposing a list */
388 * Select a Client record from the catalog
389 * Returns 1 on success
392 int select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
395 char name[MAX_NAME_LENGTH];
401 if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
402 bsendmsg(ua, _("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
405 if (num_clients <= 0) {
406 bsendmsg(ua, _("No clients defined. You must run a job before using this command.\n"));
410 start_prompt(ua, _("Defined Clients:\n"));
411 for (i=0; i < num_clients; i++) {
412 ocr.ClientId = ids[i];
413 if (!db_get_client_record(ua->jcr, ua->db, &ocr) ||
414 !acl_access_ok(ua, Client_ACL, ocr.Name)) {
417 add_prompt(ua, ocr.Name);
420 if (do_prompt(ua, _("Client"), _("Select the Client"), name, sizeof(name)) < 0) {
423 memset(&ocr, 0, sizeof(ocr));
424 bstrncpy(ocr.Name, name, sizeof(ocr.Name));
426 if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
427 bsendmsg(ua, _("Could not find Client \"%s\": ERR=%s"), name, db_strerror(ua->db));
430 memcpy(cr, &ocr, sizeof(ocr));
436 /* Scan what the user has entered looking for:
440 * if error or not found, put up a list of pool DBRs
443 * returns: false on error
444 * true on success and fills in POOL_DBR
446 bool get_pool_dbr(UAContext *ua, POOL_DBR *pr)
448 if (pr->Name[0]) { /* If name already supplied */
449 if (db_get_pool_record(ua->jcr, ua->db, pr) &&
450 acl_access_ok(ua, Pool_ACL, pr->Name)) {
453 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), pr->Name, db_strerror(ua->db));
455 if (!select_pool_dbr(ua, pr)) { /* try once more */
462 * Select a Pool record from the catalog
464 bool select_pool_dbr(UAContext *ua, POOL_DBR *pr)
467 char name[MAX_NAME_LENGTH];
471 for (i=1; i<ua->argc; i++) {
472 if (strcasecmp(ua->argk[i], NT_("pool")) == 0 && ua->argv[i] &&
473 acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
474 bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
475 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
476 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), ua->argv[i],
477 db_strerror(ua->db));
486 if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
487 bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
490 if (num_pools <= 0) {
491 bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n"));
495 start_prompt(ua, _("Defined Pools:\n"));
496 for (i=0; i < num_pools; i++) {
498 if (!db_get_pool_record(ua->jcr, ua->db, &opr) ||
499 !acl_access_ok(ua, Pool_ACL, opr.Name)) {
502 add_prompt(ua, opr.Name);
505 if (do_prompt(ua, _("Pool"), _("Select the Pool"), name, sizeof(name)) < 0) {
508 memset(&opr, 0, sizeof(opr));
509 bstrncpy(opr.Name, name, sizeof(opr.Name));
511 if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
512 bsendmsg(ua, _("Could not find Pool \"%s\": ERR=%s"), name, db_strerror(ua->db));
515 memcpy(pr, &opr, sizeof(opr));
520 * Select a Pool and a Media (Volume) record from the database
522 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
525 if (!select_media_dbr(ua, mr)) {
528 memset(pr, 0, sizeof(POOL_DBR));
529 pr->PoolId = mr->PoolId;
530 if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
531 bsendmsg(ua, "%s", db_strerror(ua->db));
534 if (!acl_access_ok(ua, Pool_ACL, pr->Name)) {
535 bsendmsg(ua, _("No access to Pool \"%s\"\n"), pr->Name);
541 /* Select a Media (Volume) record from the database */
542 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
546 memset(mr, 0, sizeof(MEDIA_DBR));
548 i = find_arg_with_value(ua, "volume");
550 bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
552 if (mr->VolumeName[0] == 0) {
554 memset(&pr, 0, sizeof(pr));
555 /* Get the pool from pool=<pool-name> */
556 if (!get_pool_dbr(ua, &pr)) {
559 mr->PoolId = pr.PoolId;
560 db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, HORZ_LIST);
561 if (!get_cmd(ua, _("Enter MediaId or Volume name: "))) {
564 if (is_a_number(ua->cmd)) {
565 mr->MediaId = str_to_int64(ua->cmd);
567 bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
571 if (!db_get_media_record(ua->jcr, ua->db, mr)) {
572 bsendmsg(ua, "%s", db_strerror(ua->db));
580 * Select a pool resource from prompt list
582 POOL *select_pool_resource(UAContext *ua)
584 char name[MAX_NAME_LENGTH];
587 start_prompt(ua, _("The defined Pool resources are:\n"));
589 foreach_res(pool, R_POOL) {
590 if (acl_access_ok(ua, Pool_ACL, pool->name())) {
591 add_prompt(ua, pool->name());
595 if (do_prompt(ua, _("Pool"), _("Select Pool resource"), name, sizeof(name)) < 0) {
598 pool = (POOL *)GetResWithName(R_POOL, name);
604 * If you are thinking about using it, you
605 * probably want to use select_pool_dbr()
606 * or get_pool_dbr() above.
608 POOL *get_pool_resource(UAContext *ua)
613 i = find_arg_with_value(ua, "pool");
614 if (i >= 0 && acl_access_ok(ua, Pool_ACL, ua->argv[i])) {
615 pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
619 bsendmsg(ua, _("Error: Pool resource \"%s\" does not exist.\n"), ua->argv[i]);
621 return select_pool_resource(ua);
625 * List all jobs and ask user to select one
627 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
629 db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, HORZ_LIST);
630 if (!get_pint(ua, _("Enter the JobId to select: "))) {
633 jr->JobId = ua->int64_val;
634 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
635 bsendmsg(ua, "%s", db_strerror(ua->db));
643 /* Scan what the user has entered looking for:
647 * if error or not found, put up a list of Jobs
650 * returns: 0 on error
651 * JobId on success and fills in JOB_DBR
653 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
657 for (i=1; i<ua->argc; i++) {
658 if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0 && ua->argv[i]) {
660 bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
661 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0 && ua->argv[i]) {
662 jr->JobId = str_to_int64(ua->argv[i]);
667 if (!db_get_job_record(ua->jcr, ua->db, jr)) {
668 bsendmsg(ua, _("Could not find Job \"%s\": ERR=%s"), ua->argv[i],
669 db_strerror(ua->db));
679 for (i=1; i<ua->argc; i++) {
680 if ((strcasecmp(ua->argk[i], NT_("jobname")) == 0 ||
681 strcasecmp(ua->argk[i], NT_("job")) == 0) && ua->argv[i]) {
683 bstrncpy(jr->Name, ua->argv[i], sizeof(jr->Name));
687 if (!select_job_dbr(ua, jr)) { /* try once more */
694 * Implement unique set of prompts
696 void start_prompt(UAContext *ua, const char *msg)
698 if (ua->max_prompts == 0) {
699 ua->max_prompts = 10;
700 ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
703 ua->prompt[0] = bstrdup(msg);
707 * Add to prompts -- keeping them unique
709 void add_prompt(UAContext *ua, const char *prompt)
712 if (ua->num_prompts == ua->max_prompts) {
713 ua->max_prompts *= 2;
714 ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
717 for (i=1; i < ua->num_prompts; i++) {
718 if (strcmp(ua->prompt[i], prompt) == 0) {
722 ua->prompt[ua->num_prompts++] = bstrdup(prompt);
726 * Display prompts and get user's choice
728 * Returns: -1 on error
729 * index base 0 on success, and choice
730 * is copied to prompt if not NULL
731 * prompt is set to the chosen prompt item string
733 int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt)
736 char pmsg[MAXSTRING];
741 if (ua->num_prompts == 2) {
744 bstrncpy(prompt, ua->prompt[1], max_prompt);
746 bsendmsg(ua, _("Automatically selected %s: %s\n"), automsg, ua->prompt[1]);
749 /* If running non-interactive, bail out */
751 bsendmsg(ua, _("Cannot select %s in batch mode.\n"), automsg);
755 // bnet_sig(ua->UA_sock, BNET_START_SELECT);
756 bsendmsg(ua, ua->prompt[0]);
757 for (i=1; i < ua->num_prompts; i++) {
758 bsendmsg(ua, "%6d: %s\n", i, ua->prompt[i]);
760 // bnet_sig(ua->UA_sock, BNET_END_SELECT);
763 /* First item is the prompt string, not the items */
764 if (ua->num_prompts == 1) {
765 bsendmsg(ua, _("Selection list for \"%s\" is empty!\n"), automsg);
766 item = -1; /* list is empty ! */
769 if (ua->num_prompts == 2) {
771 bsendmsg(ua, _("Item 1 selected automatically.\n"));
773 bstrncpy(prompt, ua->prompt[1], max_prompt);
777 sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
779 /* Either a . or an @ will get you out of the loop */
780 if (!get_pint(ua, pmsg)) {
781 item = -1; /* error */
782 bsendmsg(ua, _("Selection aborted, nothing done.\n"));
785 item = ua->pint32_val;
786 if (item < 1 || item >= ua->num_prompts) {
787 bsendmsg(ua, _("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
791 bstrncpy(prompt, ua->prompt[item], max_prompt);
797 for (i=0; i < ua->num_prompts; i++) {
801 return item>0 ? item-1 : item;
806 * We scan what the user has entered looking for
807 * storage=<storage-resource>
810 * ? (prompt him with storage list)
811 * <some-error> (prompt him with storage list)
813 * If use_default is set, we assume that any keyword without a value
814 * is the name of the Storage resource wanted.
816 STORE *get_storage_resource(UAContext *ua, bool use_default)
818 char *store_name = NULL;
825 for (i=1; i<ua->argc; i++) {
826 if (use_default && !ua->argv[i]) {
827 /* Ignore slots, scan and barcode(s) keywords */
828 if (strcasecmp("scan", ua->argk[i]) == 0 ||
829 strcasecmp("barcode", ua->argk[i]) == 0 ||
830 strcasecmp("barcodes", ua->argk[i]) == 0 ||
831 strcasecmp("slots", ua->argk[i]) == 0) {
834 /* Default argument is storage */
836 bsendmsg(ua, _("Storage name given twice.\n"));
839 store_name = ua->argk[i];
840 if (*store_name == '?') {
845 if (strcasecmp(ua->argk[i], NT_("storage")) == 0 ||
846 strcasecmp(ua->argk[i], NT_("sd")) == 0) {
847 store_name = ua->argv[i];
850 } else if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
851 jobid = str_to_int64(ua->argv[i]);
853 bsendmsg(ua, _("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
856 if (!(jcr=get_jcr_by_id(jobid))) {
857 bsendmsg(ua, _("JobId %s is not running.\n"), edit_int64(jobid, ed1));
864 } else if (strcasecmp(ua->argk[i], NT_("job")) == 0 ||
865 strcasecmp(ua->argk[i], NT_("jobname")) == 0) {
867 bsendmsg(ua, _("Expecting job=xxx, got: %s.\n"), ua->argk[i]);
870 if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
871 bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]);
877 } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
879 bsendmsg(ua, _("Expecting ujobid=xxx, got: %s.\n"), ua->argk[i]);
882 if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
883 bsendmsg(ua, _("Job \"%s\" is not running.\n"), ua->argv[i]);
892 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
896 if (!store && store_name && store_name[0] != 0) {
897 store = (STORE *)GetResWithName(R_STORAGE, store_name);
899 bsendmsg(ua, _("Storage resource \"%s\": not found\n"), store_name);
902 if (store && !acl_access_ok(ua, Storage_ACL, store->name())) {
905 /* No keywords found, so present a selection list */
907 store = select_storage_resource(ua);
912 /* Get drive that we are working with for this storage */
913 int get_storage_drive(UAContext *ua, STORE *store)
916 /* Get drive for autochanger if possible */
917 i = find_arg_with_value(ua, "drive");
919 drive = atoi(ua->argv[i]);
920 } else if (store && store->autochanger) {
921 /* If our structure is not set ask SD for # drives */
922 if (store->drives == 0) {
923 store->drives = get_num_drives_from_SD(ua);
925 /* If only one drive, default = 0 */
926 if (store->drives == 1) {
929 /* Ask user to enter drive number */
931 if (!get_cmd(ua, _("Enter autochanger drive[0]: "))) {
932 drive = -1; /* None */
934 drive = atoi(ua->cmd);
941 /* Get slot that we are working with for this storage */
942 int get_storage_slot(UAContext *ua, STORE *store)
945 /* Get slot for autochanger if possible */
946 i = find_arg_with_value(ua, "slot");
948 slot = atoi(ua->argv[i]);
949 } else if (store && store->autochanger) {
950 /* Ask user to enter slot number */
952 if (!get_cmd(ua, _("Enter autochanger slot: "))) {
953 slot = -1; /* None */
955 slot = atoi(ua->cmd);
964 * Scan looking for mediatype=
966 * if not found or error, put up selection list
968 * Returns: 0 on error
969 * 1 on success, MediaType is set
971 int get_media_type(UAContext *ua, char *MediaType, int max_media)
976 i = find_arg_with_value(ua, "mediatype");
978 bstrncpy(MediaType, ua->argv[i], max_media);
982 start_prompt(ua, _("Media Types defined in conf file:\n"));
984 foreach_res(store, R_STORAGE) {
985 add_prompt(ua, store->media_type);
988 return (do_prompt(ua, _("Media Type"), _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
991 bool get_level_from_name(JCR *jcr, const char *level_name)
993 /* Look up level name and pull code */
995 for (int i=0; joblevels[i].level_name; i++) {
996 if (strcasecmp(level_name, joblevels[i].level_name) == 0) {
997 jcr->JobLevel = joblevels[i].level;