]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_select.c
c34ccc4657fc5eea14faa0e271f0ee630d2b0ea6
[bacula/bacula] / bacula / src / dird / ua_select.c
1 /*
2  *
3  *   Bacula Director -- User Agent Prompt and Selection code
4  *
5  *     Kern Sibbald, October MMI
6  *
7  *   Version  $Id$
8  */
9
10 /*
11    Copyright (C) 2000-2003 Kern Sibbald and John Walker
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32
33 /* Imported variables */
34
35
36 /*
37  * Confirm a retention period
38  */
39 int confirm_retention(UAContext *ua, utime_t *ret, char *msg)
40 {
41    char ed1[30];
42
43    for ( ;; ) {
44        bsendmsg(ua, _("The current %s retention period is: %s\n"), 
45           msg, edit_utime(*ret, ed1));
46        if (!get_cmd(ua, _("Continue? (yes/mod/no): "))) {
47           return 0;
48        }
49        if (strcasecmp(ua->cmd, _("mod")) == 0) {
50           if (!get_cmd(ua, _("Enter new retention period: "))) {
51              return 0;
52           }
53           if (!duration_to_utime(ua->cmd, ret)) {
54              bsendmsg(ua, _("Invalid period.\n"));
55              continue;
56           }
57           continue;
58        }
59        if (strcasecmp(ua->cmd, _("yes")) == 0) {
60           break;
61        }
62     }
63     return 1;
64 }
65
66 /* 
67  * Given a list of keywords, find the first one
68  *  that is in the argument list.
69  * Returns: -1 if not found
70  *          index into list (base 0) on success
71  */
72 int find_arg_keyword(UAContext *ua, char **list)
73 {
74    int i, j;
75    for (i=1; i<ua->argc; i++) {
76       for(j=0; list[j]; j++) {
77          if (strcasecmp(_(list[j]), ua->argk[i]) == 0) {
78             return j;
79          }
80       }
81    }
82    return -1;
83 }
84
85 /* 
86  * Given a single keyword, find it in the argument list.
87  * Returns: -1 if not found
88  *           list index (base 0) on success
89  */
90 int find_arg(UAContext *ua, char *keyword)
91 {
92    for (int i=1; i<ua->argc; i++) {
93       if (strcasecmp(keyword, ua->argk[i]) == 0) {
94          return i;
95       }
96    }
97    return -1;
98 }
99
100
101 /* 
102  * Given a list of keywords, prompt the user 
103  * to choose one.
104  *
105  * Returns: -1 on failure
106  *          index into list (base 0) on success
107  */
108 int do_keyword_prompt(UAContext *ua, char *msg, char **list)
109 {
110    int i;
111    start_prompt(ua, _("You have the following choices:\n"));
112    for (i=0; list[i]; i++) {
113       add_prompt(ua, list[i]);
114    }
115    return do_prompt(ua, msg, NULL, 0);
116 }
117
118
119 /* 
120  * Select a Storage resource from prompt list
121  */
122 STORE *select_storage_resource(UAContext *ua)
123 {
124    char name[MAX_NAME_LENGTH];    
125    STORE *store = NULL;
126
127    start_prompt(ua, _("The defined Storage resources are:\n"));
128    LockRes();
129    while ((store = (STORE *)GetNextRes(R_STORAGE, (RES *)store))) {
130       add_prompt(ua, store->hdr.name);
131    }
132    UnlockRes();
133    do_prompt(ua, _("Select Storage resource"), name, sizeof(name));
134    store = (STORE *)GetResWithName(R_STORAGE, name);
135    return store;
136 }
137
138 /* 
139  * Select a FileSet resource from prompt list
140  */
141 FILESET *select_fileset_resource(UAContext *ua)
142 {
143    char name[MAX_NAME_LENGTH];    
144    FILESET *fs = NULL;
145
146    start_prompt(ua, _("The defined FileSet resources are:\n"));
147    LockRes();
148    while ((fs = (FILESET *)GetNextRes(R_FILESET, (RES *)fs))) {
149       add_prompt(ua, fs->hdr.name);
150    }
151    UnlockRes();
152    do_prompt(ua, _("Select FileSet resource"), name, sizeof(name));
153    fs = (FILESET *)GetResWithName(R_FILESET, name);
154    return fs;
155 }
156
157
158 /* 
159  * Get a catalog resource from prompt list
160  */
161 CAT *get_catalog_resource(UAContext *ua)
162 {
163    char name[MAX_NAME_LENGTH];    
164    CAT *catalog = NULL;
165    int i;
166
167    for (i=1; i<ua->argc; i++) {
168       if (strcasecmp(ua->argk[i], _("catalog")) == 0 && ua->argv[i]) {
169          catalog = (CAT *)GetResWithName(R_CATALOG, ua->argv[i]);
170          break;
171       }
172    }
173    if (!catalog) {
174       start_prompt(ua, _("The defined Catalog resources are:\n"));
175       LockRes();
176       while ((catalog = (CAT *)GetNextRes(R_CATALOG, (RES *)catalog))) {
177          add_prompt(ua, catalog->hdr.name);
178       }
179       UnlockRes();
180       do_prompt(ua, _("Select Catalog resource"), name, sizeof(name));
181       catalog = (CAT *)GetResWithName(R_CATALOG, name);
182    }
183    return catalog;
184 }
185
186
187 /* 
188  * Select a Job resource from prompt list
189  */
190 JOB *select_job_resource(UAContext *ua)
191 {
192    char name[MAX_NAME_LENGTH];    
193    JOB *job = NULL;
194
195    start_prompt(ua, _("The defined Job resources are:\n"));
196    LockRes();
197    while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
198       add_prompt(ua, job->hdr.name);
199    }
200    UnlockRes();
201    do_prompt(ua, _("Select Job resource"), name, sizeof(name));
202    job = (JOB *)GetResWithName(R_JOB, name);
203    return job;
204 }
205
206 /* 
207  * Select a Restore Job resource from prompt list
208  */
209 JOB *select_restore_job_resource(UAContext *ua)
210 {
211    char name[MAX_NAME_LENGTH];    
212    JOB *job = NULL;
213
214    start_prompt(ua, _("The defined Restore Job resources are:\n"));
215    LockRes();
216    while ( (job = (JOB *)GetNextRes(R_JOB, (RES *)job)) ) {
217       if (job->JobType == JT_RESTORE) {
218          add_prompt(ua, job->hdr.name);
219       }
220    }
221    UnlockRes();
222    do_prompt(ua, _("Select Restore Job"), name, sizeof(name));
223    job = (JOB *)GetResWithName(R_JOB, name);
224    return job;
225 }
226
227
228
229 /* 
230  * Select a client resource from prompt list
231  */
232 CLIENT *select_client_resource(UAContext *ua)
233 {
234    char name[MAX_NAME_LENGTH];    
235    CLIENT *client = NULL;
236
237    start_prompt(ua, _("The defined Client resources are:\n"));
238    LockRes();
239    while ( (client = (CLIENT *)GetNextRes(R_CLIENT, (RES *)client)) ) {
240       add_prompt(ua, client->hdr.name);
241    }
242    UnlockRes();
243    do_prompt(ua, _("Select Client (File daemon) resource"), name, sizeof(name));
244    client = (CLIENT *)GetResWithName(R_CLIENT, name);
245    return client;
246 }
247
248 /*
249  *  Get client resource, start by looking for
250  *   client=<client-name>
251  *  if we don't find the keyword, we prompt the user.
252  */
253 CLIENT *get_client_resource(UAContext *ua)
254 {
255    CLIENT *client = NULL;
256    int i;
257    
258    for (i=1; i<ua->argc; i++) {
259       if (strcasecmp(ua->argk[i], _("client")) == 0 && ua->argv[i]) {
260          client = (CLIENT *)GetResWithName(R_CLIENT, ua->argv[i]);
261          if (client) {
262             return client;
263          }
264          bsendmsg(ua, _("Error: Client resource %s does not exist.\n"), ua->argv[i]);
265          break;
266       }
267    }
268    return select_client_resource(ua);
269 }
270
271 /* Scan what the user has entered looking for:
272  * 
273  *  client=<client-name>
274  *
275  *  if error or not found, put up a list of client DBRs
276  *  to choose from.
277  *
278  *   returns: 0 on error
279  *            1 on success and fills in CLIENT_DBR
280  */
281 int get_client_dbr(UAContext *ua, CLIENT_DBR *cr)
282 {
283    int i;
284
285    if (cr->Name[0]) {                 /* If name already supplied */
286       if (db_get_client_record(ua->jcr, ua->db, cr)) {
287          return 1;
288       }
289       bsendmsg(ua, _("Could not find Client %s: ERR=%s"), cr->Name, db_strerror(ua->db));
290    }
291    for (i=1; i<ua->argc; i++) {
292       if (strcasecmp(ua->argk[i], _("client")) == 0 && ua->argv[i]) {
293          bstrncpy(cr->Name, ua->argv[i], sizeof(cr->Name));
294          if (!db_get_client_record(ua->jcr, ua->db, cr)) {
295             bsendmsg(ua, _("Could not find Client %s: ERR=%s"), ua->argv[i],
296                      db_strerror(ua->db));
297             cr->ClientId = 0;
298             break;
299          }
300          return 1;
301       }
302    }
303    if (!select_client_dbr(ua, cr)) {  /* try once more by proposing a list */
304       return 0;
305    }
306    return 1;
307 }
308
309 /*
310  * Select a Client record from the catalog
311  *  Returns 1 on success
312  *          0 on failure
313  */
314 int select_client_dbr(UAContext *ua, CLIENT_DBR *cr)
315 {
316    CLIENT_DBR ocr;
317    char name[MAX_NAME_LENGTH];
318    int num_clients, i;
319    uint32_t *ids; 
320
321
322    cr->ClientId = 0;
323    if (!db_get_client_ids(ua->jcr, ua->db, &num_clients, &ids)) {
324       bsendmsg(ua, _("Error obtaining client ids. ERR=%s\n"), db_strerror(ua->db));
325       return 0;
326    }
327    if (num_clients <= 0) {
328       bsendmsg(ua, _("No clients defined. Run a job to create one.\n"));
329       return 0;
330    }
331      
332    start_prompt(ua, _("Defined Clients:\n"));
333    for (i=0; i < num_clients; i++) {
334       ocr.ClientId = ids[i];
335       if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
336          continue;
337       }
338       add_prompt(ua, ocr.Name);
339    }
340    free(ids);
341    if (do_prompt(ua, _("Select the Client"), name, sizeof(name)) < 0) {
342       return 0;
343    }
344    memset(&ocr, 0, sizeof(ocr));
345    bstrncpy(ocr.Name, name, sizeof(ocr.Name));
346
347    if (!db_get_client_record(ua->jcr, ua->db, &ocr)) {
348       bsendmsg(ua, _("Could not find Client %s: ERR=%s"), name, db_strerror(ua->db));
349       return 0;
350    }
351    memcpy(cr, &ocr, sizeof(ocr));
352    return 1;
353 }
354
355
356
357 /* Scan what the user has entered looking for:
358  * 
359  *  pool=<pool-name>   
360  *
361  *  if error or not found, put up a list of pool DBRs
362  *  to choose from.
363  *
364  *   returns: 0 on error
365  *            1 on success and fills in POOL_DBR
366  */
367 int get_pool_dbr(UAContext *ua, POOL_DBR *pr)
368 {
369    if (pr->Name[0]) {                 /* If name already supplied */
370       if (db_get_pool_record(ua->jcr, ua->db, pr)) {
371          return pr->PoolId;
372       }
373       bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), pr->Name, db_strerror(ua->db));
374    }
375    if (!select_pool_dbr(ua, pr)) {  /* try once more */
376       return 0;
377    }
378    return 1;
379 }
380
381 /*
382  * Select a Pool record from the catalog
383  */
384 int select_pool_dbr(UAContext *ua, POOL_DBR *pr)
385 {
386    POOL_DBR opr;
387    char name[MAX_NAME_LENGTH];
388    int num_pools, i;
389    uint32_t *ids; 
390
391    for (i=1; i<ua->argc; i++) {
392       if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) {
393          bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
394          if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
395             bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), ua->argv[i],
396                      db_strerror(ua->db));
397             pr->PoolId = 0;
398             break;
399          }
400          return 1;
401       }
402    }
403
404    pr->PoolId = 0;
405    if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
406       bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
407       return 0;
408    }
409    if (num_pools <= 0) {
410       bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n"));
411       return 0;
412    }
413      
414    start_prompt(ua, _("Defined Pools:\n"));
415    for (i=0; i < num_pools; i++) {
416       opr.PoolId = ids[i];
417       if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
418          continue;
419       }
420       add_prompt(ua, opr.Name);
421    }
422    free(ids);
423    if (do_prompt(ua, _("Select the Pool"), name, sizeof(name)) < 0) {
424       return 0;
425    }
426    memset(&opr, 0, sizeof(opr));
427    bstrncpy(opr.Name, name, sizeof(opr.Name));
428
429    if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
430       bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), name, db_strerror(ua->db));
431       return 0;
432    }
433    memcpy(pr, &opr, sizeof(opr));
434    return 1;
435 }
436
437 /*
438  * Select a Pool and a Media (Volume) record from the database
439  */
440 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
441 {
442
443    if (!select_media_dbr(ua, mr)) {
444       return 0;
445    }
446    memset(pr, 0, sizeof(POOL_DBR));
447    pr->PoolId = mr->PoolId;
448    if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
449       bsendmsg(ua, "%s", db_strerror(ua->db));
450       return 0;
451    }
452    return 1;
453 }
454
455 /* Select a Media (Volume) record from the database */
456 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
457 {
458    int i;
459
460    memset(mr, 0, sizeof(MEDIA_DBR));
461
462    i = find_arg(ua, "volume");
463    if (i >= 0 && ua->argv[i]) {
464       bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
465    }
466    if (mr->VolumeName[0] == 0) {
467       POOL_DBR pr;
468       memset(&pr, 0, sizeof(pr));
469       /* Get the pool from pool=<pool-name> */
470       if (!get_pool_dbr(ua, &pr)) {
471          return 0;
472       }
473       mr->PoolId = pr.PoolId;
474       db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, 0);
475       if (!get_cmd(ua, _("Enter MediaId or Volume name: "))) {
476          return 0;
477       }
478       if (is_a_number(ua->cmd)) {
479          mr->MediaId = atoi(ua->cmd);
480       } else {
481          bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
482       }
483    }
484
485    if (!db_get_media_record(ua->jcr, ua->db, mr)) {
486       bsendmsg(ua, "%s", db_strerror(ua->db));
487       return 0;
488    }
489    return 1;
490 }
491
492
493 /* 
494  * Select a pool resource from prompt list
495  */
496 POOL *select_pool_resource(UAContext *ua)
497 {
498    char name[MAX_NAME_LENGTH];    
499    POOL *pool = NULL;
500
501    start_prompt(ua, _("The defined Pool resources are:\n"));
502    LockRes();
503    while ((pool = (POOL *)GetNextRes(R_POOL, (RES *)pool))) {
504       add_prompt(ua, pool->hdr.name);
505    }
506    UnlockRes();
507    do_prompt(ua, _("Select Pool resource"), name, sizeof(name));
508    pool = (POOL *)GetResWithName(R_POOL, name);
509    return pool;
510 }
511
512
513 /*
514  *  If you are thinking about using it, you
515  *  probably want to use select_pool_dbr() 
516  *  or get_pool_dbr() above.
517  */
518 POOL *get_pool_resource(UAContext *ua)
519 {
520    POOL *pool = NULL;
521    int i;
522    
523    for (i=1; i<ua->argc; i++) {
524       if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) {
525          pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
526          if (pool) {
527             return pool;
528          }
529          bsendmsg(ua, _("Error: Pool resource %s does not exist.\n"), ua->argv[i]);
530          break;
531       }
532    }
533    return select_pool_resource(ua);
534 }
535
536 /*
537  * List all jobs and ask user to select one
538  */
539 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
540 {
541    db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, 0);
542    if (!get_cmd(ua, _("Enter the JobId to select: "))) {
543       return 0;
544    }
545    jr->JobId = atoi(ua->cmd);
546    if (!db_get_job_record(ua->jcr, ua->db, jr)) {
547       bsendmsg(ua, "%s", db_strerror(ua->db));
548       return 0;
549    }
550    return jr->JobId;
551
552 }
553
554
555 /* Scan what the user has entered looking for:
556  * 
557  *  jobid=nn
558  *
559  *  if error or not found, put up a list of Jobs
560  *  to choose from.
561  *
562  *   returns: 0 on error
563  *            JobId on success and fills in JOB_DBR
564  */
565 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
566 {
567    int i;
568
569    for (i=1; i<ua->argc; i++) {
570       if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
571          jr->JobId = 0;
572          bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
573       } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) {
574          jr->JobId = atoi(ua->argv[i]);
575       } else {
576          continue;
577       }
578       if (!db_get_job_record(ua->jcr, ua->db, jr)) {
579          bsendmsg(ua, _("Could not find Job %s: ERR=%s"), ua->argv[i],
580                   db_strerror(ua->db));
581          jr->JobId = 0;
582          break;
583       }
584       return jr->JobId;
585    }
586
587    if (!select_job_dbr(ua, jr)) {  /* try once more */
588       return 0;
589    }
590    return jr->JobId;
591 }
592
593 /*
594  * Implement unique set of prompts 
595  */
596 void start_prompt(UAContext *ua, char *msg)
597 {
598   if (ua->max_prompts == 0) {
599      ua->max_prompts = 10;
600      ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
601   }
602   ua->num_prompts = 1;
603   ua->prompt[0] = bstrdup(msg);
604 }
605
606 /*
607  * Add to prompts -- keeping them unique 
608  */
609 void add_prompt(UAContext *ua, char *prompt)
610 {
611    int i;
612    if (ua->num_prompts == ua->max_prompts) {
613       ua->max_prompts *= 2;
614       ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
615          ua->max_prompts);
616     }
617     for (i=1; i < ua->num_prompts; i++) {
618        if (strcmp(ua->prompt[i], prompt) == 0) {
619           return;
620        }
621     }
622     ua->prompt[ua->num_prompts++] = bstrdup(prompt);
623 }
624
625 /*
626  * Display prompts and get user's choice
627  *
628  *  Returns: -1 on error
629  *            index base 0 on success, and choice
630  *               is copied to prompt if not NULL
631  */
632 int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt)
633 {
634    int i, item;
635    char pmsg[MAXSTRING];
636
637    bsendmsg(ua, ua->prompt[0]);
638    for (i=1; i < ua->num_prompts; i++) {
639       bsendmsg(ua, "%6d: %s\n", i, ua->prompt[i]);
640    }
641
642    if (prompt) {
643       *prompt = 0;
644    }
645
646    for ( ;; ) {
647       /* First item is the prompt string, not the items */
648       if (ua->num_prompts == 1) { 
649          bsendmsg(ua, _("Selection is empty!\n"));
650          item = 0;                    /* list is empty ! */
651          break;
652       }
653       if (ua->num_prompts == 2) {
654          item = 1;
655          bsendmsg(ua, _("Item 1 selected automatically.\n"));
656          if (prompt) {
657             bstrncpy(prompt, ua->prompt[1], max_prompt);
658          }
659          break;
660       } else {
661          sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
662       }
663       /* Either a . or an @ will get you out of the loop */
664       if (!get_cmd(ua, pmsg) || *ua->cmd == '.' || *ua->cmd == '@') {
665          item = -1;                   /* error */
666          bsendmsg(ua, _("Selection aborted, nothing done.\n"));
667          break;
668       }
669       item = atoi(ua->cmd);
670       if (item < 1 || item >= ua->num_prompts) {
671          bsendmsg(ua, _("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
672          continue;
673       }
674       if (prompt) {
675          bstrncpy(prompt, ua->prompt[item], max_prompt);
676       }
677       break;
678    }
679                               
680    for (i=0; i < ua->num_prompts; i++) {
681       free(ua->prompt[i]);
682    }
683    ua->num_prompts = 0;
684    return item - 1;
685 }
686
687
688 /*
689  * We scan what the user has entered looking for
690  *    storage=<storage-resource>
691  *    job=<job_name>
692  *    jobid=<jobid>
693  *    ?              (prompt him with storage list)
694  *    <some-error>   (prompt him with storage list)
695  *
696  * If use_default is set, we assume that any keyword without a value
697  *   is the name of the Storage resource wanted.
698  */
699 STORE *get_storage_resource(UAContext *ua, int use_default)
700 {
701    char *store_name = NULL;
702    STORE *store = NULL;
703    int jobid;
704    JCR *jcr;
705    int i;
706       
707
708    for (i=1; i<ua->argc; i++) {
709       if (use_default && !ua->argv[i]) {
710          /* Default argument is storage */
711          if (store_name) {
712             bsendmsg(ua, _("Storage name given twice.\n"));
713             return NULL;
714          }
715          /* Ignore barcode(s) keywords */
716          if (strncasecmp("barcode", ua->argk[i], 7) == 0) {
717             continue;
718          }
719          store_name = ua->argk[i];
720          if (*store_name == '?') {
721             *store_name = 0;
722             break;
723          }
724       } else {
725          if (strcasecmp(ua->argk[i], _("storage")) == 0) {
726             store_name = ua->argv[i];
727             break;
728
729          } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
730             jobid = atoi(ua->argv[i]);
731             if (jobid <= 0) {
732                bsendmsg(ua, _("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
733                return NULL;
734             }
735             if (!(jcr=get_jcr_by_id(jobid))) {
736                bsendmsg(ua, _("JobId %d is not running.\n"), jobid);
737                return NULL;
738             }
739             store = jcr->store;
740             free_jcr(jcr);
741             break;
742
743          } else if (strcasecmp(ua->argk[i], _("job")) == 0) {
744             if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
745                bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]);
746                return NULL;
747             }
748             store = jcr->store;
749             free_jcr(jcr);
750             break;
751         }
752       }
753    }
754
755    if (!store && store_name) {
756       store = (STORE *)GetResWithName(R_STORAGE, store_name);
757       if (!store) {
758          bsendmsg(ua, "Storage resource %s: not found\n", store_name);
759       }
760    }
761    /* No keywords found, so present a selection list */
762    if (!store) {
763       store = select_storage_resource(ua);
764    }
765    return store;
766 }
767
768
769 /*
770  * Scan looking for mediatype= 
771  *
772  *  if not found or error, put up selection list
773  *
774  *  Returns: 0 on error
775  *           1 on success, MediaType is set
776  */
777 int get_media_type(UAContext *ua, char *MediaType, int max_media)
778 {
779    STORE *store;
780    int i;
781
782    i = find_arg(ua, "mediatype");
783    if (i >= 0 && ua->argv[i]) {
784       bstrncpy(MediaType, ua->argv[i], max_media);
785       return 1;
786    }
787
788    start_prompt(ua, _("Media Types defined in conf file:\n"));
789    LockRes();
790    for (store = NULL; (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)); ) {
791       add_prompt(ua, store->media_type);
792    }
793    UnlockRes();
794    return (do_prompt(ua, _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
795 }