s3-prefork: Provide a cleanup function
[mat/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         int active, total;
528         int n, r;
529
530         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
531
532         /* run the cleanup function to make sure all dead children are
533          * properly and timely retired. */
534         prefork_cleanup_loop(pfp);
535
536         /* now check we do not descend below the minimum */
537         active = prefork_count_active_children(pfp, &total);
538
539         n = 0;
540         if (total < spoolss_min_children) {
541                 n = total - spoolss_min_children;
542         } else if (total - active < (total / 4)) {
543                 n = spoolss_min_children;
544         }
545
546         if (n > 0) {
547                 r = prefork_add_children(ev_ctx, pfp, n);
548                 if (r < n) {
549                         DEBUG(10, ("Tried to start %d children but only,"
550                                    "%d were actually started.!\n", n, r));
551                 }
552         }
553
554
555 }
556
557 static bool spoolssd_setup_sig_chld_handler(struct tevent_context *ev_ctx,
558                                             struct prefork_pool *pfp)
559 {
560         struct tevent_signal *se;
561
562         se = tevent_add_signal(ev_ctx, ev_ctx, SIGCHLD, 0,
563                                 spoolssd_sig_chld_handler, pfp);
564         if (!se) {
565                 DEBUG(0, ("Failed to setup SIGCHLD handler!\n"));
566                 return false;
567         }
568
569         return true;
570 }
571
572 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
573                                     struct prefork_pool *pfp,
574                                     struct timeval current_time);
575 static void spoolssd_check_children(struct tevent_context *ev_ctx,
576                                     struct tevent_timer *te,
577                                     struct timeval current_time,
578                                     void *pvt);
579
580 static bool spoolssd_setup_children_monitor(struct tevent_context *ev_ctx,
581                                             struct prefork_pool *pfp)
582 {
583         bool ok;
584
585         ok = spoolssd_setup_sig_chld_handler(ev_ctx, pfp);
586         if (!ok) {
587                 return false;
588         }
589
590         ok = spoolssd_schedule_check(ev_ctx, pfp, tevent_timeval_current());
591         return ok;
592 }
593
594 static bool spoolssd_schedule_check(struct tevent_context *ev_ctx,
595                                     struct prefork_pool *pfp,
596                                     struct timeval current_time)
597 {
598         struct tevent_timer *te;
599         struct timeval next_event;
600
601         /* check situation again in 10 seconds */
602         next_event = tevent_timeval_current_ofs(10, 0);
603
604         /* check when the socket becomes readable, so that children
605          * are checked only when there is some activity */
606         te = tevent_add_timer(ev_ctx, pfp, next_event,
607                                 spoolssd_check_children, pfp);
608         if (!te) {
609                 DEBUG(2, ("Failed to set up children monitoring!\n"));
610                 return false;
611         }
612
613         return true;
614 }
615
616 static void spoolssd_check_children(struct tevent_context *ev_ctx,
617                                     struct tevent_timer *te,
618                                     struct timeval current_time,
619                                     void *pvt)
620 {
621         struct prefork_pool *pfp;
622         int active, total;
623         int ret, n;
624
625         pfp = talloc_get_type_abort(pvt, struct prefork_pool);
626
627         if ((spoolss_prefork_status & SPOOLSS_NEW_MAX) &&
628             !(spoolss_prefork_status & SPOLLSS_ENOSPC)) {
629                 ret = prefork_expand_pool(pfp, spoolss_max_children);
630                 if (ret == ENOSPC) {
631                         spoolss_prefork_status |= SPOLLSS_ENOSPC;
632                 }
633                 spoolss_prefork_status &= ~SPOOLSS_NEW_MAX;
634         }
635
636         active = prefork_count_active_children(pfp, &total);
637
638         if (total - active < spoolss_spawn_rate) {
639                 n = prefork_add_children(ev_ctx, pfp, spoolss_spawn_rate);
640                 if (n < spoolss_spawn_rate) {
641                         DEBUG(10, ("Tried to start 5 children but only,"
642                                    "%d were actually started.!\n", n));
643                 }
644         }
645
646         if (total - active > spoolss_min_children) {
647                 if ((total - spoolss_min_children) >= spoolss_spawn_rate) {
648                         prefork_retire_children(pfp, spoolss_spawn_rate,
649                                                 time(NULL) - SPOOLSS_MIN_LIFE);
650                 }
651         }
652
653         ret = spoolssd_schedule_check(ev_ctx, pfp, current_time);
654 }
655
656 void start_spoolssd(struct tevent_context *ev_ctx,
657                     struct messaging_context *msg_ctx)
658 {
659         struct prefork_pool *pool;
660         struct rpc_srv_callbacks spoolss_cb;
661         struct dcerpc_binding_vector *v;
662         TALLOC_CTX *mem_ctx;
663         pid_t pid;
664         NTSTATUS status;
665         int listen_fd;
666         int ret;
667         bool ok;
668
669         DEBUG(1, ("Forking SPOOLSS Daemon\n"));
670
671         pid = sys_fork();
672
673         if (pid == -1) {
674                 DEBUG(0, ("Failed to fork SPOOLSS [%s], aborting ...\n",
675                            strerror(errno)));
676                 exit(1);
677         }
678
679         if (pid) {
680                 /* parent */
681                 return;
682         }
683
684         /* child */
685         close_low_fds(false);
686
687         status = reinit_after_fork(msg_ctx,
688                                    ev_ctx,
689                                    procid_self(), true);
690         if (!NT_STATUS_IS_OK(status)) {
691                 DEBUG(0,("reinit_after_fork() failed\n"));
692                 smb_panic("reinit_after_fork() failed");
693         }
694
695         spoolss_reopen_logs();
696         spoolss_prefork_config();
697
698         /* the listening fd must be created before the children are actually
699          * forked out. */
700         listen_fd = create_named_pipe_socket(SPOOLSS_PIPE_NAME);
701         if (listen_fd == -1) {
702                 exit(1);
703         }
704
705         ret = listen(listen_fd, spoolss_max_children);
706         if (ret == -1) {
707                 DEBUG(0, ("Failed to listen on spoolss pipe - %s\n",
708                           strerror(errno)));
709                 exit(1);
710         }
711
712
713         /* start children before any more initialization is done */
714         ok = prefork_create_pool(ev_ctx, ev_ctx, 1, &listen_fd,
715                                  spoolss_min_children,
716                                  spoolss_max_children,
717                                  &spoolss_children_main, NULL,
718                                  &pool);
719
720         spoolss_setup_sig_term_handler(ev_ctx);
721         spoolss_setup_sig_hup_handler(ev_ctx, pool, msg_ctx);
722
723         if (!serverid_register(procid_self(),
724                                 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
725                                 |FLAG_MSG_PRINT_GENERAL)) {
726                 exit(1);
727         }
728
729         if (!locking_init()) {
730                 exit(1);
731         }
732
733         messaging_register(msg_ctx, NULL,
734                            MSG_PRINTER_UPDATE, print_queue_receive);
735         messaging_register(msg_ctx, ev_ctx,
736                            MSG_SMB_CONF_UPDATED, smb_conf_updated);
737
738         mem_ctx = talloc_new(NULL);
739         if (mem_ctx == NULL) {
740                 exit(1);
741         }
742
743         /*
744          * Initialize spoolss with an init function to convert printers first.
745          * static_init_rpc will try to initialize the spoolss server too but you
746          * can't register it twice.
747          */
748         spoolss_cb.init = spoolss_init_cb;
749         spoolss_cb.shutdown = spoolss_shutdown_cb;
750         spoolss_cb.private_data = msg_ctx;
751
752         status = rpc_winreg_init(NULL);
753         if (!NT_STATUS_IS_OK(status)) {
754                 DEBUG(0, ("Failed to register winreg rpc inteface! (%s)\n",
755                           nt_errstr(status)));
756                 exit(1);
757         }
758
759         status = rpc_spoolss_init(&spoolss_cb);
760         if (!NT_STATUS_IS_OK(status)) {
761                 DEBUG(0, ("Failed to register spoolss rpc inteface! (%s)\n",
762                           nt_errstr(status)));
763                 exit(1);
764         }
765
766         status = dcerpc_binding_vector_new(mem_ctx, &v);
767         if (!NT_STATUS_IS_OK(status)) {
768                 DEBUG(0, ("Failed to create binding vector (%s)\n",
769                           nt_errstr(status)));
770                 exit(1);
771         }
772
773         status = dcerpc_binding_vector_add_np_default(&ndr_table_spoolss, v);
774         if (!NT_STATUS_IS_OK(status)) {
775                 DEBUG(0, ("Failed to add np to binding vector (%s)\n",
776                           nt_errstr(status)));
777                 exit(1);
778         }
779
780         status = rpc_ep_register(ev_ctx, msg_ctx, &ndr_table_spoolss, v);
781         if (!NT_STATUS_IS_OK(status)) {
782                 DEBUG(0, ("Failed to register spoolss endpoint! (%s)\n",
783                           nt_errstr(status)));
784                 exit(1);
785         }
786
787         talloc_free(mem_ctx);
788
789         ok = spoolssd_setup_children_monitor(ev_ctx, pool);
790         if (!ok) {
791                 DEBUG(0, ("Failed to setup children monitoring!\n"));
792                 exit(1);
793         }
794
795         reload_printers(ev_ctx, msg_ctx);
796
797         DEBUG(1, ("SPOOLSS Daemon Started (%d)\n", getpid()));
798
799         /* loop forever */
800         ret = tevent_loop_wait(ev_ctx);
801
802         /* should not be reached */
803         DEBUG(0,("background_queue: tevent_loop_wait() exited with %d - %s\n",
804                  ret, (ret == 0) ? "out of events" : strerror(errno)));
805         exit(1);
806 }