s3-spoolss: Introduce helper function to manage pool.
[idra/samba.git] / source3 / printing / spoolssd.c
1 /*
2    Unix SMB/Netbios implementation.
3    SPOOLSS Daemon
4    Copyright (C) Simo Sorce 2010
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20 #include "serverid.h"
21 #include "smbd/smbd.h"
22
23 #include "messages.h"
24 #include "include/printing.h"
25 #include "printing/nt_printing_migrate_internal.h"
26 #include "printing/queue_process.h"
27 #include "printing/pcap.h"
28 #include "printing/load.h"
29 #include "ntdomain.h"
30 #include "librpc/gen_ndr/srv_winreg.h"
31 #include "librpc/gen_ndr/srv_spoolss.h"
32 #include "rpc_server/rpc_server.h"
33 #include "rpc_server/rpc_ep_register.h"
34 #include "rpc_server/spoolss/srv_spoolss_nt.h"
35 #include "librpc/rpc/dcerpc_ep.h"
36 #include "lib/server_prefork.h"
37
38 #define SPOOLSS_PIPE_NAME "spoolss"
39 #define DAEMON_NAME "spoolssd"
40
41 #define SPOOLSS_MIN_CHILDREN 5
42 #define SPOOLSS_MAX_CHILDREN 25
43 #define SPOOLSS_SPAWN_RATE 5
44 #define SPOOLSS_MIN_LIFE 60 /* 1 minute minimum life time */
45
46 #define SPOOLSS_INIT     0x00
47 #define SPOOLSS_NEW_MAX  0x01
48 #define SPOLLSS_ENOSPC   0x02
49
50 static struct prefork_pool *spoolss_pool;
51 static int spoolss_min_children;
52 static int spoolss_max_children;
53 static int spoolss_spawn_rate;
54 static int spoolss_prefork_status;
55 static int spoolss_child_id = 0;
56
57 pid_t start_spoolssd(struct tevent_context *ev_ctx,
58                      struct messaging_context *msg_ctx);
59 static void spoolss_manage_pool(struct tevent_context *ev_ctx,
60                                 struct messaging_context *msg_ctx);
61
62 static void spoolss_prefork_config(void)
63 {
64         static int spoolss_prefork_config_init = false;
65         const char *prefork_str;
66         int min, max, rate;
67         bool use_defaults = false;
68         int ret;
69
70         if (!spoolss_prefork_config_init) {
71                 spoolss_pool = NULL;
72                 spoolss_prefork_status = SPOOLSS_INIT;
73                 spoolss_min_children = 0;
74                 spoolss_max_children = 0;
75                 spoolss_spawn_rate = 0;
76                 spoolss_prefork_config_init = true;
77         }
78
79         prefork_str = lp_parm_const_string(GLOBAL_SECTION_SNUM,
80                                            "spoolss", "prefork", "none");
81         if (strcmp(prefork_str, "none") == 0) {
82                 use_defaults = true;
83         } else {
84                 ret = sscanf(prefork_str, "%d:%d:%d", &min, &max, &rate);
85                 if (ret != 3) {
86                         DEBUG(0, ("invalid format for spoolss:prefork!\n"));
87                         use_defaults = true;
88                 }
89         }
90
91         if (use_defaults) {
92                 min = SPOOLSS_MIN_CHILDREN;
93                 max = SPOOLSS_MAX_CHILDREN;
94                 rate = SPOOLSS_SPAWN_RATE;
95         }
96
97         if (max > spoolss_max_children && spoolss_max_children != 0) {
98                 spoolss_prefork_status |= SPOOLSS_NEW_MAX;
99         }
100
101         spoolss_min_children = min;
102         spoolss_max_children = max;
103         spoolss_spawn_rate = rate;
104 }
105
106 static void spoolss_reopen_logs(int child_id)
107 {
108         char *lfile = lp_logfile();
109         char *ext;
110         int rc;
111
112         if (child_id) {
113                 rc = asprintf(&ext, "%s.%d", DAEMON_NAME, child_id);
114         } else {
115                 rc = asprintf(&ext, "%s", DAEMON_NAME);
116         }
117
118         if (rc == -1) {
119                 return;
120         }
121
122         rc = 0;
123         if (lfile == NULL || lfile[0] == '\0') {
124                 rc = asprintf(&lfile, "%s/log.%s",
125                               get_dyn_LOGFILEBASE(), ext);
126         } else {
127                 if (strstr(lfile, ext) == NULL) {
128                         if (child_id) {
129                                 rc = asprintf(&lfile, "%s.%d",
130                                               lp_logfile(), child_id);
131                         } else {
132                                 rc = asprintf(&lfile, "%s.%s",
133                                               lp_logfile(), ext);
134                         }
135                 }
136         }
137
138         if (rc > 0) {
139                 lp_set_logfile(lfile);
140                 SAFE_FREE(lfile);
141         }
142
143         SAFE_FREE(ext);
144
145         reopen_logs();
146 }
147
148 static void update_conf(struct tevent_context *ev,
149                         struct messaging_context *msg)
150 {
151         change_to_root_user();
152         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
153         reload_printers(ev, msg);
154
155         spoolss_reopen_logs(spoolss_child_id);
156         if (spoolss_child_id == 0) {
157                 spoolss_prefork_config();
158                 spoolss_manage_pool(ev, msg);
159         }
160 }
161
162 static void smb_conf_updated(struct messaging_context *msg,
163                              void *private_data,
164                              uint32_t msg_type,
165                              struct server_id server_id,
166                              DATA_BLOB *data)
167 {
168         struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
169                                                              struct tevent_context);
170
171         DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
172         update_conf(ev_ctx, msg);
173 }
174
175 static void update_pcap(struct tevent_context *ev_ctx,
176                         struct messaging_context *msg_ctx)
177 {
178         change_to_root_user();
179         reload_printers(ev_ctx, msg_ctx);
180 }
181
182 static void pcap_updated(struct messaging_context *msg,
183                          void *private_data,
184                          uint32_t msg_type,
185                          struct server_id server_id,
186                          DATA_BLOB *data)
187 {
188         struct tevent_context *ev_ctx;
189
190         ev_ctx = talloc_get_type_abort(private_data, struct tevent_context);
191
192         DEBUG(10, ("Got message that pcap updated. Reloading.\n"));
193         update_pcap(ev_ctx, msg);
194 }
195
196 static void spoolss_sig_term_handler(struct tevent_context *ev,
197                                      struct tevent_signal *se,
198                                      int signum,
199                                      int count,
200                                      void *siginfo,
201                                      void *private_data)
202 {
203         exit_server_cleanly("termination signal");
204 }
205
206 static void spoolss_setup_sig_term_handler(struct tevent_context *ev_ctx)
207 {
208         struct tevent_signal *se;
209
210         se = tevent_add_signal(ev_ctx,
211                                ev_ctx,
212                                SIGTERM, 0,
213                                spoolss_sig_term_handler,
214                                NULL);
215         if (!se) {
216                 exit_server("failed to setup SIGTERM handler");
217         }
218 }
219
220 static void spoolss_sig_hup_handler(struct tevent_context *ev,
221                                     struct tevent_signal *se,
222                                     int signum,
223                                     int count,
224                                     void *siginfo,
225                                     void *pvt)
226 {
227         struct messaging_context *msg_ctx;
228
229         msg_ctx = talloc_get_type_abort(pvt, struct messaging_context);
230
231         DEBUG(1,("Reloading printers after SIGHUP\n"));
232         update_conf(ev, msg_ctx);
233
234         /* relay to all children */
235         if (spoolss_pool) {
236                 prefork_send_signal_to_all(spoolss_pool, SIGHUP);
237         }
238 }
239
240 static void spoolss_setup_sig_hup_handler(struct tevent_context *ev_ctx,
241                                           struct messaging_context *msg_ctx)
242 {
243         struct tevent_signal *se;
244
245         se = tevent_add_signal(ev_ctx,
246                                ev_ctx,
247                                SIGHUP, 0,
248                                spoolss_sig_hup_handler,
249                                msg_ctx);
250         if (!se) {
251                 exit_server("failed to setup SIGHUP handler");
252         }
253 }
254
255 static bool spoolss_init_cb(void *ptr)
256 {
257         struct messaging_context *msg_ctx = talloc_get_type_abort(
258                 ptr, struct messaging_context);
259
260         return nt_printing_tdb_migrate(msg_ctx);
261 }
262
263 static bool spoolss_shutdown_cb(void *ptr)
264 {
265         srv_spoolss_cleanup();
266
267         return true;
268 }
269
270 /* Children */
271
272 struct spoolss_chld_sig_hup_ctx {
273         struct messaging_context *msg_ctx;
274         struct pf_worker_data *pf;
275 };
276
277 static void spoolss_chld_sig_hup_handler(struct tevent_context *ev,
278                                          struct tevent_signal *se,
279                                          int signum,
280                                          int count,
281                                          void *siginfo,
282                                          void *pvt)
283 {
284         struct spoolss_chld_sig_hup_ctx *shc;
285
286         shc = talloc_get_type_abort(pvt, struct spoolss_chld_sig_hup_ctx);
287
288         /* avoid wasting CPU cycles if we are going to exit soon anyways */
289         if (shc->pf != NULL &&
290             shc->pf->cmds == PF_SRV_MSG_EXIT) {
291                 return;
292         }
293
294         change_to_root_user();
295         DEBUG(1,("Reloading printers after SIGHUP\n"));
296         reload_printers(ev, shc->msg_ctx);
297         spoolss_reopen_logs(spoolss_child_id);
298 }
299
300 static bool spoolss_setup_chld_hup_handler(struct tevent_context *ev_ctx,
301                                            struct messaging_context *msg_ctx,
302                                            struct pf_worker_data *pf)
303 {
304         struct spoolss_chld_sig_hup_ctx *shc;
305         struct tevent_signal *se;
306
307         shc = talloc(ev_ctx, struct spoolss_chld_sig_hup_ctx);
308         if (!shc) {
309                 DEBUG(1, ("failed to setup SIGHUP handler"));
310                 return false;
311         }
312         shc->pf = pf;
313         shc->msg_ctx = msg_ctx;
314
315         se = tevent_add_signal(ev_ctx,
316                                ev_ctx,
317                                SIGHUP, 0,
318                                spoolss_chld_sig_hup_handler,
319                                shc);
320         if (!se) {
321                 DEBUG(1, ("failed to setup SIGHUP handler"));
322                 return false;
323         }
324
325         return true;
326 }
327
328 static bool spoolss_child_init(struct tevent_context *ev_ctx,
329                                int child_id, struct pf_worker_data *pf)
330 {
331         NTSTATUS status;
332         struct rpc_srv_callbacks spoolss_cb;
333         struct messaging_context *msg_ctx = server_messaging_context();
334         bool ok;
335
336         status = reinit_after_fork(msg_ctx, ev_ctx,
337                                    procid_self(), true);
338         if (!NT_STATUS_IS_OK(status)) {
339                 DEBUG(0,("reinit_after_fork() failed\n"));
340                 smb_panic("reinit_after_fork() failed");
341         }
342
343         spoolss_child_id = child_id;
344         spoolss_reopen_logs(child_id);
345
346         ok = spoolss_setup_chld_hup_handler(ev_ctx, msg_ctx, pf);
347         if (!ok) {
348                 return false;
349         }
350
351         if (!serverid_register(procid_self(),
352                                 FLAG_MSG_GENERAL |
353                                 FLAG_MSG_PRINT_GENERAL)) {
354                 return false;
355         }
356
357         if (!locking_init()) {
358                 return false;
359         }
360
361         messaging_register(msg_ctx, ev_ctx,
362                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
363         messaging_register(msg_ctx, ev_ctx, MSG_PRINTER_PCAP,
364                            pcap_updated);
365
366         /* As soon as messaging is up check if pcap has been loaded already.
367          * If so then we probably missed a message and should load_printers()
368          * ourselves. If pcap has not been loaded yet, then ignore, we will get
369          * a message as soon as the bq process completes the reload. */
370         if (pcap_cache_loaded()) {
371                 load_printers(ev_ctx, msg_ctx);
372         }
373
374         /* try to reinit rpc queues */
375         spoolss_cb.init = spoolss_init_cb;
376         spoolss_cb.shutdown = spoolss_shutdown_cb;
377         spoolss_cb.private_data = msg_ctx;
378
379         status = rpc_winreg_init(NULL);
380         if (!NT_STATUS_IS_OK(status)) {
381                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
382                           nt_errstr(status)));
383                 return false;
384         }
385
386         status = rpc_spoolss_init(&spoolss_cb);
387         if (!NT_STATUS_IS_OK(status)) {
388                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
389                           nt_errstr(status)));
390                 return false;
391         }
392
393         return true;
394 }
395
396 struct spoolss_children_data {
397         struct tevent_context *ev_ctx;
398         struct messaging_context *msg_ctx;
399         struct pf_worker_data *pf;
400         int listen_fd_size;
401         int *listen_fds;
402         int lock_fd;
403
404         bool listening;
405 };
406
407 static void spoolss_next_client(void *pvt);
408
409 static int spoolss_children_main(struct tevent_context *ev_ctx,
410                                  struct messaging_context *msg_ctx,
411                                  struct pf_worker_data *pf,
412                                  int child_id,
413                                  int listen_fd_size,
414                                  int *listen_fds,
415                                  int lock_fd,
416                                  void *private_data)
417 {
418         struct spoolss_children_data *data;
419         bool ok;
420         int ret;
421
422         ok = spoolss_child_init(ev_ctx, child_id, pf);
423         if (!ok) {
424                 return 1;
425         }
426
427         data = talloc(ev_ctx, struct spoolss_children_data);
428         if (!data) {
429                 return 1;
430         }
431         data->pf = pf;
432         data->ev_ctx = ev_ctx;
433         data->msg_ctx = msg_ctx;
434         data->lock_fd = lock_fd;
435         data->listen_fd_size = listen_fd_size;
436         data->listen_fds = listen_fds;
437         data->listening = false;
438
439         /* loop until it is time to exit */
440         while (pf->status != PF_WORKER_EXITING) {
441                 /* try to see if it is time to schedule the next client */
442                 spoolss_next_client(data);
443
444                 ret = tevent_loop_once(ev_ctx);
445                 if (ret != 0) {
446                         DEBUG(0, ("tevent_loop_once() exited with %d: %s\n",
447                                   ret, strerror(errno)));
448                         pf->status = PF_WORKER_EXITING;
449                 }
450         }
451
452         return ret;
453 }
454
455 static void spoolss_client_terminated(void *pvt)
456 {
457         struct spoolss_children_data *data;
458
459         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
460
461         if (data->pf->num_clients) {
462                 data->pf->num_clients--;
463         } else {
464                 DEBUG(2, ("Invalid num clients, aborting!\n"));
465                 data->pf->status = PF_WORKER_EXITING;
466                 return;
467         }
468
469         spoolss_next_client(pvt);
470 }
471
472 struct spoolss_new_client {
473         struct spoolss_children_data *data;
474         struct tsocket_address *srv_addr;
475         struct tsocket_address *cli_addr;
476 };
477
478 static void spoolss_handle_client(struct tevent_req *req);
479
480 static void spoolss_next_client(void *pvt)
481 {
482         struct tevent_req *req;
483         struct spoolss_children_data *data;
484         struct spoolss_new_client *next;
485
486         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
487
488         if (data->pf->num_clients == 0) {
489                 data->pf->status = PF_WORKER_IDLE;
490         }
491
492         if (data->pf->cmds == PF_SRV_MSG_EXIT) {
493                 DEBUG(2, ("Parent process commands we terminate!\n"));
494                 return;
495         }
496
497         if (data->listening ||
498             data->pf->num_clients >= data->pf->allowed_clients) {
499                 /* nothing to do for now we are already listening
500                  * or reached the number of clients we are allowed
501                  * to handle in parallel */
502                 return;
503         }
504
505         next = talloc_zero(data, struct spoolss_new_client);
506         if (!next) {
507                 DEBUG(1, ("Out of memory!?\n"));
508                 return;
509         }
510         next->data = data;
511
512         req = prefork_listen_send(next, data->ev_ctx, data->pf,
513                                   data->listen_fd_size,
514                                   data->listen_fds,
515                                   data->lock_fd);
516         if (!req) {
517                 DEBUG(1, ("Failed to make listening request!?\n"));
518                 talloc_free(next);
519                 return;
520         }
521         tevent_req_set_callback(req, spoolss_handle_client, next);
522
523         data->listening = true;
524 }
525
526 static void spoolss_handle_client(struct tevent_req *req)
527 {
528         struct spoolss_children_data *data;
529         struct spoolss_new_client *client;
530         int ret;
531         int sd;
532
533         client = tevent_req_callback_data(req, struct spoolss_new_client);
534         data = client->data;
535
536         ret = prefork_listen_recv(req, client, &sd,
537                                   &client->srv_addr, &client->cli_addr);
538
539         /* this will free the request too */
540         talloc_free(client);
541         /* we are done listening */
542         data->listening = false;
543
544         if (ret > 0) {
545                 DEBUG(1, ("Failed to accept client connection!\n"));
546                 /* bail out if we are not serving any other client */
547                 if (data->pf->num_clients == 0) {
548                         data->pf->status = PF_WORKER_EXITING;
549                 }
550                 return;
551         }
552
553         if (ret == -2) {
554                 DEBUG(1, ("Server asks us to die!\n"));
555                 data->pf->status = PF_WORKER_EXITING;
556                 return;
557         }
558
559         DEBUG(2, ("Spoolss preforked child %d got client connection!\n",
560                   (int)(data->pf->pid)));
561
562         named_pipe_accept_function(data->ev_ctx, data->msg_ctx,
563                                    SPOOLSS_PIPE_NAME, sd,
564                                    spoolss_client_terminated, data);
565 }
566
567 /* ==== Main Process Functions ==== */
568
569 extern pid_t background_lpq_updater_pid;
570 static char *bq_logfile;
571
572 static void check_updater_child(void)
573 {
574         int status;
575         pid_t pid;
576
577         if (background_lpq_updater_pid == -1) {
578                 return;
579         }
580
581         pid = sys_waitpid(background_lpq_updater_pid, &status, WNOHANG);
582         if (pid > 0) {
583                 DEBUG(2, ("The background queue child died... Restarting!\n"));
584                 pid = start_background_queue(server_event_context(),
585                                              server_messaging_context(),
586                                              bq_logfile);
587                 background_lpq_updater_pid = pid;
588         }
589 }
590
591 static void spoolss_manage_pool(struct tevent_context *ev_ctx,
592                                 struct messaging_context *msg_ctx)
593 {
594         time_t now = time(NULL);
595         int active, total;
596         int ret, n;
597
598         if ((spoolss_prefork_status & SPOOLSS_NEW_MAX) &&
599             !(spoolss_prefork_status & SPOLLSS_ENOSPC)) {
600                 ret = prefork_expand_pool(spoolss_pool, spoolss_max_children);
601                 if (ret == ENOSPC) {
602                         spoolss_prefork_status |= SPOLLSS_ENOSPC;
603                 }
604                 spoolss_prefork_status &= ~SPOOLSS_NEW_MAX;
605         }
606
607         active = prefork_count_active_children(spoolss_pool, &total);
608
609         if ((total < spoolss_max_children) &&
610             ((total < spoolss_min_children) ||
611              (total - active < spoolss_spawn_rate))) {
612                 n = prefork_add_children(ev_ctx, msg_ctx,
613                                          spoolss_pool, spoolss_spawn_rate);
614                 if (n < spoolss_spawn_rate) {
615                         DEBUG(10, ("Tried to start %d children but only,"
616                                    "%d were actually started.!\n",
617                                    spoolss_spawn_rate, n));
618                 }
619         }
620
621         if (total - active > spoolss_min_children) {
622                 if ((total - spoolss_min_children) >= spoolss_spawn_rate) {
623                         prefork_retire_children(spoolss_pool,
624                                                 spoolss_spawn_rate,
625                                                 now - SPOOLSS_MIN_LIFE);
626                 }
627         }
628
629         n = prefork_count_allowed_connections(spoolss_pool);
630         if (n <= spoolss_spawn_rate) {
631                 do {
632                         prefork_increase_allowed_clients(spoolss_pool);
633                         n = prefork_count_allowed_connections(spoolss_pool);
634                 } while (n <= spoolss_spawn_rate);
635         } else if (n > spoolss_max_children + spoolss_spawn_rate) {
636                 do {
637                         prefork_decrease_allowed_clients(spoolss_pool);
638                         n = prefork_count_allowed_connections(spoolss_pool);
639                 } while (n > spoolss_max_children + spoolss_spawn_rate);
640         }
641 }
642
643 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
644                                     struct messaging_context *msg_ctx,
645                                     struct timeval current_time);
646 static void spoolssd_check_children(struct tevent_context *ev_ctx,
647                                     struct tevent_timer *te,
648                                     struct timeval current_time,
649                                     void *pvt);
650
651 static void spoolssd_sigchld_handler(struct tevent_context *ev_ctx,
652                                      struct prefork_pool *pfp,
653                                      void *pvt)
654 {
655         struct messaging_context *msg_ctx;
656
657         msg_ctx = talloc_get_type_abort(pvt, struct messaging_context);
658
659         /* run pool management so we can fork/retire or increase
660          * the allowed connections per child based on load */
661         spoolss_manage_pool(ev_ctx, msg_ctx);
662
663         /* also check if the updater child is alive and well */
664         check_updater_child();
665 }
666
667 static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
668                                             struct messaging_context *msg_ctx)
669 {
670         bool ok;
671
672         /* add our oun sigchld callback */
673         prefork_set_sigchld_callback(spoolss_pool,
674                                      spoolssd_sigchld_handler, msg_ctx);
675
676         ok = spoolssd_schedule_check(ev_ctx, msg_ctx,
677                                      tevent_timeval_current());
678         return ok;
679 }
680
681 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
682                                     struct messaging_context *msg_ctx,
683                                     struct timeval current_time)
684 {
685         struct tevent_timer *te;
686         struct timeval next_event;
687
688         /* check situation again in 10 seconds */
689         next_event = tevent_timeval_current_ofs(10, 0);
690
691         /* TODO: check when the socket becomes readable, so that children
692          * are checked only when there is some activity ? */
693         te = tevent_add_timer(ev_ctx, spoolss_pool, next_event,
694                                 spoolssd_check_children, msg_ctx);
695         if (!te) {
696                 DEBUG(2, ("Failed to set up children monitoring!\n"));
697                 return false;
698         }
699
700         return true;
701 }
702
703 static void spoolssd_check_children(struct tevent_context *ev_ctx,
704                                     struct tevent_timer *te,
705                                     struct timeval current_time,
706                                     void *pvt)
707 {
708         struct messaging_context *msg_ctx;
709
710         msg_ctx = talloc_get_type_abort(pvt, struct messaging_context);
711
712         spoolss_manage_pool(ev_ctx, msg_ctx);
713
714         spoolssd_schedule_check(ev_ctx, msg_ctx, current_time);
715 }
716
717 static void print_queue_forward(struct messaging_context *msg,
718                                 void *private_data,
719                                 uint32_t msg_type,
720                                 struct server_id server_id,
721                                 DATA_BLOB *data)
722 {
723         messaging_send_buf(msg, pid_to_procid(background_lpq_updater_pid),
724                            MSG_PRINTER_UPDATE, data->data, data->length);
725 }
726
727 static char *get_bq_logfile(void)
728 {
729         char *lfile = lp_logfile();
730         int rc;
731
732         if (lfile == NULL || lfile[0] == '\0') {
733                 rc = asprintf(&lfile, "%s/log.%s.bq",
734                                         get_dyn_LOGFILEBASE(), DAEMON_NAME);
735         } else {
736                 rc = asprintf(&lfile, "%s.bq", lp_logfile());
737         }
738         if (rc == -1) {
739                 lfile = NULL;
740         }
741         return lfile;
742 }
743
744 pid_t start_spoolssd(struct tevent_context *ev_ctx,
745                     struct messaging_context *msg_ctx)
746 {
747         struct rpc_srv_callbacks spoolss_cb;
748         struct dcerpc_binding_vector *v;
749         TALLOC_CTX *mem_ctx;
750         pid_t pid;
751         NTSTATUS status;
752         int listen_fd;
753         int ret;
754         bool ok;
755
756         DEBUG(1, ("Forking SPOOLSS Daemon\n"));
757
758         /*
759          * Block signals before forking child as it will have to
760          * set its own handlers. Child will re-enable SIGHUP as
761          * soon as the handlers are set up.
762          */
763         BlockSignals(true, SIGTERM);
764         BlockSignals(true, SIGHUP);
765
766         pid = sys_fork();
767
768         if (pid == -1) {
769                 DEBUG(0, ("Failed to fork SPOOLSS [%s]\n",
770                            strerror(errno)));
771         }
772
773         /* parent or error */
774         if (pid != 0) {
775
776                 /* Re-enable SIGHUP before returnig */
777                 BlockSignals(false, SIGTERM);
778                 BlockSignals(false, SIGHUP);
779                 return pid;
780         }
781
782         /* child */
783         close_low_fds(false);
784
785         status = reinit_after_fork(msg_ctx,
786                                    ev_ctx,
787                                    procid_self(), true);
788         if (!NT_STATUS_IS_OK(status)) {
789                 DEBUG(0,("reinit_after_fork() failed\n"));
790                 smb_panic("reinit_after_fork() failed");
791         }
792
793         spoolss_reopen_logs(0);
794         spoolss_prefork_config();
795
796         spoolss_setup_sig_term_handler(ev_ctx);
797         spoolss_setup_sig_hup_handler(ev_ctx, msg_ctx);
798
799         BlockSignals(false, SIGTERM);
800         BlockSignals(false, SIGHUP);
801
802         /* always start the backgroundqueue listner in spoolssd */
803         bq_logfile = get_bq_logfile();
804         pid = start_background_queue(ev_ctx, msg_ctx, bq_logfile);
805         if (pid > 0) {
806                 background_lpq_updater_pid = pid;
807         }
808
809         /* the listening fd must be created before the children are actually
810          * forked out. */
811         listen_fd = create_named_pipe_socket(SPOOLSS_PIPE_NAME);
812         if (listen_fd == -1) {
813                 exit(1);
814         }
815
816         ret = listen(listen_fd, spoolss_max_children);
817         if (ret == -1) {
818                 DEBUG(0, ("Failed to listen on spoolss pipe - %s\n",
819                           strerror(errno)));
820                 exit(1);
821         }
822
823         /* start children before any more initialization is done */
824         ok = prefork_create_pool(ev_ctx, /* mem_ctx */
825                                  ev_ctx, msg_ctx,
826                                  1, &listen_fd,
827                                  spoolss_min_children,
828                                  spoolss_max_children,
829                                  &spoolss_children_main, NULL,
830                                  &spoolss_pool);
831         if (!ok) {
832                 exit(1);
833         }
834
835         if (!serverid_register(procid_self(),
836                                 FLAG_MSG_GENERAL |
837                                 FLAG_MSG_PRINT_GENERAL)) {
838                 exit(1);
839         }
840
841         if (!locking_init()) {
842                 exit(1);
843         }
844
845         messaging_register(msg_ctx, ev_ctx,
846                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
847         messaging_register(msg_ctx, NULL, MSG_PRINTER_UPDATE,
848                            print_queue_forward);
849         messaging_register(msg_ctx, ev_ctx, MSG_PRINTER_PCAP,
850                            pcap_updated);
851
852         /* As soon as messaging is up check if pcap has been loaded already.
853          * If so then we probably missed a message and should load_printers()
854          * ourselves. If pcap has not been loaded yet, then ignore, we will get
855          * a message as soon as the bq process completes the reload. */
856         if (pcap_cache_loaded()) {
857                 load_printers(ev_ctx, msg_ctx);
858         }
859
860         mem_ctx = talloc_new(NULL);
861         if (mem_ctx == NULL) {
862                 exit(1);
863         }
864
865         /*
866          * Initialize spoolss with an init function to convert printers first.
867          * static_init_rpc will try to initialize the spoolss server too but you
868          * can't register it twice.
869          */
870         spoolss_cb.init = spoolss_init_cb;
871         spoolss_cb.shutdown = spoolss_shutdown_cb;
872         spoolss_cb.private_data = msg_ctx;
873
874         status = rpc_winreg_init(NULL);
875         if (!NT_STATUS_IS_OK(status)) {
876                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
877                           nt_errstr(status)));
878                 exit(1);
879         }
880
881         status = rpc_spoolss_init(&spoolss_cb);
882         if (!NT_STATUS_IS_OK(status)) {
883                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
884                           nt_errstr(status)));
885                 exit(1);
886         }
887
888         status = dcerpc_binding_vector_new(mem_ctx, &v);
889         if (!NT_STATUS_IS_OK(status)) {
890                 DEBUG(0, ("Failed to create binding vector (%s)\n",
891                           nt_errstr(status)));
892                 exit(1);
893         }
894
895         status = dcerpc_binding_vector_add_np_default(&ndr_table_spoolss, v);
896         if (!NT_STATUS_IS_OK(status)) {
897                 DEBUG(0, ("Failed to add np to binding vector (%s)\n",
898                           nt_errstr(status)));
899                 exit(1);
900         }
901
902         status = rpc_ep_register(ev_ctx, msg_ctx, &ndr_table_spoolss, v);
903         if (!NT_STATUS_IS_OK(status)) {
904                 DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
905                           nt_errstr(status)));
906                 exit(1);
907         }
908
909         talloc_free(mem_ctx);
910
911         ok = spoolssd_setup_children_monitor(ev_ctx, msg_ctx);
912         if (!ok) {
913                 DEBUG(0, ("Failed to setup children monitoring!\n"));
914                 exit(1);
915         }
916
917         DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));
918
919         spoolss_manage_pool(ev_ctx, msg_ctx);
920
921         /* loop forever */
922         ret = tevent_loop_wait(ev_ctx);
923
924         /* should not be reached */
925         DEBUG(0,("spoolssd tevent_loop_wait() exited with %d - %s\n",
926                  ret, (ret == 0) ? "out of events" : strerror(errno)));
927         exit(1);
928 }