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