]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/wx-console/console_thread.cpp
Correct a minor build problem with wx-console.
[bacula/bacula] / bacula / src / wx-console / console_thread.cpp
1 /*
2  *
3  *    Interaction thread between director and the GUI
4  *
5  *    Nicolas Boichat, April 2004
6  *
7  *    Version $Id$
8  */
9 /*
10    Copyright (C) 2004 Kern Sibbald and John Walker
11
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    as published by the Free Software Foundation; either version 2
15    of the License, or (at your option) any later version.
16
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    GNU General Public License for more details.
21
22    You should have received a copy of the GNU General Public License
23    along with this program; if not, write to the Free Software
24    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
25  */
26
27 // 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
28
29 #include "console_thread.h" // class's header file
30
31 #include <wx/wxprec.h>
32
33 #include <wx/thread.h>
34 #include <wx/file.h>
35 #include <bacula.h>
36 #include <jcr.h>
37
38 #include "console_conf.h"
39
40 #include "csprint.h"
41
42 #ifdef HAVE_WIN32
43 #include <windows.h>
44 char OK_msg[]   = "2000 OK\n";
45 char TERM_msg[] = "2999 Terminate\n";
46 #endif
47
48 /* Imported functions */
49 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
50
51 bool console_thread::inited = false;
52 bool console_thread::configloaded = false;
53 wxString console_thread::working_dir = ".";
54
55 void console_thread::SetWorkingDirectory(wxString w_dir) {
56    if ((w_dir.Last() == '/') || (w_dir.Last() == '\\')) {
57       console_thread::working_dir = w_dir.Mid(0, w_dir.Length()-1);
58    }
59    else {
60       console_thread::working_dir = w_dir;
61    }
62 }
63
64 void console_thread::InitLib() {
65    if (WSA_Init() != 0) {
66       csprint("Error while initializing windows sockets...\n");
67       inited = false;
68       return;
69    }
70    
71    init_stack_dump();
72    my_name_is(0, NULL, "wx-console");
73    //textdomain("bacula-console");
74    working_directory = console_thread::working_dir;
75    
76    inited = true;
77 }
78
79 void console_thread::FreeLib() {
80    if (inited) {
81       if (WSACleanup() != 0) {
82          csprint("Error while cleaning up windows sockets...\n");
83       }
84    }
85 }
86
87 wxString errmsg;
88
89 /*
90  * Format a scanner error message
91  */
92 static void scan_err(const char *file, int line, LEX *lc, const char *msg, ...)
93 {
94    va_list arg_ptr;
95    char buf[MAXSTRING];
96    char more[MAXSTRING];
97    char err[MAXSTRING];
98    
99    va_start(arg_ptr, msg);
100    bvsnprintf(buf, sizeof(buf), msg, arg_ptr);
101    va_end(arg_ptr);
102
103    if (lc->line_no > lc->begin_line_no) {
104       bsnprintf(more, sizeof(more),
105                 _("Problem probably begins at line %d.\n"), lc->begin_line_no);
106    } else {
107       more[0] = 0;
108    }
109    bsnprintf(err, sizeof(err), _("Config error: %s\n"
110 "            : line %d, col %d of file %s\n%s\n%s"),
111       buf, lc->line_no, lc->col_no, lc->fname, lc->line, more);
112    errmsg << err; 
113 }
114
115 wxString console_thread::LoadConfig(wxString configfile) {
116    if (!inited) {
117       InitLib();
118       if (!inited)
119          return "Error while initializing library.";
120    }
121    
122    free_config_resources();
123    
124    MSGS* msgs = (MSGS *)malloc(sizeof(MSGS));
125    memset(msgs, 0, sizeof(MSGS));
126    for (int i=1; i<=M_MAX; i++) {
127 #ifndef WIN32
128       add_msg_dest(msgs, MD_STDOUT, i, NULL, NULL);
129 #endif
130       add_msg_dest(msgs, MD_SYSLOG, i, NULL, NULL);
131       add_msg_dest(msgs, MD_CONSOLE, i, NULL, NULL);
132    }
133    
134    init_msg(NULL, msgs);
135    init_console_msg(console_thread::working_dir);
136
137    errmsg = "";
138    if (!parse_config(configfile.c_str(), &scan_err)) {
139       configloaded = false;
140       term_msg();
141       return errmsg;
142    }
143    
144    term_msg();
145    wxRemoveFile(console_thread::working_dir + "/wx-console.conmsg");
146    init_msg(NULL, NULL);
147    
148    configloaded = true;
149    
150    return "";
151 }
152
153 // class constructor
154 console_thread::console_thread() {
155    UA_sock = NULL;
156    choosingdirector = false;
157 }
158
159 // class destructor
160 console_thread::~console_thread() {
161    if (UA_sock) {
162       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
163       bnet_close(UA_sock);
164       UA_sock = NULL;
165    }
166 }
167
168 /*
169  * Thread entry point
170  */
171 void* console_thread::Entry() {
172    if (!inited) {
173       csprint("Error : Library not initialized\n");
174       csprint(NULL, CS_END);
175       csprint(NULL, CS_DISCONNECTED);
176       csprint(NULL, CS_TERMINATED);
177       #ifdef HAVE_WIN32
178          Exit();
179       #endif
180       return NULL;
181    }
182    
183    if (!configloaded) {
184       csprint("Error : No configuration file loaded\n");
185       csprint(NULL, CS_END);
186       csprint(NULL, CS_DISCONNECTED);
187       csprint(NULL, CS_TERMINATED);
188       #ifdef HAVE_WIN32
189          Exit();
190       #endif
191       return NULL;
192    }
193    
194    csprint("Connecting...\n");
195   
196    int count = 0;
197    DIRRES* res[16]; /* Maximum 16 directors */
198    
199    LockRes();
200    DIRRES* dir;
201    foreach_res(dir, R_DIRECTOR) {
202       res[count] = dir;
203       count++;
204       if (count == 16) {
205          break;
206       }
207    }
208    UnlockRes();
209    
210    if (count == 0) {
211       csprint("Error : No director defined in config file.\n");
212       csprint(NULL, CS_END);
213       csprint(NULL, CS_DISCONNECTED);
214       csprint(NULL, CS_TERMINATED);
215       #ifdef HAVE_WIN32
216          Exit();
217       #endif
218       return NULL;
219    }
220    else if (count == 1) {
221       directorchoosen = 1;
222    }
223    else {
224       while (true) {
225          csprint("Multiple directors found in your config file.\n");
226          for (int i = 0; i < count; i++) {
227             if (i < 9) {
228                csprint(wxString("    ") << (i+1) << ": " << res[i]->hdr.name << "\n");
229             }
230             else {
231                csprint(wxString("   ") <<  (i+1) << ": " << res[i]->hdr.name << "\n");
232             }
233          }
234          csprint(wxString("Please choose a director (1-") << count << ") : ");
235          csprint(NULL, CS_PROMPT);
236          choosingdirector = true;
237          directorchoosen = -1;
238          while(directorchoosen == -1) {
239             bmicrosleep(0, 2000);
240             Yield();
241          }      
242          choosingdirector = false;
243          if (directorchoosen != 0) {
244             break;
245          }
246       }
247    }
248
249    memset(&jcr, 0, sizeof(jcr));
250    
251    jcr.dequeuing = 1; /* TODO: catch messages */
252
253    UA_sock = bnet_connect(&jcr, 3, 3, "Director daemon",
254       res[directorchoosen-1]->address, NULL, res[directorchoosen-1]->DIRport, 0);
255       
256    if (UA_sock == NULL) {
257       csprint("Failed to connect to the director\n");
258       csprint(NULL, CS_END);
259       csprint(NULL, CS_DISCONNECTED);
260       csprint(NULL, CS_TERMINATED);
261       #ifdef HAVE_WIN32
262          Exit();
263       #endif
264       return NULL;
265    }
266
267    csprint("Connected\n");
268
269    jcr.dir_bsock = UA_sock;
270    LockRes();
271    /* If cons==NULL, default console will be used */
272    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
273    UnlockRes();
274    if (!authenticate_director(&jcr, res[directorchoosen-1], cons)) {
275       csprint("ERR=");
276       csprint(UA_sock->msg);
277       csprint(NULL, CS_END);
278       csprint(NULL, CS_DISCONNECTED);
279       csprint(NULL, CS_TERMINATED);
280       #ifdef HAVE_WIN32
281          Exit();
282       #endif
283       return NULL;
284    }
285    
286    csprint(NULL, CS_CONNECTED);
287    
288    Write(".messages\n");
289
290    int stat;
291
292    /* main loop */
293    while(!TestDestroy()) {   /* Tests if thread has been ended */
294       if ((stat = bnet_recv(UA_sock)) >= 0) {
295          csprint(UA_sock->msg);
296       }
297       else if (stat == BNET_SIGNAL) {
298          if (UA_sock->msglen == BNET_PROMPT) {
299             csprint(NULL, CS_PROMPT);
300          }
301          else if (UA_sock->msglen == BNET_EOD) {
302             csprint(NULL, CS_END);
303          }
304          else if (UA_sock->msglen == BNET_HEARTBEAT) {
305             bnet_sig(UA_sock, BNET_HB_RESPONSE);
306             csprint("<< Heartbeat signal received, answered. >>\n", CS_DEBUG);
307          }
308          else {
309             csprint("<< Unexpected signal received : ", CS_DEBUG);
310             csprint(bnet_sig_to_ascii(UA_sock), CS_DEBUG);
311             csprint(">>\n", CS_DEBUG);
312          }
313       }
314       else { /* BNET_HARDEOF || BNET_ERROR */
315          csprint(NULL, CS_END);
316          break;
317       }
318            
319       if (is_bnet_stop(UA_sock)) {
320          csprint(NULL, CS_END);
321          break;            /* error or term */
322       }
323    }
324    
325    csprint(NULL, CS_DISCONNECTED);
326
327    csprint("Connection terminated\n");
328    
329    UA_sock = NULL;
330
331    csprint(NULL, CS_TERMINATED);
332
333    #ifdef HAVE_WIN32
334       Exit();
335    #endif
336    
337    return NULL;
338 }
339
340 void console_thread::Write(const char* str) {
341    if (UA_sock) {
342        UA_sock->msglen = strlen(str);
343        pm_strcpy(&UA_sock->msg, str);
344        bnet_send(UA_sock);
345    }
346    else if (choosingdirector) {
347       wxString number = str;
348       number.RemoveLast(); /* Removes \n */
349       long val;
350       if (number.ToLong(&val)) {
351          directorchoosen = (int)val;
352       }
353       else {
354          directorchoosen = 0;
355       }
356    }
357 }
358
359 void console_thread::Delete() {
360    Write("quit\n");
361    if (UA_sock) {
362       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
363       bnet_close(UA_sock);
364       UA_sock = NULL;
365       /*csprint(NULL, CS_END);
366       csprint(NULL, CS_DISCONNECTED);
367       csprint(NULL, CS_TERMINATED);*/
368    }
369 }