2010-05-20 08:48:18 -04:00
/*
Unix SMB / Netbios implementation .
SPOOLSS Daemon
Copyright ( C ) Simo Sorce 2010
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "includes.h"
2011-03-24 10:22:57 +01:00
# include "serverid.h"
2011-03-22 23:49:17 +01:00
# include "smbd/smbd.h"
2011-03-23 12:43:17 +01:00
# include "locking/proto.h"
2011-03-24 10:22:57 +01:00
2011-03-24 15:31:06 +01:00
# include "messages.h"
2010-05-20 08:48:18 -04:00
# include "include/printing.h"
2010-06-15 18:39:27 -04:00
# include "printing/nt_printing_migrate.h"
# include "librpc/gen_ndr/srv_winreg.h"
# include "librpc/gen_ndr/srv_spoolss.h"
2010-05-20 08:48:18 -04:00
# include "rpc_server/rpc_server.h"
2011-03-28 14:18:23 +02:00
# include "rpc_server/rpc_ep_setup.h"
2010-05-20 08:48:18 -04:00
# define SPOOLSS_PIPE_NAME "spoolss"
2010-08-25 10:15:47 +02:00
# define DAEMON_NAME "spoolssd"
2010-06-15 18:38:44 -04:00
2011-01-20 18:59:40 +01:00
void start_spoolssd ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ) ;
2010-06-15 18:38:44 -04:00
static void spoolss_reopen_logs ( void )
{
2010-08-25 10:15:47 +02:00
char * lfile = lp_logfile ( ) ;
int rc ;
2010-06-15 18:38:44 -04:00
2011-03-28 14:30:29 +02:00
if ( lfile = = NULL | | lfile [ 0 ] = = ' \0 ' ) {
rc = asprintf ( & lfile , " %s/log.%s " , get_dyn_LOGFILEBASE ( ) , DAEMON_NAME ) ;
2010-08-25 10:15:47 +02:00
if ( rc > 0 ) {
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
}
2011-03-28 14:30:29 +02:00
} else {
if ( strstr ( lfile , DAEMON_NAME ) = = NULL ) {
rc = asprintf ( & lfile , " %s.%s " , lp_logfile ( ) , DAEMON_NAME ) ;
if ( rc > 0 ) {
lp_set_logfile ( lfile ) ;
SAFE_FREE ( lfile ) ;
}
}
2010-06-15 18:38:44 -04:00
}
2011-03-28 14:30:29 +02:00
2010-06-15 18:38:44 -04:00
reopen_logs ( ) ;
}
2010-06-16 15:36:06 -04:00
static void smb_conf_updated ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id server_id ,
DATA_BLOB * data )
{
2011-01-20 18:59:40 +01:00
struct tevent_context * ev_ctx = talloc_get_type_abort ( private_data ,
struct tevent_context ) ;
2010-06-16 15:36:06 -04:00
DEBUG ( 10 , ( " Got message saying smb.conf was updated. Reloading. \n " ) ) ;
change_to_root_user ( ) ;
2011-01-20 18:59:40 +01:00
reload_printers ( ev_ctx , msg ) ;
2010-06-16 15:36:06 -04:00
spoolss_reopen_logs ( ) ;
}
2010-06-16 13:03:32 -04:00
static void spoolss_sig_term_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
exit_server_cleanly ( " termination signal " ) ;
}
2011-01-20 18:59:40 +01:00
static void spoolss_setup_sig_term_handler ( struct tevent_context * ev_ctx )
2010-06-16 13:03:32 -04:00
{
struct tevent_signal * se ;
2011-01-20 18:59:40 +01:00
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
2010-06-16 13:03:32 -04:00
SIGTERM , 0 ,
spoolss_sig_term_handler ,
NULL ) ;
if ( ! se ) {
exit_server ( " failed to setup SIGTERM handler " ) ;
}
}
static void spoolss_sig_hup_handler ( struct tevent_context * ev ,
struct tevent_signal * se ,
int signum ,
int count ,
void * siginfo ,
void * private_data )
{
2011-01-20 18:59:40 +01:00
struct messaging_context * msg_ctx = talloc_get_type_abort ( private_data ,
struct messaging_context ) ;
2010-06-16 13:03:32 -04:00
change_to_root_user ( ) ;
DEBUG ( 1 , ( " Reloading printers after SIGHUP \n " ) ) ;
2011-01-20 18:59:40 +01:00
reload_printers ( ev , msg_ctx ) ;
2010-06-16 13:03:32 -04:00
spoolss_reopen_logs ( ) ;
}
2011-01-20 18:59:40 +01:00
static void spoolss_setup_sig_hup_handler ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx )
2010-06-16 13:03:32 -04:00
{
struct tevent_signal * se ;
2011-01-20 18:59:40 +01:00
se = tevent_add_signal ( ev_ctx ,
ev_ctx ,
2010-06-16 13:03:32 -04:00
SIGHUP , 0 ,
spoolss_sig_hup_handler ,
2011-01-20 18:59:40 +01:00
msg_ctx ) ;
2010-06-16 13:03:32 -04:00
if ( ! se ) {
exit_server ( " failed to setup SIGHUP handler " ) ;
}
}
2010-06-15 18:39:27 -04:00
static bool spoolss_init_cb ( void * ptr )
{
2011-01-20 18:59:40 +01:00
struct messaging_context * msg_ctx = talloc_get_type_abort (
ptr , struct messaging_context ) ;
return nt_printing_tdb_migrate ( msg_ctx ) ;
}
static bool spoolss_shutdown_cb ( void * ptr )
{
srv_spoolss_cleanup ( ) ;
return true ;
2010-06-15 18:39:27 -04:00
}
2011-01-20 18:59:40 +01:00
void start_spoolssd ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx )
2010-05-20 08:48:18 -04:00
{
2010-06-15 18:39:27 -04:00
struct rpc_srv_callbacks spoolss_cb ;
2010-05-20 08:48:18 -04:00
pid_t pid ;
NTSTATUS status ;
int ret ;
DEBUG ( 1 , ( " Forking SPOOLSS Daemon \n " ) ) ;
pid = sys_fork ( ) ;
if ( pid = = - 1 ) {
DEBUG ( 0 , ( " Failed to fork SPOOLSS [%s], aborting ... \n " ,
strerror ( errno ) ) ) ;
exit ( 1 ) ;
}
if ( pid ) {
/* parent */
return ;
}
/* child */
2010-06-15 18:38:44 -04:00
close_low_fds ( false ) ;
2011-01-20 18:59:40 +01:00
status = reinit_after_fork ( msg_ctx ,
ev_ctx ,
2010-05-20 08:48:18 -04:00
procid_self ( ) , true ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " reinit_after_fork() failed \n " ) ) ;
smb_panic ( " reinit_after_fork() failed " ) ;
}
2010-06-15 18:38:44 -04:00
spoolss_reopen_logs ( ) ;
2011-01-20 18:59:40 +01:00
spoolss_setup_sig_term_handler ( ev_ctx ) ;
spoolss_setup_sig_hup_handler ( ev_ctx , msg_ctx ) ;
2010-05-20 08:48:18 -04:00
if ( ! serverid_register ( procid_self ( ) ,
FLAG_MSG_GENERAL | FLAG_MSG_SMBD
| FLAG_MSG_PRINT_GENERAL ) ) {
exit ( 1 ) ;
}
if ( ! locking_init ( ) ) {
exit ( 1 ) ;
}
2011-01-20 18:59:40 +01:00
messaging_register ( msg_ctx , NULL ,
2010-05-20 08:48:18 -04:00
MSG_PRINTER_UPDATE , print_queue_receive ) ;
2011-01-20 18:59:40 +01:00
messaging_register ( msg_ctx , ev_ctx ,
2010-06-16 15:36:06 -04:00
MSG_SMB_CONF_UPDATED , smb_conf_updated ) ;
2010-05-20 08:48:18 -04:00
2010-06-15 18:39:27 -04:00
/*
* Initialize spoolss with an init function to convert printers first .
* static_init_rpc will try to initialize the spoolss server too but you
* can ' t register it twice .
*/
spoolss_cb . init = spoolss_init_cb ;
2011-01-20 18:59:40 +01:00
spoolss_cb . shutdown = spoolss_shutdown_cb ;
spoolss_cb . private_data = msg_ctx ;
2010-06-15 18:39:27 -04:00
status = rpc_winreg_init ( NULL ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register winreg rpc inteface! (%s) \n " ,
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
status = rpc_spoolss_init ( & spoolss_cb ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register spoolss rpc inteface! (%s) \n " ,
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
2011-01-20 18:59:40 +01:00
if ( ! setup_named_pipe_socket ( SPOOLSS_PIPE_NAME , ev_ctx ) ) {
2010-05-20 08:48:18 -04:00
exit ( 1 ) ;
}
2011-03-28 14:18:23 +02:00
status = rpc_ep_setup_register ( ev_ctx , msg_ctx , & ndr_table_spoolss , NULL , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Failed to register spoolss endpoint! (%s) \n " ,
nt_errstr ( status ) ) ) ;
exit ( 1 ) ;
}
2010-06-15 18:39:27 -04:00
DEBUG ( 1 , ( " SPOOLSS Daemon Started (%d) \n " , getpid ( ) ) ) ;
2010-05-20 08:48:18 -04:00
/* loop forever */
2011-01-20 18:59:40 +01:00
ret = tevent_loop_wait ( ev_ctx ) ;
2010-05-20 08:48:18 -04:00
/* should not be reached */
DEBUG ( 0 , ( " background_queue: tevent_loop_wait() exited with %d - %s \n " ,
ret , ( ret = = 0 ) ? " out of events " : strerror ( errno ) ) ) ;
exit ( 1 ) ;
}