]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_server.c
eb5c586770eb08f03c72b9b3cca4be35acdb4dab
[bacula/bacula] / bacula / src / dird / ua_server.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2015 Kern Sibbald
5    Copyright (C) 2000-2014 Free Software Foundation Europe e.V.
6
7    The original author of Bacula is Kern Sibbald, with contributions
8    from many others, a complete list can be found in the file AUTHORS.
9
10    You may use this file and others of this release according to the
11    license defined in the LICENSE file, which includes the Affero General
12    Public License, v3.0 ("AGPLv3") and some additional permissions and
13    terms pursuant to its AGPLv3 Section 7.
14
15    This notice must be preserved when any source code is 
16    conveyed and/or propagated.
17
18    Bacula(R) is a registered trademark of Kern Sibbald.
19 */
20 /*
21  *
22  *   Bacula Director -- User Agent Server
23  *
24  *     Kern Sibbald, September MM
25  *
26  */
27
28 #include "bacula.h"
29 #include "dird.h"
30
31 /* Imported variables */
32
33
34 /* Forward referenced functions */
35 extern "C" void *connect_thread(void *arg);
36 static void *handle_UA_client_request(void *arg);
37
38
39 /* Global variables */
40 static int started = FALSE;
41 static workq_t ua_workq;
42
43 struct s_addr_port {
44    char *addr;
45    char *port;
46 };
47
48 /* Called here by Director daemon to start UA (user agent)
49  * command thread. This routine creates the thread and then
50  * returns.
51  */
52 void start_UA_server(dlist *addrs)
53 {
54    pthread_t thid;
55    int status;
56    static dlist *myaddrs = addrs;
57
58    if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) {
59       berrno be;
60       Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.bstrerror(status));
61    }
62    started = TRUE;
63    return;
64 }
65
66 extern "C"
67 void *connect_thread(void *arg)
68 {
69    pthread_detach(pthread_self());
70    set_jcr_in_tsd(INVALID_JCR);
71
72    /* Permit MaxConsoleConnect console connections */
73    bnet_thread_server((dlist*)arg, director->MaxConsoleConnect, &ua_workq, handle_UA_client_request);
74    return NULL;
75 }
76
77 /*
78  * Create a Job Control Record for a control "job",
79  *   filling in all the appropriate fields.
80  */
81 JCR *new_control_jcr(const char *base_name, int job_type)
82 {
83    JCR *jcr;
84    jcr = new_jcr(sizeof(JCR), dird_free_jcr);
85    /*
86     * The job and defaults are not really used, but
87     *  we set them up to ensure that everything is correctly
88     *  initialized.
89     */
90    LockRes();
91    jcr->job = (JOB *)GetNextRes(R_JOB, NULL);
92    set_jcr_defaults(jcr, jcr->job);
93    UnlockRes();
94    jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */
95    create_unique_job_name(jcr, base_name);
96    jcr->sched_time = jcr->start_time;
97    jcr->setJobType(job_type);
98    jcr->setJobLevel(L_NONE);
99    jcr->setJobStatus(JS_Running);
100    jcr->JobId = 0;
101    return jcr;
102 }
103
104 /*
105  * Handle Director User Agent commands
106  *
107  */
108 static void *handle_UA_client_request(void *arg)
109 {
110    int stat;
111    UAContext *ua;
112    JCR *jcr;
113    BSOCK *user = (BSOCK *)arg;
114
115    pthread_detach(pthread_self());
116
117    jcr = new_control_jcr("-Console-", JT_CONSOLE);
118
119    ua = new_ua_context(jcr);
120    ua->UA_sock = user;
121    set_jcr_in_tsd(INVALID_JCR);
122
123    user->recv();             /* Get first message */
124    if (!authenticate_user_agent(ua)) {
125       goto getout;
126    }
127
128    while (!ua->quit) {
129       if (ua->api) user->signal(BNET_MAIN_PROMPT);
130       stat = user->recv();
131       if (stat >= 0) {
132          pm_strcpy(ua->cmd, ua->UA_sock->msg);
133          parse_ua_args(ua);
134          if (ua->argc > 0 && ua->argk[0][0] == '.') {
135             do_a_dot_command(ua);
136          } else {
137             do_a_command(ua);
138          }
139          dequeue_messages(ua->jcr);
140          if (!ua->quit) {
141             if (console_msg_pending && acl_access_ok(ua, Command_ACL, "messages", 8)) {
142                if (ua->auto_display_messages) {
143                   pm_strcpy(ua->cmd, "messages");
144                   qmessagescmd(ua, ua->cmd);
145                   ua->user_notified_msg_pending = false;
146                } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) {
147                   if (ua->api) {
148                      user->signal(BNET_MSGS_PENDING);
149                   } else {
150                      bsendmsg(ua, _("You have messages.\n"));
151                   }
152                   ua->user_notified_msg_pending = true;
153                }
154             }
155             if (!ua->api) user->signal(BNET_EOD);     /* send end of command */
156          }
157       } else if (user->is_stop()) {
158          ua->quit = true;
159       } else { /* signal */
160          user->signal(BNET_POLL);
161       }
162
163       /* At the end of each command, revert to the main shared SQL link */
164       ua->db = ua->shared_db;
165    }
166
167 getout:
168    close_db(ua);
169    free_ua_context(ua);
170    free_jcr(jcr);
171
172    return NULL;
173 }
174
175 /*
176  * Create a UAContext for a Job that is running so that
177  *   it can the User Agent routines and
178  *   to ensure that the Job gets the proper output.
179  *   This is a sort of mini-kludge, and should be
180  *   unified at some point.
181  */
182 UAContext *new_ua_context(JCR *jcr)
183 {
184    UAContext *ua;
185
186    ua = (UAContext *)malloc(sizeof(UAContext));
187    memset(ua, 0, sizeof(UAContext));
188    ua->jcr = jcr;
189    ua->shared_db = ua->db = jcr->db;
190    ua->cmd = get_pool_memory(PM_FNAME);
191    ua->args = get_pool_memory(PM_FNAME);
192    ua->errmsg = get_pool_memory(PM_FNAME);
193    ua->verbose = true;
194    ua->automount = true;
195    return ua;
196 }
197
198 void free_ua_context(UAContext *ua)
199 {
200    if (ua->cmd) {
201       free_pool_memory(ua->cmd);
202    }
203    if (ua->args) {
204       free_pool_memory(ua->args);
205    }
206    if (ua->errmsg) {
207       free_pool_memory(ua->errmsg);
208    }
209    if (ua->prompt) {
210       free(ua->prompt);
211    }
212    if (ua->unique) {
213       free(ua->unique);
214    }
215    free_bsock(ua->UA_sock);
216    free(ua);
217 }
218
219
220 /*
221  * Called from main Bacula thread
222  */
223 void term_ua_server()
224 {
225    if (!started) {
226       return;
227    }
228 }