]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_input.c
Fix bconsole bug with new BNET signals
[bacula/bacula] / bacula / src / dird / ua_input.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2001-2010 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from
7    many others, a complete list can be found in the file AUTHORS.
8    This program is Free Software; you can redistribute it and/or
9    modify it under the terms of version three of the GNU Affero General Public
10    License as published by the Free Software Foundation and included
11    in the file LICENSE.
12
13    This program is distributed in the hope that it will be useful, but
14    WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16    General Public License for more details.
17
18    You should have received a copy of the GNU Affero General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21    02110-1301, USA.
22
23    Bacula® is a registered trademark of Kern Sibbald.
24    The licensor of Bacula is the Free Software Foundation Europe
25    (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
26    Switzerland, email:ftf@fsfeurope.org.
27 */
28 /*
29  *
30  *   Bacula Director -- User Agent Input and scanning code
31  *
32  *     Kern Sibbald, October MMI
33  *
34  */
35
36 #include "bacula.h"
37 #include "dird.h"
38
39
40 /* Imported variables */
41
42
43 /* Exported functions */
44
45 /* 
46  * If subprompt is set, we send a BNET_SUB_PROMPT signal otherwise
47  *   send a BNET_TEXT_INPUT signal.
48  */
49 int get_cmd(UAContext *ua, const char *prompt, bool subprompt)
50 {
51    BSOCK *sock = ua->UA_sock;
52    int stat;
53
54    ua->cmd[0] = 0;
55    if (!sock || ua->batch) {          /* No UA or batch mode */
56       return 0;
57    }
58    if (!subprompt && ua->api) {
59       sock->signal(BNET_TEXT_INPUT);
60    }
61    sock->fsend("%s", prompt);
62    if (!ua->api || subprompt) {
63       sock->signal(BNET_SUB_PROMPT);
64    }
65    for ( ;; ) {
66       stat = sock->recv();
67       if (stat == BNET_SIGNAL) {
68          continue;                    /* ignore signals */
69       }
70       if (is_bnet_stop(sock)) {
71          return 0;                    /* error or terminate */
72       }
73       pm_strcpy(ua->cmd, sock->msg);
74       strip_trailing_junk(ua->cmd);
75       if (strcmp(ua->cmd, ".messages") == 0) {
76          qmessagescmd(ua, ua->cmd);
77       }
78       /* Lone dot => break */
79       if (ua->cmd[0] == '.' && ua->cmd[1] == 0) {
80          return 0;
81       }
82       break;
83    }
84    return 1;
85 }
86
87 /*
88  * Get a positive integer
89  *  Returns:  false if failure
90  *            true  if success => value in ua->pint32_val
91  */
92 bool get_pint(UAContext *ua, const char *prompt)
93 {
94    double dval;
95    ua->pint32_val = 0;
96    ua->int64_val = 0;
97    for (;;) {
98       ua->cmd[0] = 0;
99       if (!get_cmd(ua, prompt)) {
100          return false;
101       }
102       /* Kludge for slots blank line => 0 */
103       if (ua->cmd[0] == 0 && strncmp(prompt, _("Enter slot"), strlen(_("Enter slot"))) == 0) {
104          return true;
105       }
106       if (!is_a_number(ua->cmd)) {
107          ua->warning_msg(_("Expected a positive integer, got: %s\n"), ua->cmd);
108          continue;
109       }
110       errno = 0;
111       dval = strtod(ua->cmd, NULL);
112       if (errno != 0 || dval < 0) {
113          ua->warning_msg(_("Expected a positive integer, got: %s\n"), ua->cmd);
114          continue;
115       }
116       ua->pint32_val = (uint32_t)dval;
117       ua->int64_val = (int64_t)dval;
118       return true;
119    }
120 }
121
122 /*
123  * Test a yes or no response
124  *  Returns:  false if failure
125  *            true  if success => ret == 1 for yes
126  *                                ret == 0 for no
127  */
128 bool is_yesno(char *val, int *ret)
129 {
130    *ret = 0;
131    if ((strcasecmp(val,   _("yes")) == 0) ||
132        (strcasecmp(val, NT_("yes")) == 0))
133    {
134       *ret = 1;
135    } else if ((strcasecmp(val,   _("no")) == 0) ||
136               (strcasecmp(val, NT_("no")) == 0))
137    {
138       *ret = 0;
139    } else {
140       return false;
141    }
142
143    return true;
144 }
145
146 /*
147  * Gets a yes or no response
148  *  Returns:  false if failure
149  *            true  if success => ua->pint32_val == 1 for yes
150  *                                ua->pint32_val == 0 for no
151  */
152 bool get_yesno(UAContext *ua, const char *prompt)
153 {
154    int len;
155    int ret;
156    ua->pint32_val = 0;
157    for (;;) {
158       if (ua->api) ua->UA_sock->signal(BNET_YESNO);
159       if (!get_cmd(ua, prompt)) {
160          return false;
161       }
162       len = strlen(ua->cmd);
163       if (len < 1 || len > 3) {
164          continue;
165       }
166       if (is_yesno(ua->cmd, &ret)) {
167          ua->pint32_val = ret;
168          return true;
169       }
170       ua->warning_msg(_("Invalid response. You must answer yes or no.\n"));
171    }
172 }
173
174 /* 
175  *  Gets an Enabled value => 0, 1, 2, yes, no, archived
176  *  Returns: 0, 1, 2 if OK
177  *           -1 on error
178  */
179 int get_enabled(UAContext *ua, const char *val) 
180 {
181    int Enabled = -1;
182
183    if (strcasecmp(val, "yes") == 0 || strcasecmp(val, "true") == 0) {
184      Enabled = 1;
185    } else if (strcasecmp(val, "no") == 0 || strcasecmp(val, "false") == 0) {
186       Enabled = 0;
187    } else if (strcasecmp(val, "archived") == 0) { 
188       Enabled = 2;
189    } else {
190       Enabled = atoi(val);
191    }
192    if (Enabled < 0 || Enabled > 2) {
193       ua->error_msg(_("Invalid Enabled value, it must be yes, no, archived, 0, 1, or 2\n"));
194       return -1;     
195    }
196    return Enabled;
197 }
198
199 void parse_ua_args(UAContext *ua)
200 {
201    parse_args(ua->cmd, &ua->args, &ua->argc, ua->argk, ua->argv, MAX_CMD_ARGS);
202 }
203
204 /*
205  * Check if the comment has legal characters
206  * If ua is non-NULL send the message
207  */
208 bool is_comment_legal(UAContext *ua, const char *name)
209 {
210    int len;
211    const char *p;
212    const char *forbid = "'<>&\\\"";
213
214    /* Restrict the characters permitted in the comment */
215    for (p=name; *p; p++) {
216       if (!strchr(forbid, (int)(*p))) {
217          continue;
218       }
219       if (ua) {
220          ua->error_msg(_("Illegal character \"%c\" in a comment.\n"), *p);
221       }
222       return 0;
223    }
224    len = strlen(name);
225    if (len >= MAX_NAME_LENGTH) {
226       if (ua) {
227          ua->error_msg(_("Comment too long.\n"));
228       }
229       return 0;
230    }
231    if (len == 0) {
232       if (ua) {
233          ua->error_msg(_("Comment must be at least one character long.\n"));
234       }
235       return 0;
236    }
237    return 1;
238 }