]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_server.c
BFILE I/O, new console @ commands, regression, file mode restore fixes
[bacula/bacula] / bacula / src / dird / ua_server.c
1 /*
2  *
3  *   Bacula Director -- User Agent Server
4  *
5  *     Kern Sibbald, September MM
6  *
7  *    Version $Id$
8  */
9
10 /*
11    Copyright (C) 2000-2003 Kern Sibbald and John Walker
12
13    This program is free software; you can redistribute it and/or
14    modify it under the terms of the GNU General Public License as
15    published by the Free Software Foundation; either version 2 of
16    the License, or (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21    General Public License for more details.
22
23    You should have received a copy of the GNU General Public
24    License along with this program; if not, write to the Free
25    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
26    MA 02111-1307, USA.
27
28  */
29
30 #include "bacula.h"
31 #include "dird.h"
32
33 /* Imported subroutines */
34 extern void run_job(JCR *jcr);
35
36 /* Imported variables */
37 extern int r_first;
38 extern int r_last;
39 extern struct s_res resources[];
40 extern int console_msg_pending;
41 extern char my_name[];
42
43 /* Static variables */
44
45 /* Exported variables */
46 int quit_cmd_thread = 0;
47
48 /* Imported functions */
49
50 /* Forward referenced functions */
51
52 static void *connect_thread(void *arg);
53 static void *handle_UA_client_request(void *arg);
54
55
56 /* Global variables */
57 static int started = FALSE;
58 static workq_t ua_workq;
59
60 struct s_addr_port {
61    char *addr;
62    int port;
63 };
64
65 /* Called here by Director daemon to start UA (user agent)
66  * command thread. This routine creates the thread and then
67  * returns.
68  */
69 void start_UA_server(char *UA_addr, int UA_port)
70 {
71    pthread_t thid;
72    int status;
73    static struct s_addr_port arg;
74
75    arg.port = UA_port;
76    arg.addr = UA_addr;
77    if ((status=pthread_create(&thid, NULL, connect_thread, (void *)&arg)) != 0) {
78       Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), strerror(status));
79    }
80    started = TRUE;
81    return;
82 }
83
84 static void *connect_thread(void *arg)
85 {
86    struct s_addr_port *UA = (struct s_addr_port *)arg;
87
88    pthread_detach(pthread_self());
89
90    /*  ****FIXME**** put # 5 on config parameter */
91    bnet_thread_server(UA->addr, UA->port, 5, &ua_workq, handle_UA_client_request);
92    return NULL;
93 }
94
95 /*
96  * Handle Director User Agent commands   
97  *
98  */
99 static void *handle_UA_client_request(void *arg)
100 {
101    int stat;
102    UAContext ua;
103    BSOCK *UA_sock = (BSOCK *) arg;
104
105    pthread_detach(pthread_self());
106
107    memset(&ua, 0, sizeof(ua));
108    ua.automount = TRUE;
109    ua.verbose = 1;
110    ua.jcr = new_jcr(sizeof(JCR), dird_free_jcr);
111    ua.jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
112    ua.UA_sock = UA_sock;
113    ua.cmd = get_pool_memory(PM_FNAME);
114    ua.args = get_pool_memory(PM_FNAME);
115
116    create_unique_job_name(ua.jcr, "*Console*");
117    ua.jcr->sched_time = ua.jcr->start_time;
118    ua.jcr->JobType = JT_CONSOLE;
119
120    bnet_recv(ua.UA_sock);          /* Get first message */
121    if (!authenticate_user_agent(ua.UA_sock)) {
122       goto getout;
123    }
124
125    while (!ua.quit) {
126       stat = bnet_recv(ua.UA_sock);
127       if (stat >= 0) {
128          ua.cmd = check_pool_memory_size(ua.cmd, ua.UA_sock->msglen+1);
129          bstrncpy(ua.cmd, ua.UA_sock->msg, ua.UA_sock->msglen+1);
130          parse_ua_args(&ua);
131          if (ua.argc > 0 && ua.argk[0][0] == '.') {
132             do_a_dot_command(&ua, ua.cmd);
133          } else {
134             do_a_command(&ua, ua.cmd);
135          }
136          if (!ua.quit) {
137             if (ua.auto_display_messages) {
138                strcpy(ua.cmd, "messages");
139                qmessagescmd(&ua, ua.cmd);
140                ua.user_notified_msg_pending = FALSE;
141             } else if (!ua.user_notified_msg_pending && console_msg_pending) {
142                bsendmsg(&ua, _("You have messages.\n"));
143                ua.user_notified_msg_pending = TRUE;
144             }
145             bnet_sig(ua.UA_sock, BNET_EOD); /* send end of command */
146          }
147       } else if (is_bnet_stop(ua.UA_sock)) {
148          ua.quit = TRUE;
149          break;
150       } else { /* signal */
151          bnet_sig(ua.UA_sock, BNET_POLL);
152       }
153    }
154
155 getout:
156    if (ua.UA_sock) {
157       bnet_close(ua.UA_sock);
158       ua.UA_sock = NULL;
159    }
160
161    close_db(&ua);                     /* do this before freeing JCR */
162
163    if (ua.jcr) {
164       free_jcr(ua.jcr);
165       ua.jcr = NULL;
166    }
167    if (ua.prompt) {
168       free(ua.prompt);
169    }
170    if (ua.cmd) {
171       free_pool_memory(ua.cmd);
172    }
173    if (ua.args) {
174       free_pool_memory(ua.args);
175    }
176    return NULL;
177 }
178
179 /*
180  * Called from main Bacula thread 
181  */
182 void term_ua_server()
183 {
184    if (!started) {
185       return;
186    }
187    quit_cmd_thread = TRUE;
188 }