3 * Bacula Director -- User Agent Server
5 * Kern Sibbald, September MM
10 Copyright (C) 2000-2005 Kern Sibbald
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.
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.
27 /* Imported variables */
30 extern struct s_res resources[];
31 extern int console_msg_pending;
32 extern char my_name[];
35 /* Forward referenced functions */
36 extern "C" void *connect_thread(void *arg);
37 static void *handle_UA_client_request(void *arg);
40 /* Global variables */
41 static int started = FALSE;
42 static workq_t ua_workq;
49 /* Called here by Director daemon to start UA (user agent)
50 * command thread. This routine creates the thread and then
53 void start_UA_server(dlist *addrs)
57 static dlist *myaddrs = addrs;
59 if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) {
61 Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.strerror(status));
68 void *connect_thread(void *arg)
70 pthread_detach(pthread_self());
72 /* Permit 10 console connections */
73 bnet_thread_server((dlist*)arg, 10, &ua_workq, handle_UA_client_request);
78 * Create a Job Control Record for a control "job",
79 * filling in all the appropriate fields.
81 JCR *new_control_jcr(const char *base_name, int job_type)
84 jcr = new_jcr(sizeof(JCR), dird_free_jcr);
86 * The job and defaults are not really used, but
87 * we set them up to ensure that everything is correctly
91 jcr->job = (JOB *)GetNextRes(R_JOB, NULL);
92 set_jcr_defaults(jcr, jcr->job);
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 set_jcr_job_status(jcr, JS_Running);
105 * Handle Director User Agent commands
108 static void *handle_UA_client_request(void *arg)
114 pthread_detach(pthread_self());
116 jcr = new_control_jcr("*Console*", JT_CONSOLE);
118 ua = new_ua_context(jcr);
119 ua->UA_sock = (BSOCK *)arg;
121 bnet_recv(ua->UA_sock); /* Get first message */
122 if (!authenticate_user_agent(ua)) {
127 stat = bnet_recv(ua->UA_sock);
129 pm_strcpy(ua->cmd, ua->UA_sock->msg);
131 if (ua->argc > 0 && ua->argk[0][0] == '.') {
132 do_a_dot_command(ua, ua->cmd);
134 do_a_command(ua, ua->cmd);
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;
145 bnet_sig(ua->UA_sock, BNET_EOD); /* send end of command */
147 } else if (is_bnet_stop(ua->UA_sock)) {
149 } else { /* signal */
150 bnet_sig(ua->UA_sock, BNET_POLL);
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.
169 UAContext *new_ua_context(JCR *jcr)
173 ua = (UAContext *)malloc(sizeof(UAContext));
174 memset(ua, 0, sizeof(UAContext));
177 ua->cmd = get_pool_memory(PM_FNAME);
178 ua->args = get_pool_memory(PM_FNAME);
180 ua->automount = TRUE;
184 void free_ua_context(UAContext *ua)
187 free_pool_memory(ua->cmd);
190 free_pool_memory(ua->args);
197 bnet_close(ua->UA_sock);
205 * Called from main Bacula thread
207 void term_ua_server()