3 * Bacula Console interface to the Director
5 * Kern Sibbald, September MM
11 Copyright (C) 2000, 2001 Kern Sibbald and John Walker
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License
15 as published by the Free Software Foundation; either version 2
16 of the License, or (at your option) any later version.
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
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 #include "console_conf.h"
33 /* Imported functions */
34 int authenticate_director(JCR *jcr, DIRRES *director);
37 /* Exported variables */
43 extern int rl_catch_signals;
46 /* Forward referenced functions */
47 static void terminate_console(int sig);
48 int get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec);
50 /* Static variables */
51 static char *configfile = NULL;
52 static BSOCK *UA_sock = NULL;
54 static FILE *output = stdout;
55 static int stop = FALSE;
58 #define CONFIG_FILE "./console.conf" /* default configuration file */
63 "\nVersion: " VERSION " (" DATE ")\n\n"
64 "Usage: console [-s] [-c config_file] [-d debug_level] [config_file]\n"
65 " -c <file> set configuration file to file\n"
66 " -dnn set debug level to nn\n"
68 " -t test - read configuration and exit\n"
69 " -? print this message.\n"
76 void got_stop(int sig)
81 void got_continue(int sig)
86 void got_tout(int sig)
88 // printf("Got tout\n");
93 // printf("Got tin\n");
97 static void read_and_process_input(FILE *input, BSOCK *UA_sock)
100 int at_prompt = FALSE;
101 int tty_input = isatty(fileno(input));
105 if (at_prompt) { /* don't prompt multiple times */
112 stat = get_cmd(input, prompt, UA_sock, 30);
114 int len = sizeof_pool_memory(UA_sock->msg) - 1;
115 if (fgets(UA_sock->msg, len, input) == NULL) {
118 strip_trailing_junk(UA_sock->msg);
119 UA_sock->msglen = strlen(UA_sock->msg);
125 } else if (stat == 0) { /* timeout */
126 bnet_fsend(UA_sock, ".messages");
129 if (!bnet_send(UA_sock)) { /* send command */
133 if (strcmp(UA_sock->msg, ".quit") == 0 || strcmp(UA_sock->msg, ".exit") == 0) {
136 while ((stat = bnet_recv(UA_sock)) > 0) {
139 fprintf(output, "\n");
144 fprintf(output, "%s", UA_sock->msg);
152 } else if (stat == 0) {
153 if (UA_sock->msglen == BNET_PROMPT) {
156 Dmsg1(100, "Got poll %s\n", bnet_sig_to_ascii(UA_sock));
162 /*********************************************************************
164 * Main Bacula Console -- User Interface Program
167 int main(int argc, char *argv[])
169 int ch, i, ndir, item;
170 int no_signals = FALSE;
171 int test_config = FALSE;
175 my_name_is(argc, argv, "console");
176 init_msg(NULL, NULL);
177 working_directory = "/tmp";
179 while ((ch = getopt(argc, argv, "bc:d:r:st?")) != -1) {
181 case 'c': /* configuration file */
182 if (configfile != NULL)
184 configfile = bstrdup(optarg);
188 debug_level = atoi(optarg);
189 if (debug_level <= 0)
193 case 's': /* turn off signals */
211 init_signals(terminate_console);
213 signal(SIGCHLD, SIG_IGN);
214 signal(SIGTSTP, got_stop);
215 signal(SIGCONT, got_continue);
216 signal(SIGTTIN, got_tin);
217 signal(SIGTTOU, got_tout);
223 if (configfile == NULL) {
224 configfile = bstrdup(CONFIG_FILE);
227 parse_config(configfile);
231 for (dir=NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
236 Emsg1(M_ABORT, 0, "No Director resource defined in %s\n\
237 Without that I don't how to speak to the Director :-(\n", configfile);
241 terminate_console(0);
245 memset(&jcr, 0, sizeof(jcr));
248 UA_sock = init_bsock(NULL, 0, "", "", 0);
250 fprintf(output, "Available Directors:\n");
253 for (dir = NULL; (dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir)); ) {
254 fprintf(output, "%d %s at %s:%d\n", 1+ndir++, dir->hdr.name, dir->address,
258 if (get_cmd(stdin, "Select Director: ", UA_sock, 600) < 0) {
261 item = atoi(UA_sock->msg);
262 if (item < 0 || item > ndir) {
263 fprintf(output, "You must enter a number between 1 and %d\n", ndir);
268 for (i=0; i<item; i++) {
269 dir = (DIRRES *)GetNextRes(R_DIRECTOR, (RES *)dir);
275 dir = (DIRRES *)GetNextRes(R_DIRECTOR, NULL);
280 Dmsg2(-1, "Connecting to Director %s:%d\n", dir->address,dir->DIRport);
281 UA_sock = bnet_connect(&jcr, 5, 15, "Director daemon", dir->address,
282 NULL, dir->DIRport, 0);
283 if (UA_sock == NULL) {
284 terminate_console(0);
287 jcr.dir_bsock = UA_sock;
288 if (!authenticate_director(&jcr, dir)) {
289 fprintf(stderr, "ERR: %s", UA_sock->msg);
290 terminate_console(0);
294 Dmsg0(40, "Opened connection with Director daemon\n");
296 read_and_process_input(stdin, UA_sock);
299 bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
303 terminate_console(0);
308 /* Cleanup and then exit */
309 static void terminate_console(int sig)
311 static int already_here = FALSE;
313 if (already_here) /* avoid recursive temination problems */
321 #include "readline/readline.h"
322 #include "readline/history.h"
326 get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec)
330 rl_catch_signals = 1;
331 line = readline(prompt);
336 strcpy(sock->msg, line);
337 strip_trailing_junk(sock->msg);
338 sock->msglen = strlen(sock->msg);
340 add_history(sock->msg);
346 #else /* no readline, do it ourselves */
349 * Returns: 1 if data available
354 wait_for_data(int fd, int sec)
364 switch(select(fd + 1, &fdset, NULL, NULL, &tv)) {
365 case 0: /* timeout */
368 if (errno == EINTR || errno == EAGAIN) {
371 return -1; /* error return */
379 * Get next input command from terminal.
381 * Returns: 1 if got input
386 get_cmd(FILE *input, char *prompt, BSOCK *sock, int sec)
390 fprintf(output, prompt);
394 switch (wait_for_data(fileno(input), sec)) {
396 return 0; /* timeout */
398 return -1; /* error */
400 len = sizeof_pool_memory(sock->msg) - 1;
404 if (fgets(sock->msg, len, input) == NULL) {
409 strip_trailing_junk(sock->msg);
410 sock->msglen = strlen(sock->msg);