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