diff options
-rw-r--r-- | source3/Makefile.in | 1 | ||||
-rw-r--r-- | source3/include/printing.h | 2 | ||||
-rw-r--r-- | source3/printing/printing.c | 114 | ||||
-rw-r--r-- | source3/printing/queue_process.c | 294 | ||||
-rw-r--r-- | source3/printing/queue_process.h | 29 | ||||
-rw-r--r-- | source3/smbd/globals.c | 1 | ||||
-rw-r--r-- | source3/smbd/process.c | 4 | ||||
-rw-r--r-- | source3/smbd/proto.h | 2 | ||||
-rw-r--r-- | source3/smbd/server.c | 46 | ||||
-rw-r--r-- | source3/smbd/server_reload.c | 9 | ||||
-rwxr-xr-x | source3/wscript_build | 3 |
11 files changed, 339 insertions, 166 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in index f1fe0dd061..9bf3bc0399 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -972,6 +972,7 @@ PRINTBACKEND_OBJ = printing/printing.o \ printing/nt_printing_ads.o \ librpc/gen_ndr/ndr_ntprinting.o \ ../librpc/ndr/ndr_ntprinting.o \ + printing/queue_process.o \ $(PRINTBASE_OBJ) SMBD_OBJ = $(SMBD_OBJ_BASE) $(SMBD_OBJ_MAIN) diff --git a/source3/include/printing.h b/source3/include/printing.h index 0c81d07fbe..debf63f5e0 100644 --- a/source3/include/printing.h +++ b/source3/include/printing.h @@ -234,8 +234,6 @@ uint16 pjobid_to_rap(const char* sharename, uint32 jobid); bool rap_to_pjobid(uint16 rap_jobid, fstring sharename, uint32 *pjobid); void rap_jobid_delete(const char* sharename, uint32 jobid); bool print_backend_init(struct messaging_context *msg_ctx); -void start_background_queue(struct tevent_context *ev, - struct messaging_context *msg); void printing_end(void); /* The following definitions come from printing/lpq_parse.c */ diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 9dbd516940..f1e2aeb265 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -28,6 +28,7 @@ #include "../librpc/gen_ndr/netlogon.h" #include "printing/notify.h" #include "printing/pcap.h" +#include "printing/queue_process.h" #include "serverid.h" #include "smbd/smbd.h" #include "auth.h" @@ -1599,119 +1600,6 @@ void print_queue_receive(struct messaging_context *msg, return; } -static void printing_pause_fd_handler(struct tevent_context *ev, - struct tevent_fd *fde, - uint16_t flags, - void *private_data) -{ - /* - * If pause_pipe[1] is closed it means the parent smbd - * and children exited or aborted. - */ - exit_server_cleanly(NULL); -} - -extern struct child_pid *children; -extern int num_children; - -static void add_child_pid(pid_t pid) -{ - struct child_pid *child; - - child = SMB_MALLOC_P(struct child_pid); - if (child == NULL) { - DEBUG(0, ("Could not add child struct -- malloc failed\n")); - return; - } - child->pid = pid; - DLIST_ADD(children, child); - num_children += 1; -} - -static pid_t background_lpq_updater_pid = -1; - -/**************************************************************************** -main thread of the background lpq updater -****************************************************************************/ -void start_background_queue(struct tevent_context *ev, - struct messaging_context *msg_ctx) -{ - /* Use local variables for this as we don't - * need to save the parent side of this, just - * ensure it closes when the process exits. - */ - int pause_pipe[2]; - - DEBUG(3,("start_background_queue: Starting background LPQ thread\n")); - - if (pipe(pause_pipe) == -1) { - DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) )); - exit(1); - } - - background_lpq_updater_pid = sys_fork(); - - if (background_lpq_updater_pid == -1) { - DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) )); - exit(1); - } - - /* Track the printing pid along with other smbd children */ - add_child_pid(background_lpq_updater_pid); - - if(background_lpq_updater_pid == 0) { - struct tevent_fd *fde; - int ret; - NTSTATUS status; - - /* Child. */ - DEBUG(5,("start_background_queue: background LPQ thread started\n")); - - close(pause_pipe[0]); - pause_pipe[0] = -1; - - status = reinit_after_fork(msg_ctx, ev, procid_self(), true); - - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("reinit_after_fork() failed\n")); - smb_panic("reinit_after_fork() failed"); - } - - smbd_setup_sig_term_handler(); - smbd_setup_sig_hup_handler(ev, msg_ctx); - - if (!serverid_register(procid_self(), - FLAG_MSG_GENERAL|FLAG_MSG_SMBD - |FLAG_MSG_PRINT_GENERAL)) { - exit(1); - } - - if (!locking_init()) { - exit(1); - } - - messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE, - print_queue_receive); - - fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ, - printing_pause_fd_handler, - NULL); - if (!fde) { - DEBUG(0,("tevent_add_fd() failed for pause_pipe\n")); - smb_panic("tevent_add_fd() failed for pause_pipe"); - } - - DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n")); - ret = tevent_loop_wait(ev); - /* should not be reached */ - DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n", - ret, (ret == 0) ? "out of events" : strerror(errno))); - exit(1); - } - - close(pause_pipe[1]); -} - /**************************************************************************** update the internal database from the system print queue for a queue ****************************************************************************/ diff --git a/source3/printing/queue_process.c b/source3/printing/queue_process.c new file mode 100644 index 0000000000..9fbdd811ab --- /dev/null +++ b/source3/printing/queue_process.c @@ -0,0 +1,294 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + printing backend routines + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 2002 + Copyright (C) Simo Sorce 2011 + + 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 3 of the License, or + (at your option) any later version. + + 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, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/globals.h" +#include "include/messages.h" +#include "printing.h" +#include "printing/pcap.h" +#include "serverid.h" +#include "locking/proto.h" +#include "smbd/proto.h" + +/**************************************************************************** + Notify smbds of new printcap data +**************************************************************************/ +static void reload_pcap_change_notify(struct tevent_context *ev, + struct messaging_context *msg_ctx) +{ + message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL); +} + +static bool print_queue_housekeeping(const struct timeval *now, void *pvt) +{ + struct messaging_context *msg_ctx = + talloc_get_type_abort(pvt, struct messaging_context); + time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); + time_t t = time_mono(NULL); + + DEBUG(5, ("print queue housekeeping\n")); + + /* if periodic printcap rescan is enabled, + * see if it's time to reload */ + if ((printcap_cache_time != 0) && + (t >= (last_printer_reload_time + printcap_cache_time))) { + DEBUG( 3,( "Printcap cache time expired.\n")); + pcap_cache_reload(messaging_event_context(msg_ctx), + msg_ctx, + &reload_pcap_change_notify); + last_printer_reload_time = t; + } + + return true; +} + +static bool printing_subsystem_queue_tasks(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx) +{ + if (!(event_add_idle(ev_ctx, NULL, + timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0), + "print_queue_housekeeping", + print_queue_housekeeping, + msg_ctx))) { + DEBUG(0, ("Could not add print_queue_housekeeping event\n")); + return false; + } + + return true; +} + +static void bq_sig_term_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *private_data) +{ + exit_server_cleanly("termination signal"); +} + +void bq_setup_sig_term_handler(void) +{ + struct tevent_signal *se; + + se = tevent_add_signal(server_event_context(), + server_event_context(), + SIGTERM, 0, + bq_sig_term_handler, + NULL); + if (!se) { + exit_server("failed to setup SIGTERM handler"); + } +} + +static void bq_sig_hup_handler(struct tevent_context *ev, + struct tevent_signal *se, + int signum, + int count, + void *siginfo, + void *pvt) +{ + struct messaging_context *msg_ctx; + + msg_ctx = talloc_get_type_abort(pvt, struct messaging_context); + change_to_root_user(); + + DEBUG(1, ("Reloading pcap cache after SIGHUP\n")); + pcap_cache_reload(ev, msg_ctx, &reload_pcap_change_notify); +} + +static void bq_setup_sig_hup_handler(struct tevent_context *ev, + struct messaging_context *msg_ctx) +{ + struct tevent_signal *se; + + se = tevent_add_signal(ev, ev, SIGHUP, 0, bq_sig_hup_handler, + msg_ctx); + if (!se) { + exit_server("failed to setup SIGHUP handler"); + } +} + +static void bq_smb_conf_updated(struct messaging_context *msg_ctx, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct tevent_context *ev_ctx = + talloc_get_type_abort(private_data, struct tevent_context); + + DEBUG(10,("smb_conf_updated: Got message saying smb.conf was " + "updated. Reloading.\n")); + change_to_root_user(); + pcap_cache_reload(ev_ctx, msg_ctx, &reload_pcap_change_notify); +} + +static void printing_pause_fd_handler(struct tevent_context *ev, + struct tevent_fd *fde, + uint16_t flags, + void *private_data) +{ + /* + * If pause_pipe[1] is closed it means the parent smbd + * and children exited or aborted. + */ + exit_server_cleanly(NULL); +} + +extern struct child_pid *children; +extern int num_children; + +static void add_child_pid(pid_t pid) +{ + struct child_pid *child; + + child = SMB_MALLOC_P(struct child_pid); + if (child == NULL) { + DEBUG(0, ("Could not add child struct -- malloc failed\n")); + return; + } + child->pid = pid; + DLIST_ADD(children, child); + num_children += 1; +} + +pid_t background_lpq_updater_pid = -1; + +/**************************************************************************** +main thread of the background lpq updater +****************************************************************************/ +static void start_background_queue(struct tevent_context *ev, + struct messaging_context *msg_ctx) +{ + /* Use local variables for this as we don't + * need to save the parent side of this, just + * ensure it closes when the process exits. + */ + int pause_pipe[2]; + + DEBUG(3,("start_background_queue: Starting background LPQ thread\n")); + + if (pipe(pause_pipe) == -1) { + DEBUG(5,("start_background_queue: cannot create pipe. %s\n", strerror(errno) )); + exit(1); + } + + background_lpq_updater_pid = sys_fork(); + + if (background_lpq_updater_pid == -1) { + DEBUG(5,("start_background_queue: background LPQ thread failed to start. %s\n", strerror(errno) )); + exit(1); + } + + /* Track the printing pid along with other smbd children */ + add_child_pid(background_lpq_updater_pid); + + if(background_lpq_updater_pid == 0) { + struct tevent_fd *fde; + int ret; + NTSTATUS status; + + /* Child. */ + DEBUG(5,("start_background_queue: background LPQ thread started\n")); + + close(pause_pipe[0]); + pause_pipe[0] = -1; + + status = reinit_after_fork(msg_ctx, ev, procid_self(), true); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("reinit_after_fork() failed\n")); + smb_panic("reinit_after_fork() failed"); + } + + bq_setup_sig_term_handler(); + bq_setup_sig_hup_handler(ev, msg_ctx); + + if (!printing_subsystem_queue_tasks(ev, msg_ctx)) { + exit(1); + } + + if (!serverid_register(procid_self(), + FLAG_MSG_GENERAL|FLAG_MSG_SMBD + |FLAG_MSG_PRINT_GENERAL)) { + exit(1); + } + + if (!locking_init()) { + exit(1); + } + + messaging_register(msg_ctx, ev, MSG_SMB_CONF_UPDATED, + bq_smb_conf_updated); + messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE, + print_queue_receive); + + fde = tevent_add_fd(ev, ev, pause_pipe[1], TEVENT_FD_READ, + printing_pause_fd_handler, + NULL); + if (!fde) { + DEBUG(0,("tevent_add_fd() failed for pause_pipe\n")); + smb_panic("tevent_add_fd() failed for pause_pipe"); + } + + DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n")); + ret = tevent_loop_wait(ev); + /* should not be reached */ + DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n", + ret, (ret == 0) ? "out of events" : strerror(errno))); + exit(1); + } + + close(pause_pipe[1]); +} + +static bool use_background_queue; + +/* Run before the parent forks */ +bool printing_subsystem_init(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx, + bool background_queue) +{ + bool ret = true; + + use_background_queue = background_queue; + + /* Publish nt printers, this requires a working winreg pipe */ + pcap_cache_reload(ev_ctx, msg_ctx, &reload_printers); + + if (background_queue) { + start_background_queue(ev_ctx, msg_ctx); + } else { + ret = printing_subsystem_queue_tasks(ev_ctx, msg_ctx); + } + + return ret; +} + +void printing_subsystem_update(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx) +{ + if (use_background_queue) return; + + pcap_cache_reload(ev_ctx, msg_ctx, &reload_pcap_change_notify); +} diff --git a/source3/printing/queue_process.h b/source3/printing/queue_process.h new file mode 100644 index 0000000000..41305d85ab --- /dev/null +++ b/source3/printing/queue_process.h @@ -0,0 +1,29 @@ +/* + Unix SMB/Netbios implementation. + Version 3.0 + printing backend routines + Copyright (C) Andrew Tridgell 1992-2000 + Copyright (C) Jeremy Allison 2002 + Copyright (C) Simo Sorce 2011 + + 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 3 of the License, or + (at your option) any later version. + + 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, see <http://www.gnu.org/licenses/>. +*/ + +extern pid_t background_lpq_updater_pid; + +bool printing_subsystem_init(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx, + bool background_queue); +void printing_subsystem_update(struct tevent_context *ev_ctx, + struct messaging_context *msg_ctx); diff --git a/source3/smbd/globals.c b/source3/smbd/globals.c index fe743a6965..bf36dcb71f 100644 --- a/source3/smbd/globals.c +++ b/source3/smbd/globals.c @@ -60,6 +60,7 @@ bool logged_ioctl_message = false; time_t last_smb_conf_reload_time = 0; time_t last_printer_reload_time = 0; + /**************************************************************************** structure to hold a linked list of queued messages. for processing. diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 9df95a8d9d..86e834789f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -27,7 +27,7 @@ #include "../lib/async_req/async_sock.h" #include "ctdbd_conn.h" #include "../lib/util/select.h" -#include "printing/pcap.h" +#include "printing/queue_process.h" #include "system/select.h" #include "passdb.h" #include "auth.h" @@ -882,7 +882,7 @@ static void smbd_sig_hup_handler(struct tevent_context *ev, DEBUG(1,("Reloading services after SIGHUP\n")); reload_services(msg_ctx, smbd_server_conn->sock, False); if (am_parent) { - pcap_cache_reload(ev, msg_ctx, &reload_pcap_change_notify); + printing_subsystem_update(ev, msg_ctx); } } diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h index b2acaa0ee7..2b24f70930 100644 --- a/source3/smbd/proto.h +++ b/source3/smbd/proto.h @@ -966,8 +966,6 @@ void reload_printers(struct tevent_context *ev, struct messaging_context *msg_ctx); bool reload_services(struct messaging_context *msg_ctx, int smb_sock, bool test); -void reload_pcap_change_notify(struct tevent_context *ev, - struct messaging_context *msg_ctx); void exit_server(const char *const explanation); void exit_server_cleanly(const char *const explanation); void exit_server_fault(void); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 18e51a2e42..16395ee3dd 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -32,8 +32,8 @@ #include "memcache.h" #include "ctdbd_conn.h" #include "printing/printer_list.h" +#include "printing/queue_process.h" #include "rpc_server/rpc_service_setup.h" -#include "printing/pcap.h" #include "printing.h" #include "serverid.h" #include "passdb.h" @@ -69,8 +69,7 @@ static void smb_conf_updated(struct messaging_context *msg, change_to_root_user(); reload_services(msg, smbd_server_conn->sock, False); if (am_parent) { - pcap_cache_reload(ev_ctx, msg, - &reload_pcap_change_notify); + printing_subsystem_update(ev_ctx, msg); } } @@ -585,28 +584,6 @@ static bool smbd_open_one_socket(struct smbd_parent_context *parent, return true; } -static bool smbd_parent_housekeeping(const struct timeval *now, void *private_data) -{ - struct messaging_context *msg_ctx = - talloc_get_type_abort(private_data, struct messaging_context); - time_t printcap_cache_time = (time_t)lp_printcap_cache_time(); - time_t t = time_mono(NULL); - - DEBUG(5, ("parent housekeeping\n")); - - /* if periodic printcap rescan is enabled, see if it's time to reload */ - if ((printcap_cache_time != 0) - && (t >= (last_printer_reload_time + printcap_cache_time))) { - DEBUG( 3,( "Printcap cache time expired.\n")); - pcap_cache_reload(messaging_event_context(msg_ctx), - msg_ctx, - &reload_pcap_change_notify); - last_printer_reload_time = t; - } - - return true; -} - /**************************************************************************** Open the socket communication. ****************************************************************************/ @@ -757,14 +734,6 @@ static bool open_sockets_smbd(struct smbd_parent_context *parent, return false; } - if (!(event_add_idle(ev_ctx, NULL, - timeval_set(SMBD_HOUSEKEEPING_INTERVAL, 0), - "parent_housekeeping", smbd_parent_housekeeping, - msg_ctx))) { - DEBUG(0, ("Could not add parent_housekeeping event\n")); - return false; - } - /* Listen to messages */ messaging_register(msg_ctx, NULL, MSG_SMB_SAM_SYNC, msg_sam_sync); @@ -1252,9 +1221,6 @@ extern void build_options(bool screen); exit(1); } - /* Publish nt printers, this requires a working winreg pipe */ - pcap_cache_reload(ev_ctx, msg_ctx, &reload_printers); - /* only start the background queue daemon if we are running as a daemon -- bad things will happen if smbd is launched via inetd and we fork a copy of @@ -1262,7 +1228,13 @@ extern void build_options(bool screen); if (is_daemon && !interactive && lp_parm_bool(-1, "smbd", "backgroundqueue", true)) { - start_background_queue(ev_ctx, msg_ctx); + if (!printing_subsystem_init(ev_ctx, msg_ctx, true)) { + exit(1); + } + } else { + if (!printing_subsystem_init(ev_ctx, msg_ctx, false)) { + exit(1); + } } if (is_daemon && !_lp_disable_spoolss()) { diff --git a/source3/smbd/server_reload.c b/source3/smbd/server_reload.c index db81aadab1..6639c4a8f6 100644 --- a/source3/smbd/server_reload.c +++ b/source3/smbd/server_reload.c @@ -143,12 +143,3 @@ bool reload_services(struct messaging_context *msg_ctx, int smb_sock, return(ret); } - -/**************************************************************************** - Notify smbds of new printcap data -**************************************************************************/ -void reload_pcap_change_notify(struct tevent_context *ev, - struct messaging_context *msg_ctx) -{ - message_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0, NULL); -} diff --git a/source3/wscript_build b/source3/wscript_build index 3be15ea02c..266a0e3fad 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -408,7 +408,8 @@ PRINTBACKEND_SRC = '''printing/printing.c printing/nt_printing.c printing/nt_printing_tdb.c printing/nt_printing_migrate_internal.c - printing/nt_printing_ads.c''' + printing/nt_printing_ads.c + printing/queue_process.c''' NMBD_SRC1 = '''nmbd/asyncdns.c nmbd/nmbd.c nmbd/nmbd_become_dmb.c nmbd/nmbd_become_lmb.c nmbd/nmbd_browserdb.c |