]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_server.c
kes Require a messages command acl to be able to receive messages
[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-2006 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 (acl_access_ok(ua, Command_ACL, "messages", 8)) {
136                if (ua->auto_display_messages) {
137                   pm_strcpy(ua->cmd, "messages");
138                   qmessagescmd(ua, ua->cmd);
139                   ua->user_notified_msg_pending = FALSE;
140                } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) {
141                   bsendmsg(ua, _("You have messages.\n"));
142                   ua->user_notified_msg_pending = TRUE;
143                }
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       } else { /* signal */
150          bnet_sig(ua->UA_sock, BNET_POLL);
151       }
152    }
153
154 getout:
155    close_db(ua);
156    free_ua_context(ua);
157    free_jcr(jcr);
158
159    return NULL;
160 }
161
162 /*
163  * Create a UAContext for a Job that is running so that
164  *   it can the User Agent routines and
165  *   to ensure that the Job gets the proper output.
166  *   This is a sort of mini-kludge, and should be
167  *   unified at some point.
168  */
169 UAContext *new_ua_context(JCR *jcr)
170 {
171    UAContext *ua;
172
173    ua = (UAContext *)malloc(sizeof(UAContext));
174    memset(ua, 0, sizeof(UAContext));
175    ua->jcr = jcr;
176    ua->db = jcr->db;
177    ua->cmd = get_pool_memory(PM_FNAME);
178    ua->args = get_pool_memory(PM_FNAME);
179    ua->verbose = true;
180    ua->automount = true;
181    return ua;
182 }
183
184 void free_ua_context(UAContext *ua)
185 {
186    if (ua->cmd) {
187       free_pool_memory(ua->cmd);
188    }
189    if (ua->args) {
190       free_pool_memory(ua->args);
191    }
192    if (ua->prompt) {
193       free(ua->prompt);
194    }
195
196    if (ua->UA_sock) {
197       bnet_close(ua->UA_sock);
198       ua->UA_sock = NULL;
199    }
200    free(ua);
201 }
202
203
204 /*
205  * Called from main Bacula thread
206  */
207 void term_ua_server()
208 {
209    if (!started) {
210       return;
211    }
212 }