]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_input.c
More debug info when aborting
[bacula/bacula] / bacula / src / dird / ua_input.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is 
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18 */
19 /*
20  *
21  *   Bacula Director -- User Agent Input and scanning code
22  *
23  *     Kern Sibbald, October MMI
24  *
25  */
26
27 #include "bacula.h"
28 #include "dird.h"
29
30
31 /* Imported variables */
32
33
34 /* Exported functions */
35
36 /*
37  * If subprompt is set, we send a BNET_SUB_PROMPT signal otherwise
38  *   send a BNET_TEXT_INPUT signal.
39  */
40 bool get_cmd(UAContext *ua, const char *prompt, bool subprompt)
41 {
42    BSOCK *sock = ua->UA_sock;
43    int stat;
44
45    ua->cmd[0] = 0;
46    if (!sock || ua->batch) {          /* No UA or batch mode */
47       return false;
48    }
49    if (!subprompt && ua->api) {
50       sock->signal(BNET_TEXT_INPUT);
51    }
52    sock->fsend("%s", prompt);
53    if (!ua->api || subprompt) {
54       sock->signal(BNET_SUB_PROMPT);
55    }
56    for ( ;; ) {
57       stat = sock->recv();
58       if (stat == BNET_SIGNAL) {
59          continue;                    /* ignore signals */
60       }
61       if (sock->is_stop()) {
62          return false;               /* error or terminate */
63       }
64       pm_strcpy(ua->cmd, sock->msg);
65       strip_trailing_junk(ua->cmd);
66       if (strcmp(ua->cmd, ".messages") == 0) {
67          qmessagescmd(ua, ua->cmd);
68       }
69       /* Lone dot => break */
70       if (ua->cmd[0] == '.' && ua->cmd[1] == 0) {
71          return false;
72       }
73       break;
74    }
75    return true;
76 }
77
78 /*
79  * Get a selection list
80  *  We get a command from the user, scan it, then
81  *  return when OK
82  * Returns true if OK
83  *         false if error
84  */
85 bool get_selection_list(UAContext *ua, sellist &sl,
86                         const char *prompt, bool subprompt)
87 {
88    for ( ;; ) {
89       if (!get_cmd(ua, prompt, subprompt)) {
90          return false;
91       }
92       if (!sl.set_string(ua->cmd, true)) {
93          ua->send_msg("%s", sl.get_errmsg());
94          continue;
95       }
96       return true;
97    }
98 }
99
100 /*
101  * Get a positive integer
102  *  Returns:  false if failure
103  *            true  if success => value in ua->pint32_val
104  */
105 bool get_pint(UAContext *ua, const char *prompt)
106 {
107    double dval;
108    ua->pint32_val = 0;
109    ua->int64_val = 0;
110    for (;;) {
111       ua->cmd[0] = 0;
112       if (!get_cmd(ua, prompt)) {
113          return false;
114       }
115       /* Kludge for slots blank line => 0 */
116       if (ua->cmd[0] == 0 && strncmp(prompt, _("Enter slot"), strlen(_("Enter slot"))) == 0) {
117          return true;
118       }
119       if (!is_a_number(ua->cmd)) {
120          ua->warning_msg(_("Expected a positive integer, got: %s\n"), ua->cmd);
121          continue;
122       }
123       errno = 0;
124       dval = strtod(ua->cmd, NULL);
125       if (errno != 0 || dval < 0) {
126          ua->warning_msg(_("Expected a positive integer, got: %s\n"), ua->cmd);
127          continue;
128       }
129       ua->pint32_val = (uint32_t)dval;
130       ua->int64_val = (int64_t)dval;
131       return true;
132    }
133 }
134
135 /*
136  * Test a yes or no response
137  *  Returns:  false if failure
138  *            true  if success => ret == 1 for yes
139  *                                ret == 0 for no
140  */
141 bool is_yesno(char *val, int *ret)
142 {
143    *ret = 0;
144    if ((strcasecmp(val,   _("yes")) == 0) ||
145        (strcasecmp(val, NT_("yes")) == 0))
146    {
147       *ret = 1;
148    } else if ((strcasecmp(val,   _("no")) == 0) ||
149               (strcasecmp(val, NT_("no")) == 0))
150    {
151       *ret = 0;
152    } else {
153       return false;
154    }
155
156    return true;
157 }
158
159 /*
160  * Gets a yes or no response
161  *  Returns:  false if failure
162  *            true  if success => ua->pint32_val == 1 for yes
163  *                                ua->pint32_val == 0 for no
164  */
165 bool get_yesno(UAContext *ua, const char *prompt)
166 {
167    int len;
168    int ret;
169    ua->pint32_val = 0;
170    for (;;) {
171       if (ua->api) ua->UA_sock->signal(BNET_YESNO);
172       if (!get_cmd(ua, prompt)) {
173          return false;
174       }
175       len = strlen(ua->cmd);
176       if (len < 1 || len > 3) {
177          continue;
178       }
179       if (is_yesno(ua->cmd, &ret)) {
180          ua->pint32_val = ret;
181          return true;
182       }
183       ua->warning_msg(_("Invalid response. You must answer yes or no.\n"));
184    }
185 }
186
187 /*
188  *  Gets an Enabled value => 0, 1, 2, yes, no, archived
189  *  Returns: 0, 1, 2 if OK
190  *           -1 on error
191  */
192 int get_enabled(UAContext *ua, const char *val)
193 {
194    int Enabled = -1;
195
196    if (strcasecmp(val, "yes") == 0 || strcasecmp(val, "true") == 0) {
197      Enabled = 1;
198    } else if (strcasecmp(val, "no") == 0 || strcasecmp(val, "false") == 0) {
199       Enabled = 0;
200    } else if (strcasecmp(val, "archived") == 0) {
201       Enabled = 2;
202    } else {
203       Enabled = atoi(val);
204    }
205    if (Enabled < 0 || Enabled > 2) {
206       ua->error_msg(_("Invalid Enabled value, it must be yes, no, archived, 0, 1, or 2\n"));
207       return -1;
208    }
209    return Enabled;
210 }
211
212 void parse_ua_args(UAContext *ua)
213 {
214    parse_args(ua->cmd, &ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
215 }
216
217 /*
218  * Check if the comment has legal characters
219  * If ua is non-NULL send the message
220  */
221 bool is_comment_legal(UAContext *ua, const char *name)
222 {
223    int len;
224    const char *p;
225    const char *forbid = "'<>&\\\"";
226
227    /* Restrict the characters permitted in the comment */
228    for (p=name; *p; p++) {
229       if (!strchr(forbid, (int)(*p))) {
230          continue;
231       }
232       if (ua) {
233          ua->error_msg(_("Illegal character \"%c\" in a comment.\n"), *p);
234       }
235       return 0;
236    }
237    len = strlen(name);
238    if (len >= MAX_NAME_LENGTH) {
239       if (ua) {
240          ua->error_msg(_("Comment too long.\n"));
241       }
242       return 0;
243    }
244    if (len == 0) {
245       if (ua) {
246          ua->error_msg(_("Comment must be at least one character long.\n"));
247       }
248       return 0;
249    }
250    return 1;
251 }