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