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