3 * Interaction thread between director and the GUI
5 * Nicolas Boichat, April 2004
10 Copyright (C) 2004-2005 Kern Sibbald
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License
14 version 2 as amended with additional clauses defined in the
15 file LICENSE in the main source directory.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 the file LICENSE for additional details.
24 // http://66.102.9.104/search?q=cache:Djc1mPF3hRoJ:cvs.sourceforge.net/viewcvs.py/audacity/audacity-src/src/AudioIO.cpp%3Frev%3D1.102+macos+x+wxthread&hl=fr
26 /* _("...") macro returns a wxChar*, so if we need a char*, we need to convert it with:
27 * wxString(_("...")).mb_str(*wxConvCurrent) */
29 #include "console_thread.h" // class's header file
31 #include <wx/wxprec.h>
33 #include <wx/thread.h>
36 #include "console_conf.h"
42 char OK_msg[] = "2000 OK\n";
43 char TERM_msg[] = "2999 Terminate\n";
46 /* Imported functions */
47 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
49 bool console_thread::inited = false;
50 bool console_thread::configloaded = false;
51 wxString console_thread::working_dir = wxT(".");
56 * Call-back for reading a passphrase for an encrypted PEM file
57 * This function uses getpass(), which uses a static buffer and is NOT thread-safe.
59 static int tls_pem_callback(char *buf, int size, const void *userdata)
62 const char *prompt = (const char *) userdata;
65 passwd = getpass(prompt);
66 bstrncpy(buf, passwd, size);
76 * Make a quick check to see that we have all the
79 static int check_resources()
87 foreach_res(director, R_DIRECTOR) {
89 /* tls_require implies tls_enable */
90 if (director->tls_require) {
92 director->tls_enable = true;
94 Jmsg(NULL, M_FATAL, 0, wxString(_("TLS required but not configured in Bacula.\n")).mb_str(*wxConvCurrent));
100 if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable) {
101 Jmsg(NULL, M_FATAL, 0, wxString(_("Neither \"TLS CA Certificate\" or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in config file.\nAt least one CA certificate store is required.\n")).mb_str(*wxConvCurrent),
108 Jmsg(NULL, M_FATAL, 0, wxString(_("No Director resource defined in config file.\nWithout that I don't how to speak to the Director :-(\n")).mb_str(*wxConvCurrent));
113 /* Loop over Consoles */
114 foreach_res(cons, R_CONSOLE) {
115 /* tls_require implies tls_enable */
116 if (cons->tls_require) {
118 cons->tls_enable = true;
120 Jmsg(NULL, M_FATAL, 0, wxString(_("TLS required but not configured in Bacula.\n")).mb_str(*wxConvCurrent));
126 if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable) {
127 Jmsg(NULL, M_FATAL, 0, wxString(_("Neither \"TLS CA Certificate\" or \"TLS CA Certificate Dir\" are defined for Console \"%s\" in config file.\n")).mb_str(*wxConvCurrent),
137 void console_thread::SetWorkingDirectory(wxString w_dir) {
138 if ((w_dir.Last() == '/') || (w_dir.Last() == '\\')) {
139 console_thread::working_dir = w_dir.Mid(0, w_dir.Length()-1);
142 console_thread::working_dir = w_dir;
146 void console_thread::InitLib() {
147 if (WSA_Init() != 0) {
148 csprint(_("Error while initializing windows sockets...\n"));
154 my_name_is(0, NULL, "wx-console");
155 working_directory = (const char*) console_thread::working_dir.GetData();
160 void console_thread::FreeLib() {
162 if (WSACleanup() != 0) {
163 csprint(_("Error while cleaning up windows sockets...\n"));
171 * Format a scanner error message
173 static void scan_err(const char *file, int line, LEX *lc, const char *msg, ...)
177 char more[MAXSTRING];
180 va_start(arg_ptr, msg);
181 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
184 if (lc->line_no > lc->begin_line_no) {
185 bsnprintf(more, sizeof(more),
186 wxString(_("Problem probably begins at line %d.\n")).mb_str(*wxConvCurrent), lc->begin_line_no);
191 err.Format(_("Config error: %s\n : line %d, col %d of file %s\n%s\n%s"),
192 buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
197 wxString console_thread::LoadConfig(wxString configfile) {
201 return _("Error while initializing library.");
204 free_config_resources();
206 MSGS* msgs = (MSGS *)malloc(sizeof(MSGS));
207 memset(msgs, 0, sizeof(MSGS));
208 for (int i=1; i<=M_MAX; i++) {
210 add_msg_dest(msgs, MD_STDOUT, i, NULL, NULL);
212 // add_msg_dest(msgs, MD_SYSLOG, i, NULL, NULL);
213 add_msg_dest(msgs, MD_CONSOLE, i, NULL, NULL);
216 init_msg(NULL, msgs);
217 init_console_msg(console_thread::working_dir.mb_str(*wxConvCurrent));
220 if (!parse_config(configfile.mb_str(*wxConvCurrent), &scan_err)) {
221 configloaded = false;
226 if (init_tls() != 0) {
227 Jmsg(NULL, M_ERROR_TERM, 0, wxString(_("TLS library initialization failed.\n")).mb_str(*wxConvCurrent));
230 if (!check_resources()) {
231 Jmsg(NULL, M_ERROR_TERM, 0, wxString(_("Please correct configuration file.\n")).mb_str(*wxConvCurrent));
235 wxRemoveFile(console_thread::working_dir + wxT("/wx-console.conmsg"));
236 init_msg(NULL, NULL);
244 console_thread::console_thread() {
246 choosingdirector = false;
250 console_thread::~console_thread() {
252 bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
261 void* console_thread::Entry() {
262 /* It seems we must redefine the locale on each thread. */
265 m_locale.AddCatalog(wxT("bacula"));
268 #define LOCALEDIR "."
270 wxLocale::AddCatalogLookupPathPrefix(wxT(LOCALEDIR));
274 csprint(_("Error : Library not initialized\n"));
275 csprint(NULL, CS_END);
276 csprint(NULL, CS_DISCONNECTED);
277 csprint(NULL, CS_TERMINATED);
285 csprint(_("Error : No configuration file loaded\n"));
286 csprint(NULL, CS_END);
287 csprint(NULL, CS_DISCONNECTED);
288 csprint(NULL, CS_TERMINATED);
295 csprint(_("Connecting...\n"));
298 DIRRES* res[16]; /* Maximum 16 directors */
301 foreach_res(dir, R_DIRECTOR) {
311 csprint(_("Error : No director defined in config file.\n"));
312 csprint(NULL, CS_END);
313 csprint(NULL, CS_DISCONNECTED);
314 csprint(NULL, CS_TERMINATED);
319 } else if (count == 1) {
323 csprint(_("Multiple directors found in your config file.\n"));
324 for (int i = 0; i < count; i++) {
326 csprint(wxString(wxT(" ")) << (i+1) << wxT(": ") << wxString(res[i]->hdr.name,*wxConvCurrent) << wxT("\n"));
329 csprint(wxString(wxT(" ")) << (i+1) << wxT(": ") << wxString(res[i]->hdr.name,*wxConvCurrent) << wxT("\n"));
332 csprint(wxString::Format(_("Please choose a director (1-%d): "), count), CS_DATA);
333 csprint(NULL, CS_PROMPT);
334 choosingdirector = true;
335 directorchoosen = -1;
336 while(directorchoosen == -1) {
337 bmicrosleep(0, 2000);
340 choosingdirector = false;
341 if (directorchoosen != 0) {
346 dir = res[directorchoosen-1];
348 memset(&jcr, 0, sizeof(jcr));
350 jcr.dequeuing = 1; /* TODO: catch messages */
353 /* If cons==NULL, default console will be used */
354 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
358 /* Initialize Console TLS context */
359 if (cons && (cons->tls_enable || cons->tls_require)) {
360 /* Generate passphrase prompt */
361 bsnprintf(buf, sizeof(buf), wxString(_("Passphrase for Console \"%s\" TLS private key: ")).mb_str(*wxConvCurrent), cons->hdr.name);
363 /* Initialize TLS context:
364 * Args: CA certfile, CA certdir, Certfile, Keyfile,
365 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
366 cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
367 cons->tls_ca_certdir, cons->tls_certfile,
368 cons->tls_keyfile, tls_pem_callback, &buf, NULL, true);
370 if (!cons->tls_ctx) {
371 bsnprintf(buf, sizeof(buf), wxString(_("Failed to initialize TLS context for Console \"%s\".\n")).mb_str(*wxConvCurrent),
379 /* Initialize Director TLS context */
380 if (dir->tls_enable || dir->tls_require) {
381 /* Generate passphrase prompt */
382 bsnprintf(buf, sizeof(buf), wxString(_("Passphrase for Director \"%s\" TLS private key: ")).mb_str(*wxConvCurrent), dir->hdr.name);
384 /* Initialize TLS context:
385 * Args: CA certfile, CA certdir, Certfile, Keyfile,
386 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
387 dir->tls_ctx = new_tls_context(dir->tls_ca_certfile,
388 dir->tls_ca_certdir, dir->tls_certfile,
389 dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
392 bsnprintf(buf, sizeof(buf), wxString(_("Failed to initialize TLS context for Director \"%s\".\n")).mb_str(*wxConvCurrent),
400 UA_sock = bnet_connect(&jcr, 3, 3, wxString(_("Director daemon")).mb_str(*wxConvCurrent),
401 dir->address, NULL, dir->DIRport, 0);
403 if (UA_sock == NULL) {
404 csprint(_("Failed to connect to the director\n"));
405 csprint(NULL, CS_END);
406 csprint(NULL, CS_DISCONNECTED);
407 csprint(NULL, CS_TERMINATED);
414 csprint(_("Connected\n"));
416 jcr.dir_bsock = UA_sock;
417 if (!authenticate_director(&jcr, dir, cons)) {
419 csprint(UA_sock->msg);
420 csprint(NULL, CS_END);
421 csprint(NULL, CS_DISCONNECTED);
422 csprint(NULL, CS_TERMINATED);
429 csprint(NULL, CS_CONNECTED);
431 Write(".messages\n");
436 while(!TestDestroy()) { /* Tests if thread has been ended */
437 if ((stat = bnet_recv(UA_sock)) >= 0) {
438 csprint(UA_sock->msg);
440 else if (stat == BNET_SIGNAL) {
441 if (UA_sock->msglen == BNET_PROMPT) {
442 csprint(NULL, CS_PROMPT);
444 else if (UA_sock->msglen == BNET_EOD) {
445 csprint(NULL, CS_END);
447 else if (UA_sock->msglen == BNET_HEARTBEAT) {
448 bnet_sig(UA_sock, BNET_HB_RESPONSE);
449 csprint(_("<< Heartbeat signal received, answered. >>\n"), CS_DEBUG);
452 csprint(_("<< Unexpected signal received : "), CS_DEBUG);
453 csprint(bnet_sig_to_ascii(UA_sock), CS_DEBUG);
454 csprint(">>\n", CS_DEBUG);
457 else { /* BNET_HARDEOF || BNET_ERROR */
458 csprint(NULL, CS_END);
462 if (is_bnet_stop(UA_sock)) {
463 csprint(NULL, CS_END);
464 break; /* error or term */
468 csprint(NULL, CS_DISCONNECTED);
470 csprint(_("Connection terminated\n"));
474 csprint(NULL, CS_TERMINATED);
483 void console_thread::Write(const char* str)
486 UA_sock->msglen = strlen(str);
487 pm_strcpy(&UA_sock->msg, str);
489 } else if (choosingdirector) {
490 // wxString number = str;
491 // number.RemoveLast(); /* Removes \n */
494 // if (number.ToLong(&val)) {
497 directorchoosen = (int)val;
504 void console_thread::Delete() {
507 bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
510 /*csprint(NULL, CS_END);
511 csprint(NULL, CS_DISCONNECTED);
512 csprint(NULL, CS_TERMINATED);*/