X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=bacula%2Fsrc%2Fdird%2Fua_server.c;h=b602e0a1e0e7e63989e8cfcaedc9c3462fcc067a;hb=87187e5526cf427d78cbc3763a8d15df70c2ea3b;hp=75a09d86c458fa39a84adf47a950a3fff66eb3b2;hpb=da9f0514d42ea9e9774ac191efa6d6f77a6363f5;p=bacula%2Fbacula diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index 75a09d86c4..b602e0a1e0 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -1,185 +1,234 @@ /* - * - * Bacula Director -- User Agent Server - * - * Kern Sibbald, September MM - */ + Bacula® - The Network Backup Solution -/* - Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker + Copyright (C) 2000-2007 Free Software Foundation Europe e.V. - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of - the License, or (at your option) any later version. + The main author of Bacula is Kern Sibbald, with contributions from + many others, a complete list can be found in the file AUTHORS. + This program is Free Software; you can redistribute it and/or + modify it under the terms of version three of the GNU Affero General Public + License as published by the Free Software Foundation and included + in the file LICENSE. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - You should have received a copy of the GNU General Public - License along with this program; if not, write to the Free - Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, - MA 02111-1307, USA. + You should have received a copy of the GNU Affero General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. + Bacula® is a registered trademark of Kern Sibbald. + The licensor of Bacula is the Free Software Foundation Europe + (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich, + Switzerland, email:ftf@fsfeurope.org. +*/ +/* + * + * Bacula Director -- User Agent Server + * + * Kern Sibbald, September MM + * + * Version $Id$ */ #include "bacula.h" #include "dird.h" -#include "ua.h" - -/* Imported subroutines */ -extern void run_job(JCR *jcr); /* Imported variables */ -extern int r_first; -extern int r_last; -extern struct s_res resources[]; -extern int console_msg_pending; -extern FILE *con_fd; -extern char my_name[]; - -/* Static variables */ - -/* Exported variables */ -int quit_cmd_thread = 0; -/* Imported functions */ /* Forward referenced functions */ - -static void *connect_thread(void *arg); -static void handle_UA_client_request(void *arg); +extern "C" void *connect_thread(void *arg); +static void *handle_UA_client_request(void *arg); /* Global variables */ static int started = FALSE; static workq_t ua_workq; +struct s_addr_port { + char *addr; + char *port; +}; + /* Called here by Director daemon to start UA (user agent) * command thread. This routine creates the thread and then * returns. */ -void start_UA_server(int UA_port) +void start_UA_server(dlist *addrs) { pthread_t thid; int status; + static dlist *myaddrs = addrs; - set_thread_concurrency(4); - if ((status=pthread_create(&thid, NULL, connect_thread, (void *)UA_port)) != 0) { - Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), strerror(status)); + if ((status=pthread_create(&thid, NULL, connect_thread, (void *)myaddrs)) != 0) { + berrno be; + Emsg1(M_ABORT, 0, _("Cannot create UA thread: %s\n"), be.bstrerror(status)); } started = TRUE; return; } -static void *connect_thread(void *arg) +extern "C" +void *connect_thread(void *arg) { - int UA_port = (int)arg; - pthread_detach(pthread_self()); + set_jcr_in_tsd(INVALID_JCR); - bnet_thread_server(UA_port, 5, &ua_workq, handle_UA_client_request); + /* Permit MaxConsoleConnect console connections */ + bnet_thread_server((dlist*)arg, director->MaxConsoleConnect, &ua_workq, handle_UA_client_request); return NULL; } /* - * Handle Director User Agent commands + * Create a Job Control Record for a control "job", + * filling in all the appropriate fields. + */ +JCR *new_control_jcr(const char *base_name, int job_type) +{ + JCR *jcr; + jcr = new_jcr(sizeof(JCR), dird_free_jcr); + /* + * The job and defaults are not really used, but + * we set them up to ensure that everything is correctly + * initialized. + */ + LockRes(); + jcr->job = (JOB *)GetNextRes(R_JOB, NULL); + set_jcr_defaults(jcr, jcr->job); + UnlockRes(); + jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */ + create_unique_job_name(jcr, base_name); + jcr->sched_time = jcr->start_time; + jcr->setJobType(job_type); + jcr->setJobLevel(L_NONE); + jcr->setJobStatus(JS_Running); + jcr->JobId = 0; + return jcr; +} + +/* + * Handle Director User Agent commands * */ -static void handle_UA_client_request(void *arg) +static void *handle_UA_client_request(void *arg) { - int quit, stat; - static char cmd[1000]; - UAContext ua; - BSOCK *UA_sock = (BSOCK *) arg; + int stat; + UAContext *ua; + JCR *jcr; + BSOCK *user = (BSOCK *)arg; pthread_detach(pthread_self()); - memset(&ua, 0, sizeof(ua)); - ua.automount = TRUE; - ua.jcr = new_jcr(sizeof(JCR), dird_free_jcr); - close_msg(ua.jcr); /* we don't handle messages */ - ua.jcr->sd_auth_key = bstrdup("dummy"); /* dummy Storage daemon key */ - ua.UA_sock = UA_sock; - ua.cmd = (char *) get_pool_memory(PM_FNAME); - ua.args = (char *) get_pool_memory(PM_FNAME); - - create_unique_job_name(ua.jcr, "*Console*"); - ua.jcr->sched_time = ua.jcr->start_time; - ua.jcr->JobType = JT_CONSOLE; - - bnet_recv(ua.UA_sock); /* Get first message */ - if (!authenticate_user_agent(ua.UA_sock)) { + jcr = new_control_jcr("-Console-", JT_CONSOLE); + + ua = new_ua_context(jcr); + ua->UA_sock = user; + set_jcr_in_tsd(INVALID_JCR); + + user->recv(); /* Get first message */ + if (!authenticate_user_agent(ua)) { goto getout; } - quit = FALSE; - while (!quit) { - stat = bnet_recv(ua.UA_sock); - if (stat > 0) { - strncpy(cmd, ua.UA_sock->msg, sizeof(cmd)); - cmd[sizeof(cmd)-1] = 0; /* ensure it is terminated/trucated */ - parse_command_args(&ua); - if (ua.argc > 0 && ua.argk[0][0] == '.') { - quit = !do_a_dot_command(&ua, cmd); - } else { - quit = !do_a_command(&ua, cmd); - } - if (!quit) { - if (ua.auto_display_messages) { - strcpy(cmd, "messages"); - qmessagescmd(&ua, cmd); - ua.user_notified_msg_pending = FALSE; - } else if (!ua.user_notified_msg_pending && console_msg_pending) { - bsendmsg(&ua, _("You have messages.\n")); - ua.user_notified_msg_pending = TRUE; - } - bnet_sig(ua.UA_sock, BNET_EOD); /* send end of command */ - } - } else if (stat == 0) { - if (ua.UA_sock->msglen == BNET_TERMINATE) { - quit = TRUE; - break; - } - bnet_sig(ua.UA_sock, BNET_POLL); - } else { - break; /* error, exit */ + while (!ua->quit) { + if (ua->api) user->signal(BNET_MAIN_PROMPT); + stat = user->recv(); + if (stat >= 0) { + pm_strcpy(ua->cmd, ua->UA_sock->msg); + parse_ua_args(ua); + if (ua->argc > 0 && ua->argk[0][0] == '.') { + do_a_dot_command(ua); + } else { + do_a_command(ua); + } + dequeue_messages(ua->jcr); + if (!ua->quit) { + if (console_msg_pending && acl_access_ok(ua, Command_ACL, "messages", 8)) { + if (ua->auto_display_messages) { + pm_strcpy(ua->cmd, "messages"); + qmessagescmd(ua, ua->cmd); + ua->user_notified_msg_pending = false; + } else if (!ua->gui && !ua->user_notified_msg_pending && console_msg_pending) { + if (ua->api) { + user->signal(BNET_MSGS_PENDING); + } else { + bsendmsg(ua, _("You have messages.\n")); + } + ua->user_notified_msg_pending = true; + } + } + if (!ua->api) user->signal(BNET_EOD); /* send end of command */ + } + } else if (is_bnet_stop(user)) { + ua->quit = true; + } else { /* signal */ + user->signal(BNET_POLL); } } getout: - if (ua.UA_sock) { - bnet_close(ua.UA_sock); - ua.UA_sock = NULL; - } + close_db(ua); + free_ua_context(ua); + free_jcr(jcr); + + return NULL; +} - close_db(&ua); /* do this before freeing JCR */ +/* + * Create a UAContext for a Job that is running so that + * it can the User Agent routines and + * to ensure that the Job gets the proper output. + * This is a sort of mini-kludge, and should be + * unified at some point. + */ +UAContext *new_ua_context(JCR *jcr) +{ + UAContext *ua; + + ua = (UAContext *)malloc(sizeof(UAContext)); + memset(ua, 0, sizeof(UAContext)); + ua->jcr = jcr; + ua->db = jcr->db; + ua->cmd = get_pool_memory(PM_FNAME); + ua->args = get_pool_memory(PM_FNAME); + ua->errmsg = get_pool_memory(PM_FNAME); + ua->verbose = true; + ua->automount = true; + return ua; +} - if (ua.jcr) { - free_jcr(ua.jcr); - ua.jcr = NULL; +void free_ua_context(UAContext *ua) +{ + if (ua->cmd) { + free_pool_memory(ua->cmd); } - if (ua.prompt) { - free(ua.prompt); + if (ua->args) { + free_pool_memory(ua->args); } - if (ua.cmd) { - free_pool_memory(ua.cmd); + if (ua->errmsg) { + free_pool_memory(ua->errmsg); } - if (ua.args) { - free_pool_memory(ua.args); + if (ua->prompt) { + free(ua->prompt); } - return; + if (ua->UA_sock) { + bnet_close(ua->UA_sock); + ua->UA_sock = NULL; + } + free(ua); } + /* - * Called from main Bacula thread + * Called from main Bacula thread */ void term_ua_server() { if (!started) { return; } - quit_cmd_thread = TRUE; }