]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/dird/ua_server.c
Remove new bnet_sig
[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 extern int console_msg_pending;
32 extern char my_name[];
33
34
35 /* Forward referenced functions */
36 extern "C" void *connect_thread(void *arg);
37 static void *handle_UA_client_request(void *arg);
38
39
40 /* Global variables */
41 static int started = FALSE;
42 static workq_t ua_workq;
43
44 struct s_addr_port {
45    char *addr;
46    char *port;
47 };
48
49 /* Called here by Director daemon to start UA (user agent)
50  * command thread. This routine creates the thread and then
51  * returns.
52  */
53 void start_UA_server(dlist *addrs)
54 {
55    pthread_t thid;
56    int status;
57    static dlist *myaddrs = addrs;
58
59    if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) {
60       berrno be;
61       Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.strerror(status));
62    }
63    started = TRUE;
64    return;
65 }
66
67 extern "C"
68 void *connect_thread(void *arg)
69 {
70    pthread_detach(pthread_self());
71
72    /* Permit 10 console connections */
73    bnet_thread_server((dlist*)arg, 10, &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->JobType = job_type;
98    jcr->JobLevel = L_NONE;
99    jcr->JobStatus = 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
114    pthread_detach(pthread_self());
115
116    jcr = new_control_jcr("*Console*", JT_CONSOLE);
117
118    ua = new_ua_context(jcr);
119    ua->UA_sock = (BSOCK *)arg;
120
121    bnet_recv(ua->UA_sock);          /* Get first message */
122    if (!authenticate_user_agent(ua)) {
123       goto getout;
124    }
125
126    while (!ua->quit) {
127       stat = bnet_recv(ua->UA_sock);
128       if (stat >= 0) {
129          pm_strcpy(ua->cmd, ua->UA_sock->msg);
130          parse_ua_args(ua);
131          if (ua->argc > 0 && ua->argk[0][0] == '.') {
132             do_a_dot_command(ua, ua->cmd);
133          } else {
134             do_a_command(ua, ua->cmd);
135          }
136          if (!ua->quit) {
137             if (ua->auto_display_messages) {
138                pm_strcpy(ua->cmd, "messages");
139                qmessagescmd(ua, ua->cmd);
140                ua->user_notified_msg_pending = FALSE;
141             } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) {
142                bsendmsg(ua, _("You have messages.\n"));
143                ua->user_notified_msg_pending = TRUE;
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 = 1;
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 }