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 /* Note: this is the only source file in src/wx-console which uses the
27 * standard gettext macros. So every translated string passed to wxWidgets
28 * must be converted. (wxString(_("..."),wxConvUTF8)) */
30 #include "console_thread.h" // class's header file
32 #include <wx/wxprec.h>
34 #include <wx/thread.h>
39 #include "console_conf.h"
45 char OK_msg[] = "2000 OK\n";
46 char TERM_msg[] = "2999 Terminate\n";
49 /* Imported functions */
50 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
52 bool console_thread::inited = false;
53 bool console_thread::configloaded = false;
54 wxString console_thread::working_dir = wxT(".");
59 * Call-back for reading a passphrase for an encrypted PEM file
60 * This function uses getpass(), which uses a static buffer and is NOT thread-safe.
62 static int tls_pem_callback(char *buf, int size, const void *userdata)
65 const char *prompt = (const char *) userdata;
68 passwd = getpass(prompt);
69 bstrncpy(buf, passwd, size);
79 * Make a quick check to see that we have all the
82 static int check_resources()
90 foreach_res(director, R_DIRECTOR) {
92 /* tls_require implies tls_enable */
93 if (director->tls_require) {
95 director->tls_enable = true;
97 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
103 if ((!director->tls_ca_certfile && !director->tls_ca_certdir) && director->tls_enable) {
104 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
105 " or \"TLS CA Certificate Dir\" are defined for Director \"%s\" in config file.\n"
106 " At least one CA certificate store is required.\n"),
113 Jmsg(NULL, M_FATAL, 0, _("No Director resource defined in config file.\n"
114 "Without that I don't how to speak to the Director :-(\n"));
119 /* Loop over Consoles */
120 foreach_res(cons, R_CONSOLE) {
121 /* tls_require implies tls_enable */
122 if (cons->tls_require) {
124 cons->tls_enable = true;
126 Jmsg(NULL, M_FATAL, 0, _("TLS required but not configured in Bacula.\n"));
132 if ((!cons->tls_ca_certfile && !cons->tls_ca_certdir) && cons->tls_enable) {
133 Jmsg(NULL, M_FATAL, 0, _("Neither \"TLS CA Certificate\""
134 " or \"TLS CA Certificate Dir\" are defined for Console \"%s\" in config file.\n"),
144 void console_thread::SetWorkingDirectory(wxString w_dir) {
145 if ((w_dir.Last() == '/') || (w_dir.Last() == '\\')) {
146 console_thread::working_dir = w_dir.Mid(0, w_dir.Length()-1);
149 console_thread::working_dir = w_dir;
153 void console_thread::InitLib() {
154 if (WSA_Init() != 0) {
155 csprint(_("Error while initializing windows sockets...\n"));
161 my_name_is(0, NULL, "wx-console");
162 working_directory = (const char*) console_thread::working_dir.GetData();
167 void console_thread::FreeLib() {
169 if (WSACleanup() != 0) {
170 csprint(_("Error while cleaning up windows sockets...\n"));
178 * Format a scanner error message
180 static void scan_err(const char *file, int line, LEX *lc, const char *msg, ...)
184 char more[MAXSTRING];
187 va_start(arg_ptr, msg);
188 bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
191 if (lc->line_no > lc->begin_line_no) {
192 bsnprintf(more, sizeof(more),
193 _("Problem probably begins at line %d.\n"), lc->begin_line_no);
198 err.Format(wxString(_("Config error: %s\n : line %d, col %d of file %s\n%s\n%s"), wxConvUTF8),
199 buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
204 wxString console_thread::LoadConfig(wxString configfile) {
208 return wxString(_("Error while initializing library."), wxConvUTF8);
211 free_config_resources();
213 MSGS* msgs = (MSGS *)malloc(sizeof(MSGS));
214 memset(msgs, 0, sizeof(MSGS));
215 for (int i=1; i<=M_MAX; i++) {
217 add_msg_dest(msgs, MD_STDOUT, i, NULL, NULL);
219 // add_msg_dest(msgs, MD_SYSLOG, i, NULL, NULL);
220 add_msg_dest(msgs, MD_CONSOLE, i, NULL, NULL);
223 init_msg(NULL, msgs);
224 init_console_msg(console_thread::working_dir.mb_str(*wxConvCurrent));
227 if (!parse_config(configfile.mb_str(*wxConvCurrent), &scan_err)) {
228 configloaded = false;
233 if (init_tls() != 0) {
234 Jmsg(NULL, M_ERROR_TERM, 0, _("TLS library initialization failed.\n"));
237 if (!check_resources()) {
238 Jmsg(NULL, M_ERROR_TERM, 0, _("Please correct configuration file.\n"));
242 wxRemoveFile(console_thread::working_dir + wxT("/wx-console.conmsg"));
243 init_msg(NULL, NULL);
251 console_thread::console_thread() {
253 choosingdirector = false;
257 console_thread::~console_thread() {
259 bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
268 void* console_thread::Entry() {
271 csprint(_("Error : Library not initialized\n"));
272 csprint(NULL, CS_END);
273 csprint(NULL, CS_DISCONNECTED);
274 csprint(NULL, CS_TERMINATED);
282 csprint(_("Error : No configuration file loaded\n"));
283 csprint(NULL, CS_END);
284 csprint(NULL, CS_DISCONNECTED);
285 csprint(NULL, CS_TERMINATED);
292 csprint(_("Connecting...\n"));
295 DIRRES* res[16]; /* Maximum 16 directors */
298 foreach_res(dir, R_DIRECTOR) {
308 csprint(_("Error : No director defined in config file.\n"));
309 csprint(NULL, CS_END);
310 csprint(NULL, CS_DISCONNECTED);
311 csprint(NULL, CS_TERMINATED);
316 } else if (count == 1) {
320 csprint(_("Multiple directors found in your config file.\n"));
321 for (int i = 0; i < count; i++) {
323 csprint(wxString(wxT(" ")) << (i+1) << wxT(": ") << wxString(res[i]->hdr.name,*wxConvCurrent) << wxT("\n"));
326 csprint(wxString(wxT(" ")) << (i+1) << wxT(": ") << wxString(res[i]->hdr.name,*wxConvCurrent) << wxT("\n"));
329 csprint(wxString::Format(wxString(_("Please choose a director (1-%d): "), wxConvUTF8), count), CS_DATA);
330 csprint(NULL, CS_PROMPT);
331 choosingdirector = true;
332 directorchoosen = -1;
333 while(directorchoosen == -1) {
334 bmicrosleep(0, 2000);
337 choosingdirector = false;
338 if (directorchoosen != 0) {
343 dir = res[directorchoosen-1];
345 memset(&jcr, 0, sizeof(jcr));
347 jcr.dequeuing = 1; /* TODO: catch messages */
350 /* If cons==NULL, default console will be used */
351 CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
355 /* Initialize Console TLS context */
356 if (cons && (cons->tls_enable || cons->tls_require)) {
357 /* Generate passphrase prompt */
358 bsnprintf(buf, sizeof(buf), _("Passphrase for Console \"%s\" TLS private key: "), cons->hdr.name);
360 /* Initialize TLS context:
361 * Args: CA certfile, CA certdir, Certfile, Keyfile,
362 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
363 cons->tls_ctx = new_tls_context(cons->tls_ca_certfile,
364 cons->tls_ca_certdir, cons->tls_certfile,
365 cons->tls_keyfile, tls_pem_callback, &buf, NULL, true);
367 if (!cons->tls_ctx) {
368 bsnprintf(buf, sizeof(buf), _("Failed to initialize TLS context for Console \"%s\".\n"),
376 /* Initialize Director TLS context */
377 if (dir->tls_enable || dir->tls_require) {
378 /* Generate passphrase prompt */
379 bsnprintf(buf, sizeof(buf), _("Passphrase for Director \"%s\" TLS private key: "), dir->hdr.name);
381 /* Initialize TLS context:
382 * Args: CA certfile, CA certdir, Certfile, Keyfile,
383 * Keyfile PEM Callback, Keyfile CB Userdata, DHfile, Verify Peer */
384 dir->tls_ctx = new_tls_context(dir->tls_ca_certfile,
385 dir->tls_ca_certdir, dir->tls_certfile,
386 dir->tls_keyfile, tls_pem_callback, &buf, NULL, true);
389 bsnprintf(buf, sizeof(buf), _("Failed to initialize TLS context for Director \"%s\".\n"),
397 UA_sock = bnet_connect(&jcr, 3, 3, _("Director daemon"),
398 dir->address, NULL, dir->DIRport, 0);
400 if (UA_sock == NULL) {
401 csprint(_("Failed to connect to the director\n"));
402 csprint(NULL, CS_END);
403 csprint(NULL, CS_DISCONNECTED);
404 csprint(NULL, CS_TERMINATED);
411 csprint(_("Connected\n"));
413 jcr.dir_bsock = UA_sock;
414 if (!authenticate_director(&jcr, dir, cons)) {
416 csprint(UA_sock->msg);
417 csprint(NULL, CS_END);
418 csprint(NULL, CS_DISCONNECTED);
419 csprint(NULL, CS_TERMINATED);
426 csprint(NULL, CS_CONNECTED);
428 Write(".messages\n");
433 while(!TestDestroy()) { /* Tests if thread has been ended */
434 if ((stat = bnet_recv(UA_sock)) >= 0) {
435 csprint(UA_sock->msg);
437 else if (stat == BNET_SIGNAL) {
438 if (UA_sock->msglen == BNET_PROMPT) {
439 csprint(NULL, CS_PROMPT);
441 else if (UA_sock->msglen == BNET_EOD) {
442 csprint(NULL, CS_END);
444 else if (UA_sock->msglen == BNET_HEARTBEAT) {
445 bnet_sig(UA_sock, BNET_HB_RESPONSE);
446 csprint(_("<< Heartbeat signal received, answered. >>\n"), CS_DEBUG);
449 csprint(_("<< Unexpected signal received : "), CS_DEBUG);
450 csprint(bnet_sig_to_ascii(UA_sock), CS_DEBUG);
451 csprint(">>\n", CS_DEBUG);
454 else { /* BNET_HARDEOF || BNET_ERROR */
455 csprint(NULL, CS_END);
459 if (is_bnet_stop(UA_sock)) {
460 csprint(NULL, CS_END);
461 break; /* error or term */
465 csprint(NULL, CS_DISCONNECTED);
467 csprint(_("Connection terminated\n"));
471 csprint(NULL, CS_TERMINATED);
480 void console_thread::Write(const char* str)
483 UA_sock->msglen = strlen(str);
484 pm_strcpy(&UA_sock->msg, str);
486 } else if (choosingdirector) {
487 // wxString number = str;
488 // number.RemoveLast(); /* Removes \n */
491 // if (number.ToLong(&val)) {
494 directorchoosen = (int)val;
501 void console_thread::Delete() {
504 bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
507 /*csprint(NULL, CS_END);
508 csprint(NULL, CS_DISCONNECTED);
509 csprint(NULL, CS_TERMINATED);*/