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