]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_select.c
Doc, Vol name scan, misc
[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    int i;
370
371    if (pr->Name[0]) {                 /* If name already supplied */
372       if (db_get_pool_record(ua->jcr, ua->db, pr)) {
373          return pr->PoolId;
374       }
375       bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), pr->Name, db_strerror(ua->db));
376    }
377    for (i=1; i<ua->argc; i++) {
378       if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) {
379          bstrncpy(pr->Name, ua->argv[i], sizeof(pr->Name));
380          if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
381             bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), ua->argv[i],
382                      db_strerror(ua->db));
383             pr->PoolId = 0;
384             break;
385          }
386          return pr->PoolId;
387       }
388    }
389    if (!select_pool_dbr(ua, pr)) {  /* try once more */
390       return 0;
391    }
392    return 1;
393 }
394
395 /*
396  * Select a Pool record from the catalog
397  */
398 int select_pool_dbr(UAContext *ua, POOL_DBR *pr)
399 {
400    POOL_DBR opr;
401    char name[MAX_NAME_LENGTH];
402    int num_pools, i;
403    uint32_t *ids; 
404
405
406    pr->PoolId = 0;
407    if (!db_get_pool_ids(ua->jcr, ua->db, &num_pools, &ids)) {
408       bsendmsg(ua, _("Error obtaining pool ids. ERR=%s\n"), db_strerror(ua->db));
409       return 0;
410    }
411    if (num_pools <= 0) {
412       bsendmsg(ua, _("No pools defined. Use the \"create\" command to create one.\n"));
413       return 0;
414    }
415      
416    start_prompt(ua, _("Defined Pools:\n"));
417    for (i=0; i < num_pools; i++) {
418       opr.PoolId = ids[i];
419       if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
420          continue;
421       }
422       add_prompt(ua, opr.Name);
423    }
424    free(ids);
425    if (do_prompt(ua, _("Select the Pool"), name, sizeof(name)) < 0) {
426       return 0;
427    }
428    memset(&opr, 0, sizeof(opr));
429    bstrncpy(opr.Name, name, sizeof(opr.Name));
430
431    if (!db_get_pool_record(ua->jcr, ua->db, &opr)) {
432       bsendmsg(ua, _("Could not find Pool %s: ERR=%s"), name, db_strerror(ua->db));
433       return 0;
434    }
435    memcpy(pr, &opr, sizeof(opr));
436    return 1;
437 }
438
439 /*
440  * Select a Pool and a Media (Volume) record from the database
441  */
442 int select_pool_and_media_dbr(UAContext *ua, POOL_DBR *pr, MEDIA_DBR *mr)
443 {
444
445    if (!select_media_dbr(ua, mr)) {
446       return 0;
447    }
448    memset(pr, 0, sizeof(POOL_DBR));
449    pr->PoolId = mr->PoolId;
450    if (!db_get_pool_record(ua->jcr, ua->db, pr)) {
451       bsendmsg(ua, "%s", db_strerror(ua->db));
452       return 0;
453    }
454    return 1;
455 }
456
457 /* Select a Media (Volume) record from the database */
458 int select_media_dbr(UAContext *ua, MEDIA_DBR *mr)
459 {
460    int i;
461
462    memset(mr, 0, sizeof(MEDIA_DBR));
463
464    i = find_arg(ua, "volume");
465    if (i >= 0 && ua->argv[i]) {
466       bstrncpy(mr->VolumeName, ua->argv[i], sizeof(mr->VolumeName));
467    }
468    if (mr->VolumeName[0] == 0) {
469       POOL_DBR pr;
470       memset(&pr, 0, sizeof(pr));
471       /* Get the pool from pool=<pool-name> */
472       if (!get_pool_dbr(ua, &pr)) {
473          return 0;
474       }
475       mr->PoolId = pr.PoolId;
476       db_list_media_records(ua->jcr, ua->db, mr, prtit, ua, 0);
477       if (!get_cmd(ua, _("Enter MediaId or Volume name: "))) {
478          return 0;
479       }
480       if (is_a_number(ua->cmd)) {
481          mr->MediaId = atoi(ua->cmd);
482       } else {
483          bstrncpy(mr->VolumeName, ua->cmd, sizeof(mr->VolumeName));
484       }
485    }
486
487    if (!db_get_media_record(ua->jcr, ua->db, mr)) {
488       bsendmsg(ua, "%s", db_strerror(ua->db));
489       return 0;
490    }
491    return 1;
492 }
493
494
495 /* 
496  * Select a pool resource from prompt list
497  */
498 POOL *select_pool_resource(UAContext *ua)
499 {
500    char name[MAX_NAME_LENGTH];    
501    POOL *pool = NULL;
502
503    start_prompt(ua, _("The defined Pool resources are:\n"));
504    LockRes();
505    while ((pool = (POOL *)GetNextRes(R_POOL, (RES *)pool))) {
506       add_prompt(ua, pool->hdr.name);
507    }
508    UnlockRes();
509    do_prompt(ua, _("Select Pool resource"), name, sizeof(name));
510    pool = (POOL *)GetResWithName(R_POOL, name);
511    return pool;
512 }
513
514
515 /*
516  *  If you are thinking about using it, you
517  *  probably want to use select_pool_dbr() 
518  *  or get_pool_dbr() above.
519  */
520 POOL *get_pool_resource(UAContext *ua)
521 {
522    POOL *pool = NULL;
523    int i;
524    
525    for (i=1; i<ua->argc; i++) {
526       if (strcasecmp(ua->argk[i], _("pool")) == 0 && ua->argv[i]) {
527          pool = (POOL *)GetResWithName(R_POOL, ua->argv[i]);
528          if (pool) {
529             return pool;
530          }
531          bsendmsg(ua, _("Error: Pool resource %s does not exist.\n"), ua->argv[i]);
532          break;
533       }
534    }
535    return select_pool_resource(ua);
536 }
537
538 /*
539  * List all jobs and ask user to select one
540  */
541 int select_job_dbr(UAContext *ua, JOB_DBR *jr)
542 {
543    db_list_job_records(ua->jcr, ua->db, jr, prtit, ua, 0);
544    if (!get_cmd(ua, _("Enter the JobId to select: "))) {
545       return 0;
546    }
547    jr->JobId = atoi(ua->cmd);
548    if (!db_get_job_record(ua->jcr, ua->db, jr)) {
549       bsendmsg(ua, "%s", db_strerror(ua->db));
550       return 0;
551    }
552    return jr->JobId;
553
554 }
555
556
557 /* Scan what the user has entered looking for:
558  * 
559  *  jobid=nn
560  *
561  *  if error or not found, put up a list of Jobs
562  *  to choose from.
563  *
564  *   returns: 0 on error
565  *            JobId on success and fills in JOB_DBR
566  */
567 int get_job_dbr(UAContext *ua, JOB_DBR *jr)
568 {
569    int i;
570
571    for (i=1; i<ua->argc; i++) {
572       if (strcasecmp(ua->argk[i], _("job")) == 0 && ua->argv[i]) {
573          jr->JobId = 0;
574          bstrncpy(jr->Job, ua->argv[i], sizeof(jr->Job));
575       } else if (strcasecmp(ua->argk[i], _("jobid")) == 0 && ua->argv[i]) {
576          jr->JobId = atoi(ua->argv[i]);
577       } else {
578          continue;
579       }
580       if (!db_get_job_record(ua->jcr, ua->db, jr)) {
581          bsendmsg(ua, _("Could not find Job %s: ERR=%s"), ua->argv[i],
582                   db_strerror(ua->db));
583          jr->JobId = 0;
584          break;
585       }
586       return jr->JobId;
587    }
588
589    if (!select_job_dbr(ua, jr)) {  /* try once more */
590       return 0;
591    }
592    return jr->JobId;
593 }
594
595 /*
596  * Implement unique set of prompts 
597  */
598 void start_prompt(UAContext *ua, char *msg)
599 {
600   if (ua->max_prompts == 0) {
601      ua->max_prompts = 10;
602      ua->prompt = (char **)bmalloc(sizeof(char *) * ua->max_prompts);
603   }
604   ua->num_prompts = 1;
605   ua->prompt[0] = bstrdup(msg);
606 }
607
608 /*
609  * Add to prompts -- keeping them unique 
610  */
611 void add_prompt(UAContext *ua, char *prompt)
612 {
613    int i;
614    if (ua->num_prompts == ua->max_prompts) {
615       ua->max_prompts *= 2;
616       ua->prompt = (char **)brealloc(ua->prompt, sizeof(char *) *
617          ua->max_prompts);
618     }
619     for (i=1; i < ua->num_prompts; i++) {
620        if (strcmp(ua->prompt[i], prompt) == 0) {
621           return;
622        }
623     }
624     ua->prompt[ua->num_prompts++] = bstrdup(prompt);
625 }
626
627 /*
628  * Display prompts and get user's choice
629  *
630  *  Returns: -1 on error
631  *            index base 0 on success, and choice
632  *               is copied to prompt if not NULL
633  */
634 int do_prompt(UAContext *ua, char *msg, char *prompt, int max_prompt)
635 {
636    int i, item;
637    char pmsg[MAXSTRING];
638
639    bsendmsg(ua, ua->prompt[0]);
640    for (i=1; i < ua->num_prompts; i++) {
641       bsendmsg(ua, "%6d: %s\n", i, ua->prompt[i]);
642    }
643
644    if (prompt) {
645       *prompt = 0;
646    }
647
648    for ( ;; ) {
649       /* First item is the prompt string, not the items */
650       if (ua->num_prompts == 1) { 
651          bsendmsg(ua, _("Selection is empty!\n"));
652          item = 0;                    /* list is empty ! */
653          break;
654       }
655       if (ua->num_prompts == 2) {
656          item = 1;
657          bsendmsg(ua, _("Item 1 selected automatically.\n"));
658          if (prompt) {
659             bstrncpy(prompt, ua->prompt[1], max_prompt);
660          }
661          break;
662       } else {
663          sprintf(pmsg, "%s (1-%d): ", msg, ua->num_prompts-1);
664       }
665       /* Either a . or an @ will get you out of the loop */
666       if (!get_cmd(ua, pmsg) || *ua->cmd == '.' || *ua->cmd == '@') {
667          item = -1;                   /* error */
668          bsendmsg(ua, _("Selection aborted, nothing done.\n"));
669          break;
670       }
671       item = atoi(ua->cmd);
672       if (item < 1 || item >= ua->num_prompts) {
673          bsendmsg(ua, _("Please enter a number between 1 and %d\n"), ua->num_prompts-1);
674          continue;
675       }
676       if (prompt) {
677          bstrncpy(prompt, ua->prompt[item], max_prompt);
678       }
679       break;
680    }
681                               
682    for (i=0; i < ua->num_prompts; i++) {
683       free(ua->prompt[i]);
684    }
685    ua->num_prompts = 0;
686    return item - 1;
687 }
688
689
690 /*
691  * We scan what the user has entered looking for
692  *    storage=<storage-resource>
693  *    job=<job_name>
694  *    jobid=<jobid>
695  *    ?              (prompt him with storage list)
696  *    <some-error>   (prompt him with storage list)
697  *
698  * If use_default is set, we assume that any keyword without a value
699  *   is the name of the Storage resource wanted.
700  */
701 STORE *get_storage_resource(UAContext *ua, int use_default)
702 {
703    char *store_name = NULL;
704    STORE *store = NULL;
705    int jobid;
706    JCR *jcr;
707    int i;
708       
709
710    for (i=1; i<ua->argc; i++) {
711       if (use_default && !ua->argv[i]) {
712          /* Default argument is storage */
713          if (store_name) {
714             bsendmsg(ua, _("Storage name given twice.\n"));
715             return NULL;
716          }
717          /* Ignore barcode(s) keywords */
718          if (strncasecmp("barcode", ua->argk[i], 7) == 0) {
719             continue;
720          }
721          store_name = ua->argk[i];
722          if (*store_name == '?') {
723             *store_name = 0;
724             break;
725          }
726       } else {
727          if (strcasecmp(ua->argk[i], _("storage")) == 0) {
728             store_name = ua->argv[i];
729             break;
730
731          } else if (strcasecmp(ua->argk[i], _("jobid")) == 0) {
732             jobid = atoi(ua->argv[i]);
733             if (jobid <= 0) {
734                bsendmsg(ua, _("Expecting jobid=nn command, got: %s\n"), ua->argk[i]);
735                return NULL;
736             }
737             if (!(jcr=get_jcr_by_id(jobid))) {
738                bsendmsg(ua, _("JobId %d is not running.\n"), jobid);
739                return NULL;
740             }
741             store = jcr->store;
742             free_jcr(jcr);
743             break;
744
745          } else if (strcasecmp(ua->argk[i], _("job")) == 0) {
746             if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
747                bsendmsg(ua, _("Job %s is not running.\n"), ua->argv[i]);
748                return NULL;
749             }
750             store = jcr->store;
751             free_jcr(jcr);
752             break;
753         }
754       }
755    }
756
757    if (!store && store_name) {
758       store = (STORE *)GetResWithName(R_STORAGE, store_name);
759       if (!store) {
760          bsendmsg(ua, "Storage resource %s: not found\n", store_name);
761       }
762    }
763    /* No keywords found, so present a selection list */
764    if (!store) {
765       store = select_storage_resource(ua);
766    }
767    return store;
768 }
769
770
771 /*
772  * Scan looking for mediatype= 
773  *
774  *  if not found or error, put up selection list
775  *
776  *  Returns: 0 on error
777  *           1 on success, MediaType is set
778  */
779 int get_media_type(UAContext *ua, char *MediaType, int max_media)
780 {
781    STORE *store;
782    int i;
783
784    i = find_arg(ua, "mediatype");
785    if (i >= 0 && ua->argv[i]) {
786       bstrncpy(MediaType, ua->argv[i], max_media);
787       return 1;
788    }
789
790    start_prompt(ua, _("Media Types defined in conf file:\n"));
791    LockRes();
792    for (store = NULL; (store = (STORE *)GetNextRes(R_STORAGE, (RES *)store)); ) {
793       add_prompt(ua, store->media_type);
794    }
795    UnlockRes();
796    return (do_prompt(ua, _("Select the Media Type"), MediaType, max_media) < 0) ? 0 : 1;
797 }