]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/wx-console/console_thread.cpp
revert working_directory
[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 DWORD  g_platform_id = VER_PLATFORM_WIN32_WINDOWS;
45 char OK_msg[]   = "2000 OK\n";
46 char TERM_msg[] = "2999 Terminate\n";
47 #endif
48
49 /* Imported functions */
50 int authenticate_director(JCR *jcr, DIRRES *director, CONRES *cons);
51
52 bool console_thread::inited = false;
53 bool console_thread::configloaded = false;
54
55 void console_thread::InitLib() {
56    if (WSA_Init() != 0) {
57       csprint("Error while initializing windows sockets...\n");
58       inited = false;
59       return;
60    }
61    
62    init_stack_dump();
63    my_name_is(0, NULL, "wx-console");
64    //textdomain("bacula-console");
65    working_directory = ".";
66    
67    inited = true;
68 }
69
70 void console_thread::FreeLib() {
71    if (inited) {
72       if (WSACleanup() != 0) {
73          csprint("Error while cleaning up windows sockets...\n");
74       }
75    }
76 }
77
78 wxString console_thread::LoadConfig(wxString configfile) {
79    if (!inited) {
80       InitLib();
81       if (!inited)
82          return "Error while initializing library.";
83    }
84    
85    free_config_resources();
86    
87    MSGS* msgs = (MSGS *)malloc(sizeof(MSGS));
88    memset(msgs, 0, sizeof(MSGS));
89    for (int i=1; i<=M_MAX; i++) {
90 #ifndef WIN32
91       add_msg_dest(msgs, MD_STDOUT, i, NULL, NULL);
92 #endif
93       add_msg_dest(msgs, MD_SYSLOG, i, NULL, NULL);
94       add_msg_dest(msgs, MD_CONSOLE, i, NULL, NULL);
95    }
96    
97    init_msg(NULL, msgs);
98    init_console_msg(".");
99
100    if (!parse_config(configfile.c_str(), 0)) {
101       configloaded = false;
102       wxFile file("./wx-console.conmsg");
103       if (!file.IsOpened())
104          return "Unable to retrieve error message.";
105       wxString err = "";
106       wxChar buffer[513];
107       off_t len;
108       while ((len = file.Read(buffer, 512)) > -1) {
109          buffer[len] = (wxChar)0;
110          err += buffer;
111          if (file.Eof())
112             break;
113       }
114       file.Close();
115       term_msg();
116       wxRemoveFile("./wx-console.conmsg");
117       return err;
118    }
119    
120    term_msg();
121    wxRemoveFile("./wx-console.conmsg");
122    init_msg(NULL, NULL);
123    
124    configloaded = true;
125    
126    return "";
127 }
128
129 // class constructor
130 console_thread::console_thread() {
131    UA_sock = NULL;
132    choosingdirector = false;
133 }
134
135 // class destructor
136 console_thread::~console_thread() {
137    if (UA_sock) {
138       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
139       bnet_close(UA_sock);
140       UA_sock = NULL;
141    }
142 }
143
144 /*
145  * Thread entry point
146  */
147 void* console_thread::Entry() {
148    if (!inited) {
149       csprint("Error : Library not initialized\n");
150       csprint(NULL, CS_END);
151       csprint(NULL, CS_DISCONNECTED);
152       csprint(NULL, CS_TERMINATED);
153       #ifdef HAVE_WIN32
154          Exit();
155       #endif
156       return NULL;
157    }
158    
159    if (!configloaded) {
160       csprint("Error : No configuration file loaded\n");
161       csprint(NULL, CS_END);
162       csprint(NULL, CS_DISCONNECTED);
163       csprint(NULL, CS_TERMINATED);
164       #ifdef HAVE_WIN32
165          Exit();
166       #endif
167       return NULL;
168    }
169    
170    csprint("Connecting...\n");
171   
172    int count = 0;
173    DIRRES* res[16]; /* Maximum 16 directors */
174    
175    LockRes();
176    DIRRES* dir;
177    foreach_res(dir, R_DIRECTOR) {
178       res[count] = dir;
179       count++;
180       if (count == 16) {
181          break;
182       }
183    }
184    UnlockRes();
185    
186    if (count == 0) {
187       csprint("Error : No director defined in config file.\n");
188       csprint(NULL, CS_END);
189       csprint(NULL, CS_DISCONNECTED);
190       csprint(NULL, CS_TERMINATED);
191       #ifdef HAVE_WIN32
192          Exit();
193       #endif
194       return NULL;
195    }
196    else if (count == 1) {
197       directorchoosen = 1;
198    }
199    else {
200       while (true) {
201          csprint("Multiple directors found in your config file.\n");
202          for (int i = 0; i < count; i++) {
203             if (i < 9) {
204                csprint(wxString("    ") << (i+1) << ": " << res[i]->hdr.name << "\n");
205             }
206             else {
207                csprint(wxString("   ") <<  (i+1) << ": " << res[i]->hdr.name << "\n");
208             }
209          }
210          csprint(wxString("Please choose a director (1-") << count << ") : ");
211          csprint(NULL, CS_PROMPT);
212          choosingdirector = true;
213          directorchoosen = -1;
214          while(directorchoosen == -1) {
215             bmicrosleep(0, 2000);
216             Yield();
217          }      
218          choosingdirector = false;
219          if (directorchoosen != 0) {
220             break;
221          }
222       }
223    }
224
225    memset(&jcr, 0, sizeof(jcr));
226    
227    jcr.dequeuing = 1; /* TODO: catch messages */
228
229    UA_sock = bnet_connect(&jcr, 3, 3, "Director daemon",
230       res[directorchoosen-1]->address, NULL, res[directorchoosen-1]->DIRport, 0);
231       
232    if (UA_sock == NULL) {
233       csprint("Failed to connect to the director\n");
234       csprint(NULL, CS_END);
235       csprint(NULL, CS_DISCONNECTED);
236       csprint(NULL, CS_TERMINATED);
237       #ifdef HAVE_WIN32
238          Exit();
239       #endif
240       return NULL;
241    }
242
243    csprint("Connected\n");
244
245    jcr.dir_bsock = UA_sock;
246    LockRes();
247    /* If cons==NULL, default console will be used */
248    CONRES *cons = (CONRES *)GetNextRes(R_CONSOLE, (RES *)NULL);
249    UnlockRes();
250    if (!authenticate_director(&jcr, res[directorchoosen-1], cons)) {
251       csprint("ERR=");
252       csprint(UA_sock->msg);
253       csprint(NULL, CS_END);
254       csprint(NULL, CS_DISCONNECTED);
255       csprint(NULL, CS_TERMINATED);
256       #ifdef HAVE_WIN32
257          Exit();
258       #endif
259       return NULL;
260    }
261    
262    csprint(NULL, CS_CONNECTED);
263    
264    Write(".messages\n");
265
266    int stat;
267
268    /* main loop */
269    while(!TestDestroy()) {   /* Tests if thread has been ended */
270       if ((stat = bnet_recv(UA_sock)) >= 0) {
271          csprint(UA_sock->msg);
272       }
273       else if (stat == BNET_SIGNAL) {
274          if (UA_sock->msglen == BNET_PROMPT) {
275             csprint(NULL, CS_PROMPT);
276          }
277          else if (UA_sock->msglen == BNET_EOD) {
278             csprint(NULL, CS_END);
279          }
280          else if (UA_sock->msglen == BNET_HEARTBEAT) {
281             bnet_sig(UA_sock, BNET_HB_RESPONSE);
282             csprint("<< Heartbeat signal received, answered. >>\n", CS_DEBUG);
283          }
284          else {
285             csprint("<< Unexpected signal received : ", CS_DEBUG);
286             csprint(bnet_sig_to_ascii(UA_sock), CS_DEBUG);
287             csprint(">>\n", CS_DEBUG);
288          }
289       }
290       else { /* BNET_HARDEOF || BNET_ERROR */
291          csprint(NULL, CS_END);
292          break;
293       }
294            
295       if (is_bnet_stop(UA_sock)) {
296          csprint(NULL, CS_END);
297          break;            /* error or term */
298       }
299    }
300    
301    csprint(NULL, CS_DISCONNECTED);
302
303    csprint("Connection terminated\n");
304    
305    UA_sock = NULL;
306
307    csprint(NULL, CS_TERMINATED);
308
309    #ifdef HAVE_WIN32
310       Exit();
311    #endif
312    
313    return NULL;
314 }
315
316 void console_thread::Write(const char* str) {
317    if (UA_sock) {
318        UA_sock->msglen = strlen(str);
319        pm_strcpy(&UA_sock->msg, str);
320        bnet_send(UA_sock);
321    }
322    else if (choosingdirector) {
323       wxString number = str;
324       number.RemoveLast(); /* Removes \n */
325       long val;
326       if (number.ToLong(&val)) {
327          directorchoosen = (int)val;
328       }
329       else {
330          directorchoosen = 0;
331       }
332    }
333 }
334
335 void console_thread::Delete() {
336    Write("quit\n");
337    if (UA_sock) {
338       bnet_sig(UA_sock, BNET_TERMINATE); /* send EOF */
339       bnet_close(UA_sock);
340       UA_sock = NULL;
341       /*csprint(NULL, CS_END);
342       csprint(NULL, CS_DISCONNECTED);
343       csprint(NULL, CS_TERMINATED);*/
344    }
345 }