s3-prefork: add support for multiple listning file descriptors
[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 "ntdomain.h"
27 #include "librpc/gen_ndr/srv_winreg.h"
28 #include "librpc/gen_ndr/srv_spoolss.h"
29 #include "rpc_server/rpc_server.h"
30 #include "rpc_server/rpc_ep_register.h"
31 #include "rpc_server/spoolss/srv_spoolss_nt.h"
32 #include "librpc/rpc/dcerpc_ep.h"
33 #include "lib/server_prefork.h"
34
35 #define SPOOLSS_PIPE_NAME "spoolss"
36 #define DAEMON_NAME "spoolssd"
37
38 #define SPOOLSS_MIN_CHILDREN 5
39 #define SPOOLSS_MAX_CHILDREN 25
40 #define SPOOLSS_SPAWN_RATE 5
41 #define SPOOLSS_MIN_LIFE 60 /* 1 minute minimum life time */
42
43 #define SPOOLSS_ALL_FINE 0x00
44 #define SPOOLSS_NEW_MAX  0x01
45 #define SPOLLSS_ENOSPC   0x02
46
47 static int spoolss_min_children;
48 static int spoolss_max_children;
49 static int spoolss_spawn_rate;
50 static int spoolss_prefork_status;
51
52 static void spoolss_prefork_config(void)
53 {
54         static int spoolss_prefork_config_init = false;
55         const char *prefork_str;
56         int min, max, rate;
57         bool use_defaults = false;
58         int ret;
59
60         if (!spoolss_prefork_config_init) {
61                 spoolss_prefork_status = SPOOLSS_ALL_FINE;
62                 spoolss_min_children = 0;
63                 spoolss_max_children = 0;
64                 spoolss_spawn_rate = 0;
65                 spoolss_prefork_config_init = true;
66         }
67
68         prefork_str = lp_parm_const_string(GLOBAL_SECTION_SNUM,
69                                            "spoolssd", "prefork", "none");
70         if (strcmp(prefork_str, "none") == 0) {
71                 use_defaults = true;
72         } else {
73                 ret = sscanf(prefork_str, "%d:%d:%d", &min, &max, &rate);
74                 if (ret != 3) {
75                         DEBUG(0, ("invalid format for spoolssd:prefork!\n"));
76                         use_defaults = true;
77                 }
78         }
79
80         if (use_defaults) {
81                 min = SPOOLSS_MIN_CHILDREN;
82                 max = SPOOLSS_MAX_CHILDREN;
83                 rate = SPOOLSS_SPAWN_RATE;
84         }
85
86         if (max > spoolss_max_children && spoolss_max_children != 0) {
87                 spoolss_prefork_status |= SPOOLSS_NEW_MAX;
88         }
89
90         spoolss_min_children = min;
91         spoolss_max_children = max;
92         spoolss_spawn_rate = rate;
93 }
94
95 void start_spoolssd(struct tevent_context *ev_ctx,
96                     struct messaging_context *msg_ctx);
97
98 static void spoolss_reopen_logs(void)
99 {
100         char *lfile = lp_logfile();
101         int rc;
102
103         if (lfile == NULL || lfile[0] == '\0') {
104                 rc = asprintf(&lfile, "%s/log.%s", get_dyn_LOGFILEBASE(), DAEMON_NAME);
105                 if (rc > 0) {
106                         lp_set_logfile(lfile);
107                         SAFE_FREE(lfile);
108                 }
109         } else {
110                 if (strstr(lfile, DAEMON_NAME) == NULL) {
111                         rc = asprintf(&lfile, "%s.%s", lp_logfile(), DAEMON_NAME);
112                         if (rc > 0) {
113                                 lp_set_logfile(lfile);
114                                 SAFE_FREE(lfile);
115                         }
116                 }
117         }
118
119         reopen_logs();
120 }
121
122 static void update_conf(struct tevent_context *ev,
123                         struct messaging_context *msg)
124 {
125         change_to_root_user();
126         lp_load(get_dyn_CONFIGFILE(), true, false, false, true);
127         reload_printers(ev, msg);
128
129         spoolss_reopen_logs();
130         spoolss_prefork_config();
131 }
132
133 static void smb_conf_updated(struct messaging_context *msg,
134                              void *private_data,
135                              uint32_t msg_type,
136                              struct server_id server_id,
137                              DATA_BLOB *data)
138 {
139         struct tevent_context *ev_ctx = talloc_get_type_abort(private_data,
140                                                              struct tevent_context);
141
142         DEBUG(10, ("Got message saying smb.conf was updated. Reloading.\n"));
143         update_conf(ev_ctx, msg);
144 }
145
146 static void spoolss_sig_term_handler(struct tevent_context *ev,
147                                      struct tevent_signal *se,
148                                      int signum,
149                                      int count,
150                                      void *siginfo,
151                                      void *private_data)
152 {
153         exit_server_cleanly("termination signal");
154 }
155
156 static void spoolss_setup_sig_term_handler(struct tevent_context *ev_ctx)
157 {
158         struct tevent_signal *se;
159
160         se = tevent_add_signal(ev_ctx,
161                                ev_ctx,
162                                SIGTERM, 0,
163                                spoolss_sig_term_handler,
164                                NULL);
165         if (!se) {
166                 exit_server("failed to setup SIGTERM handler");
167         }
168 }
169
170 struct spoolss_hup_ctx {
171         struct messaging_context *msg_ctx;
172         struct prefork_pool *pfp;
173 };
174
175 static void spoolss_sig_hup_handler(struct tevent_context *ev,
176                                     struct tevent_signal *se,
177                                     int signum,
178                                     int count,
179                                     void *siginfo,
180                                     void *pvt)
181 {
182         struct spoolss_hup_ctx *hup_ctx;
183
184         hup_ctx = talloc_get_type_abort(pvt, struct spoolss_hup_ctx);
185
186         DEBUG(1,("Reloading printers after SIGHUP\n"));
187         update_conf(ev, hup_ctx->msg_ctx);
188
189         /* relay to all children */
190         prefork_send_signal_to_all(hup_ctx->pfp, SIGHUP);
191 }
192
193 static void spoolss_setup_sig_hup_handler(struct tevent_context *ev_ctx,
194                                           struct prefork_pool *pfp,
195                                           struct messaging_context *msg_ctx)
196 {
197         struct spoolss_hup_ctx *hup_ctx;
198         struct tevent_signal *se;
199
200         hup_ctx = talloc(ev_ctx, struct spoolss_hup_ctx);
201         if (!hup_ctx) {
202                 exit_server("failed to setup SIGHUP handler");
203         }
204         hup_ctx->pfp = pfp;
205         hup_ctx->msg_ctx = msg_ctx;
206
207         se = tevent_add_signal(ev_ctx,
208                                ev_ctx,
209                                SIGHUP, 0,
210                                spoolss_sig_hup_handler,
211                                hup_ctx);
212         if (!se) {
213                 exit_server("failed to setup SIGHUP handler");
214         }
215 }
216
217 static bool spoolss_init_cb(void *ptr)
218 {
219         struct messaging_context *msg_ctx = talloc_get_type_abort(
220                 ptr, struct messaging_context);
221
222         return nt_printing_tdb_migrate(msg_ctx);
223 }
224
225 static bool spoolss_shutdown_cb(void *ptr)
226 {
227         srv_spoolss_cleanup();
228
229         return true;
230 }
231
232 /* Childrens */
233
234 struct spoolss_chld_sig_hup_ctx {
235         struct messaging_context *msg_ctx;
236         struct pf_worker_data *pf;
237 };
238
239 static void spoolss_chld_sig_hup_handler(struct tevent_context *ev,
240                                          struct tevent_signal *se,
241                                          int signum,
242                                          int count,
243                                          void *siginfo,
244                                          void *pvt)
245 {
246         struct spoolss_chld_sig_hup_ctx *shc;
247
248         shc = talloc_get_type_abort(pvt, struct spoolss_chld_sig_hup_ctx);
249
250         /* avoid wasting CPU cycles if we are going to exit soon anyways */
251         if (shc->pf != NULL &&
252             shc->pf->cmds == PF_SRV_MSG_EXIT) {
253                 return;
254         }
255
256         change_to_root_user();
257         DEBUG(1,("Reloading printers after SIGHUP\n"));
258         reload_printers(ev, shc->msg_ctx);
259         spoolss_reopen_logs();
260 }
261
262 static bool spoolss_setup_chld_hup_handler(struct tevent_context *ev_ctx,
263                                            struct pf_worker_data *pf,
264                                            struct messaging_context *msg_ctx)
265 {
266         struct spoolss_chld_sig_hup_ctx *shc;
267         struct tevent_signal *se;
268
269         shc = talloc(ev_ctx, struct spoolss_chld_sig_hup_ctx);
270         if (!shc) {
271                 DEBUG(1, ("failed to setup SIGHUP handler"));
272                 return false;
273         }
274         shc->pf = pf;
275         shc->msg_ctx = msg_ctx;
276
277         se = tevent_add_signal(ev_ctx,
278                                ev_ctx,
279                                SIGHUP, 0,
280                                spoolss_chld_sig_hup_handler,
281                                shc);
282         if (!se) {
283                 DEBUG(1, ("failed to setup SIGHUP handler"));
284                 return false;
285         }
286
287         return true;
288 }
289
290 static bool spoolss_child_init(struct tevent_context *ev_ctx,
291                                         struct pf_worker_data *pf)
292 {
293         NTSTATUS status;
294         struct rpc_srv_callbacks spoolss_cb;
295         struct messaging_context *msg_ctx = server_messaging_context();
296         bool ok;
297
298         status = reinit_after_fork(msg_ctx, ev_ctx,
299                                    procid_self(), true);
300         if (!NT_STATUS_IS_OK(status)) {
301                 DEBUG(0,("reinit_after_fork() failed\n"));
302                 smb_panic("reinit_after_fork() failed");
303         }
304
305         spoolss_reopen_logs();
306
307         ok = spoolss_setup_chld_hup_handler(ev_ctx, pf, msg_ctx);
308         if (!ok) {
309                 return false;
310         }
311
312         if (!serverid_register(procid_self(), FLAG_MSG_GENERAL)) {
313                 return false;
314         }
315
316         if (!locking_init()) {
317                 return false;
318         }
319
320         messaging_register(msg_ctx, ev_ctx,
321                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
322
323         /* try to reinit rpc queues */
324         spoolss_cb.init = spoolss_init_cb;
325         spoolss_cb.shutdown = spoolss_shutdown_cb;
326         spoolss_cb.private_data = msg_ctx;
327
328         status = rpc_winreg_init(NULL);
329         if (!NT_STATUS_IS_OK(status)) {
330                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
331                           nt_errstr(status)));
332                 return false;
333         }
334
335         status = rpc_spoolss_init(&spoolss_cb);
336         if (!NT_STATUS_IS_OK(status)) {
337                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
338                           nt_errstr(status)));
339                 return false;
340         }
341
342         reload_printers(ev_ctx, msg_ctx);
343
344         return true;
345 }
346
347 struct spoolss_children_data {
348         struct tevent_context *ev_ctx;
349         struct messaging_context *msg_ctx;
350         struct pf_worker_data *pf;
351         int listen_fd_size;
352         int *listen_fds;
353         int lock_fd;
354
355         bool listening;
356 };
357
358 static void spoolss_next_client(void *pvt);
359
360 static int spoolss_children_main(struct tevent_context *ev_ctx,
361                                  struct pf_worker_data *pf,
362                                  int listen_fd_size,
363                                  int *listen_fds,
364                                  int lock_fd,
365                                  void *private_data)
366 {
367         struct messaging_context *msg_ctx = server_messaging_context();
368         struct spoolss_children_data *data;
369         bool ok;
370         int ret;
371
372         ok = spoolss_child_init(ev_ctx, pf);
373         if (!ok) {
374                 return 1;
375         }
376
377         data = talloc(ev_ctx, struct spoolss_children_data);
378         if (!data) {
379                 return 1;
380         }
381         data->pf = pf;
382         data->ev_ctx = ev_ctx;
383         data->msg_ctx = msg_ctx;
384         data->lock_fd = lock_fd;
385         data->listen_fd_size = listen_fd_size;
386         data->listen_fds = listen_fds;
387         data->listening = false;
388
389         /* loop until it is time to exit */
390         while (pf->status != PF_WORKER_EXITING) {
391                 /* try to see if it is time to schedule the next client */
392                 spoolss_next_client(data);
393
394                 ret = tevent_loop_once(ev_ctx);
395                 if (ret != 0) {
396                         DEBUG(0, ("tevent_loop_once() exited with %d: %s\n",
397                                   ret, strerror(errno)));
398                         pf->status = PF_WORKER_EXITING;
399                 }
400         }
401
402         return ret;
403 }
404
405 static void spoolss_client_terminated(void *pvt)
406 {
407         struct spoolss_children_data *data;
408
409         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
410
411         if (data->pf->num_clients) {
412                 data->pf->num_clients--;
413         } else {
414                 DEBUG(2, ("Invalid num clients, aborting!\n"));
415                 data->pf->status = PF_WORKER_EXITING;
416                 return;
417         }
418
419         spoolss_next_client(pvt);
420 }
421
422 struct spoolss_new_client {
423         struct spoolss_children_data *data;
424         struct sockaddr_un sunaddr;
425         socklen_t addrlen;
426 };
427
428 static void spoolss_handle_client(struct tevent_req *req);
429
430 static void spoolss_next_client(void *pvt)
431 {
432         struct tevent_req *req;
433         struct spoolss_children_data *data;
434         struct spoolss_new_client *next;
435
436         data = talloc_get_type_abort(pvt, struct spoolss_children_data);
437
438         if (data->pf->num_clients == 0) {
439                 data->pf->status = PF_WORKER_IDLE;
440         }
441
442         if (data->pf->cmds == PF_SRV_MSG_EXIT) {
443                 DEBUG(2, ("Parent process commands we terminate!\n"));
444                 return;
445         }
446
447         if (data->listening ||
448             data->pf->num_clients >= data->pf->allowed_clients) {
449                 /* nothing to do for now we are already listening
450                  * or reached the number of clients we are allowed
451                  * to handle in parallel */
452                 return;
453         }
454
455         next = talloc_zero(data, struct spoolss_new_client);
456         if (!next) {
457                 DEBUG(1, ("Out of memory!?\n"));
458                 return;
459         }
460         next->data = data;
461         next->addrlen = sizeof(next->sunaddr);
462
463         req = prefork_listen_send(next, data->ev_ctx, data->pf,
464                                   data->listen_fd_size,
465                                   data->listen_fds,
466                                   data->lock_fd,
467                                   (struct sockaddr *)&next->sunaddr,
468                                   &next->addrlen);
469         if (!req) {
470                 DEBUG(1, ("Failed to make listening request!?\n"));
471                 talloc_free(next);
472                 return;
473         }
474         tevent_req_set_callback(req, spoolss_handle_client, next);
475
476         data->listening = true;
477 }
478
479 static void spoolss_handle_client(struct tevent_req *req)
480 {
481         struct spoolss_children_data *data;
482         struct spoolss_new_client *client;
483         int ret;
484         int sd;
485
486         client = tevent_req_callback_data(req, struct spoolss_new_client);
487         data = client->data;
488
489         ret = prefork_listen_recv(req, &sd);
490
491         /* this will free the request too */
492         talloc_free(client);
493         /* we are done listening */
494         data->listening = false;
495
496         if (ret > 0) {
497                 DEBUG(1, ("Failed to accept client connection!\n"));
498                 /* bail out if we are not serving any other client */
499                 if (data->pf->num_clients == 0) {
500                         data->pf->status = PF_WORKER_EXITING;
501                 }
502                 return;
503         }
504
505         if (ret == -2) {
506                 DEBUG(1, ("Server asks us to die!\n"));
507                 data->pf->status = PF_WORKER_EXITING;
508                 return;
509         }
510
511         DEBUG(2, ("Spoolss preforked child %d got client connection!\n",
512                   (int)(data->pf->pid)));
513
514         named_pipe_accept_function(data->ev_ctx, data->msg_ctx,
515                                    SPOOLSS_PIPE_NAME, sd,
516                                    spoolss_client_terminated, data);
517 }
518
519 /* ==== Main Process Functions ==== */
520
521 static void spoolssd_sig_chld_handler(struct tevent_context *ev_ctx,
522                                       struct tevent_signal *se,
523                                       int signum, int count,
524                                       void *siginfo, void *pvt)
525 {
526         struct prefork_pool *pfp;
527         pid_t pid;
528         int status;
529         bool ok;
530         int active, total;
531         int n, r;
532
533         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
534
535         while ((pid = sys_waitpid(-1, &status, WNOHANG)) > 0) {
536                 ok = prefork_mark_pid_dead(pfp, pid);
537                 if (!ok) {
538                         DEBUG(1, ("Pid %d was not found in children pool!\n",
539                                   (int)pid));
540                 }
541         }
542
543         /* now check we do not descent below the minimum */
544         active = prefork_count_active_children(pfp, &total);
545
546         n = 0;
547         if (total < spoolss_min_children) {
548                 n = total - spoolss_min_children;
549         } else if (total - active < (total / 4)) {
550                 n = spoolss_min_children;
551         }
552
553         if (n > 0) {
554                 r = prefork_add_children(ev_ctx, pfp, n);
555                 if (r < n) {
556                         DEBUG(10, ("Tried to start %d children but only,"
557                                    "%d were actually started.!\n", n, r));
558                 }
559         }
560
561
562 }
563
564 static bool spoolssd_setup_sig_chld_handler(struct tevent_context *ev_ctx,
565                                             struct prefork_pool *pfp)
566 {
567         struct tevent_signal *se;
568
569         se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
570                                 spoolssd_sig_chld_handler, pfp);
571         if (!se) {
572                 DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
573                 return false;
574         }
575
576         return true;
577 }
578
579 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
580                                     struct prefork_pool *pfp,
581                                     struct timeval current_time);
582 static void spoolssd_check_children(struct tevent_context *ev_ctx,
583                                     struct tevent_timer *te,
584                                     struct timeval current_time,
585                                     void *pvt);
586
587 static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
588                                             struct prefork_pool *pfp)
589 {
590         bool ok;
591
592         ok = spoolssd_setup_sig_chld_handler(ev_ctx, pfp);
593         if (!ok) {
594                 return false;
595         }
596
597         ok = spoolssd_schedule_check(ev_ctx, pfp, tevent_timeval_current());
598         return ok;
599 }
600
601 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
602                                     struct prefork_pool *pfp,
603                                     struct timeval current_time)
604 {
605         struct tevent_timer *te;
606         struct timeval next_event;
607
608         /* check situation again in 10 seconds */
609         next_event = tevent_timeval_current_ofs(10, 0);
610
611         /* check when the socket becomes readable, so that children
612          * are checked only when there is some activity */
613         te = tevent_add_timer(ev_ctx, pfp, next_event,
614                                 spoolssd_check_children, pfp);
615         if (!te) {
616                 DEBUG(2, ("Failed to set up children monitoring!\n"));
617                 return false;
618         }
619
620         return true;
621 }
622
623 static void spoolssd_check_children(struct tevent_context *ev_ctx,
624                                     struct tevent_timer *te,
625                                     struct timeval current_time,
626                                     void *pvt)
627 {
628         struct prefork_pool *pfp;
629         int active, total;
630         int ret, n;
631
632         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
633
634         if ((spoolss_prefork_status & SPOOLSS_NEW_MAX) &&
635             !(spoolss_prefork_status & SPOLLSS_ENOSPC)) {
636                 ret = prefork_expand_pool(pfp, spoolss_max_children);
637                 if (ret == ENOSPC) {
638                         spoolss_prefork_status |= SPOLLSS_ENOSPC;
639                 }
640                 spoolss_prefork_status &= ~SPOOLSS_NEW_MAX;
641         }
642
643         active = prefork_count_active_children(pfp, &total);
644
645         if (total - active < spoolss_spawn_rate) {
646                 n = prefork_add_children(ev_ctx, pfp, spoolss_spawn_rate);
647                 if (n < spoolss_spawn_rate) {
648                         DEBUG(10, ("Tried to start 5 children but only,"
649                                    "%d were actually started.!\n", n));
650                 }
651         }
652
653         if (total - active > spoolss_min_children) {
654                 if ((total - spoolss_min_children) >= spoolss_spawn_rate) {
655                         prefork_retire_children(pfp, spoolss_spawn_rate,
656                                                 time(NULL) - SPOOLSS_MIN_LIFE);
657                 }
658         }
659
660         ret = spoolssd_schedule_check(ev_ctx, pfp, current_time);
661 }
662
663 void start_spoolssd(struct tevent_context *ev_ctx,
664                     struct messaging_context *msg_ctx)
665 {
666         struct prefork_pool *pool;
667         struct rpc_srv_callbacks spoolss_cb;
668         struct dcerpc_binding_vector *v;
669         TALLOC_CTX *mem_ctx;
670         pid_t pid;
671         NTSTATUS status;
672         int listen_fd;
673         int ret;
674         bool ok;
675
676         DEBUG(1, ("Forking SPOOLSS Daemon\n"));
677
678         pid = sys_fork();
679
680         if (pid == -1) {
681                 DEBUG(0, ("Failed to fork SPOOLSS [%s], aborting ...\n",
682                            strerror(errno)));
683                 exit(1);
684         }
685
686         if (pid) {
687                 /* parent */
688                 return;
689         }
690
691         /* child */
692         close_low_fds(false);
693
694         status = reinit_after_fork(msg_ctx,
695                                    ev_ctx,
696                                    procid_self(), true);
697         if (!NT_STATUS_IS_OK(status)) {
698                 DEBUG(0,("reinit_after_fork() failed\n"));
699                 smb_panic("reinit_after_fork() failed");
700         }
701
702         spoolss_reopen_logs();
703         spoolss_prefork_config();
704
705         /* the listening fd must be created before the children are actually
706          * forked out. */
707         listen_fd = create_named_pipe_socket(SPOOLSS_PIPE_NAME);
708         if (listen_fd == -1) {
709                 exit(1);
710         }
711
712         ret = listen(listen_fd, spoolss_max_children);
713         if (ret == -1) {
714                 DEBUG(0, ("Failed to listen on spoolss pipe - %s\n",
715                           strerror(errno)));
716                 exit(1);
717         }
718
719
720         /* start children before any more initialization is done */
721         ok = prefork_create_pool(ev_ctx, ev_ctx, 1, &listen_fd,
722                                  spoolss_min_children,
723                                  spoolss_max_children,
724                                  &spoolss_children_main, NULL,
725                                  &pool);
726
727         spoolss_setup_sig_term_handler(ev_ctx);
728         spoolss_setup_sig_hup_handler(ev_ctx, pool, msg_ctx);
729
730         if (!serverid_register(procid_self(),
731                                 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
732                                 |FLAG_MSG_PRINT_GENERAL)) {
733                 exit(1);
734         }
735
736         if (!locking_init()) {
737                 exit(1);
738         }
739
740         messaging_register(msg_ctx, NULL,
741                            MSG_PRINTER_UPDATE, print_queue_receive);
742         messaging_register(msg_ctx, ev_ctx,
743                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
744
745         mem_ctx = talloc_new(NULL);
746         if (mem_ctx == NULL) {
747                 exit(1);
748         }
749
750         /*
751          * Initialize spoolss with an init function to convert printers first.
752          * static_init_rpc will try to initialize the spoolss server too but you
753          * can't register it twice.
754          */
755         spoolss_cb.init = spoolss_init_cb;
756         spoolss_cb.shutdown = spoolss_shutdown_cb;
757         spoolss_cb.private_data = msg_ctx;
758
759         status = rpc_winreg_init(NULL);
760         if (!NT_STATUS_IS_OK(status)) {
761                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
762                           nt_errstr(status)));
763                 exit(1);
764         }
765
766         status = rpc_spoolss_init(&spoolss_cb);
767         if (!NT_STATUS_IS_OK(status)) {
768                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
769                           nt_errstr(status)));
770                 exit(1);
771         }
772
773         status = dcerpc_binding_vector_new(mem_ctx, &v);
774         if (!NT_STATUS_IS_OK(status)) {
775                 DEBUG(0, ("Failed to create binding vector (%s)\n",
776                           nt_errstr(status)));
777                 exit(1);
778         }
779
780         status = dcerpc_binding_vector_add_np_default(&ndr_table_spoolss, v);
781         if (!NT_STATUS_IS_OK(status)) {
782                 DEBUG(0, ("Failed to add np to binding vector (%s)\n",
783                           nt_errstr(status)));
784                 exit(1);
785         }
786
787         status = rpc_ep_register(ev_ctx, msg_ctx, &ndr_table_spoolss, v);
788         if (!NT_STATUS_IS_OK(status)) {
789                 DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
790                           nt_errstr(status)));
791                 exit(1);
792         }
793
794         talloc_free(mem_ctx);
795
796         ok = spoolssd_setup_children_monitor(ev_ctx, pool);
797         if (!ok) {
798                 DEBUG(0, ("Failed to setup children monitoring!\n"));
799                 exit(1);
800         }
801
802         reload_printers(ev_ctx, msg_ctx);
803
804         DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));
805
806         /* loop forever */
807         ret = tevent_loop_wait(ev_ctx);
808
809         /* should not be reached */
810         DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
811                  ret, (ret == 0) ? "out of events" : strerror(errno)));
812         exit(1);
813 }