2 Unix SMB/Netbios implementation.
4 printing backend routines
5 Copyright (C) Andrew Tridgell 1992-2000
6 Copyright (C) Jeremy Allison 2002
7 Copyright (C) Simo Sorce 2011
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "smbd/globals.h"
25 #include "include/messages.h"
26 #include "lib/util/util_process.h"
28 #include "printing/pcap.h"
29 #include "printing/printer_list.h"
30 #include "printing/queue_process.h"
31 #include "locking/proto.h"
32 #include "locking/share_mode_lock.h"
33 #include "smbd/smbd.h"
34 #include "rpc_server/rpc_config.h"
35 #include "printing/load.h"
36 #include "printing/spoolssd.h"
37 #include "rpc_server/spoolss/srv_spoolss_nt.h"
39 #include "nt_printing.h"
40 #include "util_event.h"
41 #include "lib/global_contexts.h"
44 * @brief Purge stale printers and reload from pre-populated pcap cache.
46 * This function should normally only be called as a callback on a successful
47 * pcap_cache_reload().
49 * This function can cause DELETION of printers and drivers from our registry,
50 * so calling it on a failed pcap reload may REMOVE permanently all printers
53 * @param[in] ev The event context.
55 * @param[in] msg_ctx The messaging context.
57 static void delete_and_reload_printers_full(struct tevent_context *ev,
58 struct messaging_context *msg_ctx)
60 struct auth_session_info *session_info = NULL;
61 struct spoolss_PrinterInfo2 *pinfo2 = NULL;
62 const struct loadparm_substitution *lp_sub =
63 loadparm_s3_global_substitution();
71 n_services = lp_numservices();
72 pnum = lp_servicenumber(PRINTERS_NAME);
74 status = make_session_info_system(talloc_tos(), &session_info);
75 if (!NT_STATUS_IS_OK(status)) {
76 DEBUG(3, ("reload_printers: "
77 "Could not create system session_info\n"));
78 /* can't remove stale printers before we
79 * are fully initialized */
84 * Add default config for printers added to smb.conf file and remove
87 for (snum = 0; snum < n_services; snum++) {
88 /* avoid removing PRINTERS_NAME */
93 /* skip no-printer services */
94 if (!snum_is_shared_printer(snum)) {
98 sname = lp_const_servicename(snum);
99 pname = lp_printername(session_info, lp_sub, snum);
101 /* check printer, but avoid removing non-autoloaded printers */
102 if (lp_autoloaded(snum) &&
103 !printer_list_printername_exists(pname)) {
104 DEBUG(3, ("removing stale printer %s\n", pname));
106 if (is_printer_published(session_info, session_info,
109 lp_servicename(session_info,
113 nt_printer_publish(session_info,
120 nt_printer_remove(session_info, session_info, msg_ctx,
123 DEBUG(8, ("Adding default registry entry for printer "
124 "[%s], if it doesn't exist.\n", sname));
125 nt_printer_add(session_info, session_info, msg_ctx,
130 /* finally, purge old snums */
131 delete_and_reload_printers();
133 TALLOC_FREE(session_info);
137 /****************************************************************************
138 Notify smbds of new printcap data
139 **************************************************************************/
140 static void reload_pcap_change_notify(struct tevent_context *ev,
141 struct messaging_context *msg_ctx)
144 * Reload the printers first in the background process so that
145 * newly added printers get default values created in the registry.
147 * This will block the process for some time (~1 sec per printer), but
148 * it doesn't block smbd's serving clients.
150 delete_and_reload_printers_full(ev, msg_ctx);
152 messaging_send_all(msg_ctx, MSG_PRINTER_PCAP, NULL, 0);
156 struct tevent_context *ev;
157 struct messaging_context *msg;
158 struct idle_event *housekeep;
159 struct tevent_signal *sighup_handler;
160 struct tevent_signal *sigchld_handler;
163 static bool print_queue_housekeeping(const struct timeval *now, void *pvt)
165 struct bq_state *state;
167 state = talloc_get_type_abort(pvt, struct bq_state);
169 DEBUG(5, ("print queue housekeeping\n"));
170 pcap_cache_reload(state->ev, state->msg, reload_pcap_change_notify);
175 static bool printing_subsystem_queue_tasks(struct bq_state *state)
177 uint32_t housekeeping_period = lp_printcap_cache_time();
179 /* cancel any existing housekeeping event */
180 TALLOC_FREE(state->housekeep);
182 if ((housekeeping_period == 0) || !lp_load_printers()) {
183 DEBUG(4, ("background print queue housekeeping disabled\n"));
187 state->housekeep = event_add_idle(state->ev, NULL,
188 timeval_set(housekeeping_period, 0),
189 "print_queue_housekeeping",
190 print_queue_housekeeping, state);
191 if (state->housekeep == NULL) {
192 DEBUG(0,("Could not add print_queue_housekeeping event\n"));
199 static void bq_reopen_logs(char *logfile)
202 lp_set_logfile(logfile);
207 static void bq_sig_term_handler(struct tevent_context *ev,
208 struct tevent_signal *se,
214 exit_server_cleanly("termination signal");
217 static void bq_setup_sig_term_handler(void)
219 struct tevent_signal *se;
221 se = tevent_add_signal(global_event_context(),
222 global_event_context(),
227 exit_server("failed to setup SIGTERM handler");
231 static void bq_sig_hup_handler(struct tevent_context *ev,
232 struct tevent_signal *se,
238 struct bq_state *state;
240 state = talloc_get_type_abort(pvt, struct bq_state);
241 change_to_root_user();
243 DEBUG(1, ("Reloading pcap cache after SIGHUP\n"));
244 pcap_cache_reload(state->ev, state->msg,
245 reload_pcap_change_notify);
246 printing_subsystem_queue_tasks(state);
247 bq_reopen_logs(NULL);
250 static void bq_sig_chld_handler(struct tevent_context *ev_ctx,
251 struct tevent_signal *se,
252 int signum, int count,
253 void *siginfo, void *pvt)
260 pid = waitpid(-1, &status, WNOHANG);
261 } while ((pid == -1) && (errno == EINTR));
263 if (WIFEXITED(status)) {
264 DBG_INFO("Bq child process %d terminated with %d\n",
266 WEXITSTATUS(status));
268 DBG_NOTICE("Bq child process %d terminated abnormally\n",
274 static void bq_smb_conf_updated(struct messaging_context *msg_ctx,
277 struct server_id server_id,
280 struct bq_state *state;
282 state = talloc_get_type_abort(private_data, struct bq_state);
284 DEBUG(10,("smb_conf_updated: Got message saying smb.conf was "
285 "updated. Reloading.\n"));
286 change_to_root_user();
287 pcap_cache_reload(state->ev, msg_ctx, reload_pcap_change_notify);
288 printing_subsystem_queue_tasks(state);
291 static int bq_state_destructor(struct bq_state *s)
293 struct messaging_context *msg_ctx = s->msg;
294 TALLOC_FREE(s->sighup_handler);
295 TALLOC_FREE(s->sigchld_handler);
296 messaging_deregister(msg_ctx, MSG_PRINTER_DRVUPGRADE, NULL);
297 messaging_deregister(msg_ctx, MSG_PRINTER_UPDATE, NULL);
298 messaging_deregister(msg_ctx, MSG_SMB_CONF_UPDATED, s);
302 struct bq_state *register_printing_bq_handlers(
304 struct messaging_context *msg_ctx)
306 struct bq_state *state = NULL;
309 state = talloc_zero(mem_ctx, struct bq_state);
313 state->ev = messaging_tevent_context(msg_ctx);
314 state->msg = msg_ctx;
316 status = messaging_register(
317 msg_ctx, state, MSG_SMB_CONF_UPDATED, bq_smb_conf_updated);
318 if (!NT_STATUS_IS_OK(status)) {
321 status = messaging_register(
322 msg_ctx, NULL, MSG_PRINTER_UPDATE, print_queue_receive);
323 if (!NT_STATUS_IS_OK(status)) {
324 goto fail_dereg_smb_conf_updated;
326 status = messaging_register(
327 msg_ctx, NULL, MSG_PRINTER_DRVUPGRADE, do_drv_upgrade_printer);
328 if (!NT_STATUS_IS_OK(status)) {
329 goto fail_dereg_printer_update;
332 state->sighup_handler = tevent_add_signal(
333 state->ev, state, SIGHUP, 0, bq_sig_hup_handler, state);
334 if (state->sighup_handler == NULL) {
335 goto fail_dereg_printer_drvupgrade;
337 state->sigchld_handler = tevent_add_signal(
338 state->ev, state, SIGCHLD, 0, bq_sig_chld_handler, NULL);
339 if (state->sigchld_handler == NULL) {
340 goto fail_free_handlers;
343 talloc_set_destructor(state, bq_state_destructor);
348 TALLOC_FREE(state->sighup_handler);
349 TALLOC_FREE(state->sigchld_handler);
350 fail_dereg_printer_drvupgrade:
351 messaging_deregister(msg_ctx, MSG_PRINTER_DRVUPGRADE, NULL);
352 fail_dereg_printer_update:
353 messaging_deregister(msg_ctx, MSG_PRINTER_UPDATE, NULL);
354 fail_dereg_smb_conf_updated:
355 messaging_deregister(msg_ctx, MSG_SMB_CONF_UPDATED, state);
361 /****************************************************************************
362 main thread of the background lpq updater
363 ****************************************************************************/
364 pid_t start_background_queue(struct tevent_context *ev,
365 struct messaging_context *msg_ctx,
369 struct bq_state *state;
373 DEBUG(3,("start_background_queue: Starting background LPQ thread\n"));
376 * Block signals before forking child as it will have to
377 * set its own handlers. Child will re-enable SIGHUP as
378 * soon as the handlers are set up.
380 BlockSignals(true, SIGTERM);
381 BlockSignals(true, SIGHUP);
385 /* parent or error */
387 /* Re-enable SIGHUP before returnig */
388 BlockSignals(false, SIGTERM);
389 BlockSignals(false, SIGHUP);
394 DEBUG(5,("start_background_queue: background LPQ thread started\n"));
396 status = smbd_reinit_after_fork(msg_ctx, ev, true, "lpqd");
398 if (!NT_STATUS_IS_OK(status)) {
399 DEBUG(0,("reinit_after_fork() failed\n"));
400 smb_panic("reinit_after_fork() failed");
403 /* Remove previous forwarder message set in parent. */
404 messaging_deregister(msg_ctx, MSG_PRINTER_DRVUPGRADE, NULL);
406 state = register_printing_bq_handlers(NULL, msg_ctx);
408 DBG_ERR("Could not register bq handlers\n");
412 bq_reopen_logs(logfile);
413 bq_setup_sig_term_handler();
415 BlockSignals(false, SIGTERM);
416 BlockSignals(false, SIGHUP);
418 if (!printing_subsystem_queue_tasks(state)) {
422 if (!locking_init()) {
426 pcap_cache_reload(ev, msg_ctx, reload_pcap_change_notify);
428 DEBUG(5,("start_background_queue: background LPQ thread waiting for messages\n"));
429 ret = tevent_loop_wait(ev);
430 /* should not be reached */
431 DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
432 ret, (ret == 0) ? "out of events" : strerror(errno)));
438 /* Run before the parent forks */
439 bool printing_subsystem_init(struct tevent_context *ev_ctx,
440 struct messaging_context *msg_ctx,
441 struct dcesrv_context *dce_ctx,
443 bool background_queue)
447 if (!print_backend_init(msg_ctx)) {
451 /* start spoolss daemon */
452 /* start as a separate daemon only if enabled */
453 if (start_daemons && rpc_spoolss_daemon() == RPC_DAEMON_FORK) {
455 pid = start_spoolssd(ev_ctx, msg_ctx, dce_ctx);
457 } else if (start_daemons && background_queue) {
459 pid = start_background_queue(ev_ctx, msg_ctx, NULL);
463 struct bq_state *state;
465 state = talloc_zero(NULL, struct bq_state);
470 state->msg = msg_ctx;
472 ret = printing_subsystem_queue_tasks(state);
474 /* Publish nt printers, this requires a working winreg pipe */
475 pcap_cache_reload(ev_ctx, msg_ctx,
476 delete_and_reload_printers_full);
484 background_lpq_updater_pid = pid;
489 void printing_subsystem_update(struct tevent_context *ev_ctx,
490 struct messaging_context *msg_ctx,
493 if (background_lpq_updater_pid != -1) {
496 /* Send a sighup to the background process.
497 * this will force it to reload printers */
498 kill(background_lpq_updater_pid, SIGHUP);
503 pcap_cache_reload(ev_ctx, msg_ctx,
504 delete_and_reload_printers_full);