]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_server.c
1c6da1fbefe337e5ecb567aa61027f7253adb25f
[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-2004 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
35 /* Imported variables */
36 extern int r_first;
37 extern int r_last;
38 extern struct s_res resources[];
39 extern int console_msg_pending;
40 extern char my_name[];
41
42 /* Static variables */
43
44 /* Exported variables */
45 int quit_cmd_thread = 0;
46
47 /* Imported functions */
48
49 /* Forward referenced functions */
50
51 extern "C" void *connect_thread(void *arg);
52
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    char *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(dlist *addrs)
70 {
71    pthread_t thid;
72    int status;
73    static dlist *myaddrs = addrs;
74
75    if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) {
76       berrno be;
77       be.set_errno(status);
78       Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.strerror());
79    }
80    started = TRUE;
81    return;
82 }
83
84 extern "C" 
85 void *connect_thread(void *arg)
86 {
87    pthread_detach(pthread_self());
88
89    /*  ****FIXME**** put # 10 (timeout) on config parameter */
90    bnet_thread_server((dlist*)arg, 10, &ua_workq, handle_UA_client_request);
91    return NULL;
92 }
93
94 /*
95  * Create a Job Control Record for a control "job",
96  *   filling in all the appropriate fields.
97  */
98 JCR *new_control_jcr(const char *base_name, int job_type)
99 {
100    JCR *jcr;
101    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
102    /*
103     * The job and defaults are not really used, but
104     *  we set them up to ensure that everything is correctly
105     *  initialized.
106     */
107    LockRes();
108    jcr->job = (JOB *)GetNextRes(R_JOB, NULL);
109    set_jcr_defaults(jcr, jcr->job);
110    UnlockRes();
111    jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
112    create_unique_job_name(jcr, base_name);
113    jcr->sched_time = jcr->start_time;
114    jcr->JobType = job_type;
115    jcr->JobLevel = L_NONE;
116    jcr->JobStatus = JS_Running;
117    jcr->JobId = 0;
118    return jcr;
119 }
120
121 /*
122  * Handle Director User Agent commands   
123  *
124  */
125 static void *handle_UA_client_request(void *arg)
126 {
127    int stat;
128    UAContext *ua;
129    JCR *jcr;
130    BSOCK *UA_sock = (BSOCK *)arg;
131
132    pthread_detach(pthread_self());
133
134    jcr = new_control_jcr("*Console*", JT_CONSOLE);
135
136    ua = new_ua_context(jcr);
137    ua->UA_sock = UA_sock;
138
139    bnet_recv(ua->UA_sock);          /* Get first message */
140    if (!authenticate_user_agent(ua)) {
141       goto getout;
142    }
143
144    while (!ua->quit) {
145       stat = bnet_recv(ua->UA_sock);
146       if (stat >= 0) {
147          pm_strcpy(ua->cmd, ua->UA_sock->msg);
148          parse_ua_args(ua);
149          if (ua->argc > 0 && ua->argk[0][0] == '.') {
150             do_a_dot_command(ua, ua->cmd);
151          } else {
152             do_a_command(ua, ua->cmd);
153          }
154          if (!ua->quit) {
155             if (ua->auto_display_messages) {
156                strcpy(ua->cmd, "messages");
157                qmessagescmd(ua, ua->cmd);
158                ua->user_notified_msg_pending = FALSE;
159             } else if (!ua->user_notified_msg_pending && console_msg_pending) {
160                bsendmsg(ua, _("You have messages.\n"));
161                ua->user_notified_msg_pending = TRUE;
162             }
163             bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */
164          }
165       } else if (is_bnet_stop(ua->UA_sock)) {
166          ua->quit = true;
167       } else { /* signal */
168          bnet_sig(ua->UA_sock, BNET_POLL);
169       }
170    }
171
172 getout:
173    close_db(ua);
174    free_ua_context(ua);
175    free_jcr(jcr);
176
177    return NULL;
178 }
179
180 /*
181  * Create a UAContext for a Job that is running so that
182  *   it can the User Agent routines and    
183  *   to ensure that the Job gets the proper output.
184  *   This is a sort of mini-kludge, and should be
185  *   unified at some point.
186  */
187 UAContext *new_ua_context(JCR *jcr)
188 {
189    UAContext *ua;
190
191    ua = (UAContext *)malloc(sizeof(UAContext));
192    memset(ua, 0, sizeof(UAContext));
193    ua->jcr = jcr;
194    ua->db = jcr->db;
195    ua->cmd = get_pool_memory(PM_FNAME);
196    ua->args = get_pool_memory(PM_FNAME);
197    ua->verbose = 1;
198    ua->automount = TRUE;
199    return ua;
200 }
201
202 void free_ua_context(UAContext *ua)
203 {
204    if (ua->cmd) {
205       free_pool_memory(ua->cmd);
206    }
207    if (ua->args) {
208       free_pool_memory(ua->args);
209    }
210    if (ua->prompt) {
211       free(ua->prompt);
212    }
213
214    if (ua->UA_sock) {
215       bnet_close(ua->UA_sock);
216    }
217    free(ua);
218 }
219
220
221 /*
222  * Called from main Bacula thread 
223  */
224 void term_ua_server()
225 {
226    if (!started) {
227       return;
228    }
229    quit_cmd_thread = TRUE;
230 }