2012-11-02 11:42:28 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2003-04-14 07:59:25 +04:00
Send messages to other Samba daemons
Copyright ( C ) Tim Potter 2003
2000-09-13 11:07:17 +04:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
2003-04-14 07:59:25 +04:00
Copyright ( C ) Martin Pool 2001 - 2002
2002-07-15 14:35:28 +04:00
Copyright ( C ) Simo Sorce 2002
2006-05-04 04:35:05 +04:00
Copyright ( C ) James Peach 2006
2010-07-19 23:00:31 +04:00
2000-09-13 11:07:17 +04:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-09-13 11:07:17 +04:00
( at your option ) any later version .
2010-07-19 23:00:31 +04:00
2000-09-13 11:07:17 +04:00
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 .
2010-07-19 23:00:31 +04:00
2000-09-13 11:07:17 +04:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-09-13 11:07:17 +04:00
*/
# include "includes.h"
2011-02-26 01:20:06 +03:00
# include "system/filesys.h"
2017-01-01 23:00:55 +03:00
# include "lib/util/server_id.h"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2010-07-31 02:47:20 +04:00
# include "librpc/gen_ndr/spoolss.h"
# include "nt_printing.h"
2011-02-22 12:28:29 +03:00
# include "printing/notify.h"
2011-03-23 16:18:59 +03:00
# include "libsmb/nmblib.h"
2011-03-24 17:31:06 +03:00
# include "messages.h"
2011-05-05 13:25:29 +04:00
# include "util_tdb.h"
2012-07-20 03:36:18 +04:00
# include "../lib/util/pidfile.h"
2013-01-27 20:24:49 +04:00
# include "serverid.h"
2018-08-21 22:35:11 +03:00
# include "cmdline_contexts.h"
2000-09-13 11:07:17 +04:00
2018-11-20 17:57:51 +03:00
# ifdef HAVE_LIBUNWIND_H
2006-05-04 04:35:05 +04:00
# include <libunwind.h>
# endif
2018-11-20 17:57:51 +03:00
# ifdef HAVE_LIBUNWIND_PTRACE_H
2006-05-04 04:35:05 +04:00
# include <libunwind-ptrace.h>
# endif
2018-11-20 17:57:51 +03:00
# ifdef HAVE_SYS_PTRACE_H
2006-05-04 04:35:05 +04:00
# include <sys/ptrace.h>
# endif
2003-04-14 07:59:25 +04:00
/* Default timeout value when waiting for replies (in seconds) */
2002-01-08 00:32:22 +03:00
2003-04-14 07:59:25 +04:00
# define DEFAULT_TIMEOUT 10
2000-09-13 11:07:17 +04:00
2003-04-14 07:59:25 +04:00
static int timeout = DEFAULT_TIMEOUT ;
static int num_replies ; /* Used by message callback fns */
2000-10-12 04:29:01 +04:00
2003-04-14 07:59:25 +04:00
/* Send a message to a destination pid. Zero means broadcast smbd. */
2000-10-12 04:29:01 +04:00
2007-10-19 04:40:25 +04:00
static bool send_message ( struct messaging_context * msg_ctx ,
2007-05-15 18:39:18 +04:00
struct server_id pid , int msg_type ,
2007-05-22 02:17:13 +04:00
const void * buf , int len )
2003-04-14 07:59:25 +04:00
{
2005-09-30 21:13:37 +04:00
if ( procid_to_pid ( & pid ) ! = 0 )
2007-05-15 18:39:18 +04:00
return NT_STATUS_IS_OK (
messaging_send_buf ( msg_ctx , pid , msg_type ,
2015-04-27 02:02:55 +03:00
( const uint8_t * ) buf , len ) ) ;
2003-04-14 07:59:25 +04:00
2017-11-05 14:54:10 +03:00
messaging_send_all ( msg_ctx , msg_type , buf , len ) ;
2010-07-19 23:00:31 +04:00
2017-11-05 14:54:10 +03:00
return true ;
2003-04-14 07:59:25 +04:00
}
2002-11-26 03:46:31 +03:00
2009-01-21 09:30:13 +03:00
static void smbcontrol_timeout ( struct tevent_context * event_ctx ,
struct tevent_timer * te ,
struct timeval now ,
void * private_data )
2007-07-24 13:20:23 +04:00
{
2007-10-19 04:40:25 +04:00
bool * timed_out = ( bool * ) private_data ;
2007-07-24 13:20:23 +04:00
TALLOC_FREE ( te ) ;
* timed_out = True ;
}
2003-04-14 07:59:25 +04:00
/* Wait for one or more reply messages */
2012-01-16 19:11:42 +04:00
static void wait_replies ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-10-19 04:40:25 +04:00
bool multiple_replies )
2003-04-14 07:59:25 +04:00
{
2009-01-21 09:30:13 +03:00
struct tevent_timer * te ;
2007-10-19 04:40:25 +04:00
bool timed_out = False ;
2007-07-24 13:20:23 +04:00
2012-12-06 18:40:29 +04:00
te = tevent_add_timer ( ev_ctx , NULL ,
timeval_current_ofs ( timeout , 0 ) ,
smbcontrol_timeout , ( void * ) & timed_out ) ;
if ( te = = NULL ) {
2009-01-21 09:30:13 +03:00
DEBUG ( 0 , ( " tevent_add_timer failed \n " ) ) ;
2007-07-24 13:20:23 +04:00
return ;
}
2002-11-26 03:46:31 +03:00
2007-07-24 13:20:23 +04:00
while ( ! timed_out ) {
2009-01-21 09:30:13 +03:00
int ret ;
2003-04-14 07:59:25 +04:00
if ( num_replies > 0 & & ! multiple_replies )
break ;
2012-01-16 19:11:42 +04:00
ret = tevent_loop_once ( ev_ctx ) ;
2009-01-21 09:30:13 +03:00
if ( ret ! = 0 ) {
break ;
}
2007-07-24 13:20:23 +04:00
}
2003-04-14 07:59:25 +04:00
}
2004-04-30 03:05:58 +04:00
/* Message handler callback that displays the PID and a string on stdout */
2007-05-16 17:02:53 +04:00
static void print_pid_string_cb ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
2004-04-30 03:05:58 +04:00
{
2014-11-04 15:59:25 +03:00
struct server_id_buf pidstr ;
2010-03-05 19:06:08 +03:00
2014-11-04 15:59:25 +03:00
printf ( " PID %s: %.*s " , server_id_str_buf ( pid , & pidstr ) ,
( int ) data - > length , ( const char * ) data - > data ) ;
2004-04-30 03:05:58 +04:00
num_replies + + ;
}
2003-04-14 07:59:25 +04:00
/* Send no message. Useful for testing. */
2012-01-16 19:08:48 +04:00
static bool do_noop ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> noop \n " ) ;
return False ;
2000-09-30 00:08:00 +04:00
}
2003-04-14 07:59:25 +04:00
/* Move along, nothing to see here */
return True ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Send a debug string */
2012-01-16 19:08:48 +04:00
static bool do_debug ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2001-12-21 07:28:03 +03:00
{
2003-04-14 07:59:25 +04:00
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> debug "
" <debug-string> \n " ) ;
return False ;
}
2001-12-21 07:28:03 +03:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_DEBUG , argv [ 1 ] ,
strlen ( argv [ 1 ] ) + 1 ) ;
2003-04-14 07:59:25 +04:00
}
2011-02-03 18:30:29 +03:00
2012-01-16 19:08:48 +04:00
static bool do_idmap ( struct tevent_context * ev ,
struct messaging_context * msg_ctx ,
2011-02-03 18:30:29 +03:00
const struct server_id pid ,
const int argc , const char * * argv )
{
static const char * usage = " Usage: "
" smbcontrol <dest> idmap <cmd> [arg] \n "
2012-04-20 12:37:24 +04:00
" \t cmd: "
" \t delete \" UID <uid> \" | \" GID <gid> \" |<sid> \n "
2011-02-03 18:30:29 +03:00
" \t \t kill \" UID <uid> \" | \" GID <gid> \" |<sid> \n " ;
const char * arg = NULL ;
int arglen = 0 ;
int msg_type ;
switch ( argc ) {
case 2 :
break ;
case 3 :
arg = argv [ 2 ] ;
arglen = strlen ( arg ) + 1 ;
break ;
default :
fprintf ( stderr , " %s " , usage ) ;
return false ;
}
2012-04-20 12:37:24 +04:00
if ( strcmp ( argv [ 1 ] , " delete " ) = = 0 ) {
2011-08-19 20:10:29 +04:00
msg_type = ID_CACHE_DELETE ;
2011-02-03 18:30:29 +03:00
}
else if ( strcmp ( argv [ 1 ] , " kill " ) = = 0 ) {
2011-08-19 20:10:29 +04:00
msg_type = ID_CACHE_KILL ;
2011-02-03 18:30:29 +03:00
}
else if ( strcmp ( argv [ 1 ] , " help " ) = = 0 ) {
fprintf ( stdout , " %s " , usage ) ;
return true ;
}
else {
fprintf ( stderr , " %s " , usage ) ;
return false ;
}
return send_message ( msg_ctx , pid , msg_type , arg , arglen ) ;
}
2006-05-04 04:35:05 +04:00
# if defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE)
/* Return the name of a process given it's PID. This will only work on Linux,
2014-08-18 12:24:35 +04:00
* but that ' s probably moot since this whole stack tracing implementation is
2006-05-04 04:35:05 +04:00
* Linux - specific anyway .
*/
static const char * procname ( pid_t pid , char * buf , size_t bufsz )
{
char path [ 64 ] ;
FILE * fp ;
snprintf ( path , sizeof ( path ) , " /proc/%llu/cmdline " ,
( unsigned long long ) pid ) ;
if ( ( fp = fopen ( path , " r " ) ) = = NULL ) {
return NULL ;
}
fgets ( buf , bufsz , fp ) ;
fclose ( fp ) ;
return buf ;
}
static void print_stack_trace ( pid_t pid , int * count )
{
void * pinfo = NULL ;
unw_addr_space_t aspace = NULL ;
unw_cursor_t cursor ;
unw_word_t ip , sp ;
char nbuf [ 256 ] ;
unw_word_t off ;
int ret ;
if ( ptrace ( PTRACE_ATTACH , pid , NULL , NULL ) < 0 ) {
fprintf ( stderr ,
" Failed to attach to process %llu: %s \n " ,
( unsigned long long ) pid , strerror ( errno ) ) ;
return ;
}
/* Wait until the attach is complete. */
waitpid ( pid , NULL , 0 ) ;
if ( ( ( pinfo = _UPT_create ( pid ) ) = = NULL ) | |
( ( aspace = unw_create_addr_space ( & _UPT_accessors , 0 ) ) = = NULL ) ) {
/* Probably out of memory. */
fprintf ( stderr ,
" Unable to initialize stack unwind for process %llu \n " ,
( unsigned long long ) pid ) ;
goto cleanup ;
}
if ( ( ret = unw_init_remote ( & cursor , aspace , pinfo ) ) ) {
fprintf ( stderr ,
" Unable to unwind stack for process %llu: %s \n " ,
( unsigned long long ) pid , unw_strerror ( ret ) ) ;
goto cleanup ;
}
if ( * count > 0 ) {
printf ( " \n " ) ;
}
if ( procname ( pid , nbuf , sizeof ( nbuf ) ) ) {
printf ( " Stack trace for process %llu (%s): \n " ,
( unsigned long long ) pid , nbuf ) ;
} else {
printf ( " Stack trace for process %llu: \n " ,
( unsigned long long ) pid ) ;
}
while ( unw_step ( & cursor ) > 0 ) {
ip = sp = off = 0 ;
unw_get_reg ( & cursor , UNW_REG_IP , & ip ) ;
unw_get_reg ( & cursor , UNW_REG_SP , & sp ) ;
ret = unw_get_proc_name ( & cursor , nbuf , sizeof ( nbuf ) , & off ) ;
if ( ret ! = 0 & & ret ! = - UNW_ENOMEM ) {
snprintf ( nbuf , sizeof ( nbuf ) , " <unknown symbol> " ) ;
}
printf ( " %s + %#llx [ip=%#llx] [sp=%#llx] \n " ,
nbuf , ( long long ) off , ( long long ) ip ,
( long long ) sp ) ;
}
( * count ) + + ;
cleanup :
if ( aspace ) {
unw_destroy_addr_space ( aspace ) ;
}
if ( pinfo ) {
_UPT_destroy ( pinfo ) ;
}
ptrace ( PTRACE_DETACH , pid , NULL , NULL ) ;
}
2017-10-26 18:18:36 +03:00
static int stack_trace_server ( pid_t pid , void * priv )
2006-05-04 04:35:05 +04:00
{
2017-10-26 18:18:36 +03:00
print_stack_trace ( pid , ( int * ) priv ) ;
2006-05-04 04:35:05 +04:00
return 0 ;
}
2012-01-16 19:08:48 +04:00
static bool do_daemon_stack_trace ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2012-01-16 19:08:48 +04:00
const int argc , const char * * argv )
2006-05-04 04:35:05 +04:00
{
pid_t dest ;
int count = 0 ;
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> stacktrace \n " ) ;
return False ;
}
dest = procid_to_pid ( & pid ) ;
if ( dest ! = 0 ) {
/* It would be nice to be able to make sure that this PID is
* the PID of a smbd / winbind / nmbd process , not some random PID
* the user liked the look of . It doesn ' t seem like it ' s worth
* the effort at the moment , however .
*/
print_stack_trace ( dest , & count ) ;
} else {
2017-10-26 18:18:36 +03:00
messaging_dgm_forall ( stack_trace_server , & count ) ;
2006-05-04 04:35:05 +04:00
}
return True ;
}
# else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
2012-01-16 19:08:48 +04:00
static bool do_daemon_stack_trace ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2012-01-16 19:08:48 +04:00
const int argc , const char * * argv )
2006-05-04 04:35:05 +04:00
{
fprintf ( stderr ,
" Daemon stack tracing is not supported on this platform \n " ) ;
return False ;
}
# endif /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
/* Inject a fault (fatal signal) into a running smbd */
2006-04-04 04:27:50 +04:00
2012-01-16 19:08:48 +04:00
static bool do_inject_fault ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2012-01-16 19:08:48 +04:00
const int argc , const char * * argv )
2006-04-04 04:27:50 +04:00
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> inject "
" <bus|hup|term|internal|segv> \n " ) ;
return False ;
}
2018-12-11 01:04:25 +03:00
# if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
2006-04-04 05:07:28 +04:00
fprintf ( stderr , " Fault injection is only available in "
2018-12-11 01:04:25 +03:00
" developer and self test builds \n " ) ;
2006-04-04 04:27:50 +04:00
return False ;
2018-12-11 01:04:25 +03:00
# else /* DEVELOPER || ENABLE_SELFTEST */
2006-04-04 04:27:50 +04:00
{
int sig = 0 ;
if ( strcmp ( argv [ 1 ] , " bus " ) = = 0 ) {
sig = SIGBUS ;
} else if ( strcmp ( argv [ 1 ] , " hup " ) = = 0 ) {
sig = SIGHUP ;
} else if ( strcmp ( argv [ 1 ] , " term " ) = = 0 ) {
sig = SIGTERM ;
} else if ( strcmp ( argv [ 1 ] , " segv " ) = = 0 ) {
sig = SIGSEGV ;
} else if ( strcmp ( argv [ 1 ] , " internal " ) = = 0 ) {
/* Force an internal error, ie. an unclean exit. */
sig = - 1 ;
} else {
fprintf ( stderr , " Unknown signal name '%s' \n " , argv [ 1 ] ) ;
return False ;
}
2007-05-15 18:39:18 +04:00
return send_message ( msg_ctx , pid , MSG_SMB_INJECT_FAULT ,
2007-05-22 02:17:13 +04:00
& sig , sizeof ( int ) ) ;
2006-04-04 04:27:50 +04:00
}
2018-12-11 01:04:25 +03:00
# endif /* DEVELOPER || ENABLE_SELFTEST */
2006-04-04 04:27:50 +04:00
}
2018-12-03 23:31:22 +03:00
static bool do_sleep ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
2019-05-29 09:10:55 +03:00
# if defined(DEVELOPER) || defined(ENABLE_SELFTEST)
2018-12-03 23:31:22 +03:00
unsigned int seconds ;
long input ;
const long MAX_SLEEP = 60 * 60 ; /* One hour maximum sleep */
2019-05-20 17:07:08 +03:00
# endif
2018-12-03 23:31:22 +03:00
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> sleep seconds \n " ) ;
return False ;
}
# if !defined(DEVELOPER) && !defined(ENABLE_SELFTEST)
fprintf ( stderr , " Sleep is only available in "
" developer and self test builds \n " ) ;
return False ;
# else /* DEVELOPER || ENABLE_SELFTEST */
input = atol ( argv [ 1 ] ) ;
if ( input < 1 | | input > MAX_SLEEP ) {
fprintf ( stderr ,
" Invalid duration for sleep '%s' \n "
" It should be at least 1 second and no more than %ld \n " ,
argv [ 1 ] ,
MAX_SLEEP ) ;
return False ;
}
seconds = input ;
return send_message ( msg_ctx , pid ,
MSG_SMB_SLEEP ,
& seconds ,
sizeof ( unsigned int ) ) ;
# endif /* DEVELOPER || ENABLE_SELFTEST */
}
2003-04-14 07:59:25 +04:00
/* Force a browser election */
2012-01-16 19:08:48 +04:00
static bool do_election ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> force-election \n " ) ;
return False ;
2001-12-21 07:28:03 +03:00
}
2003-04-14 07:59:25 +04:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_FORCE_ELECTION , NULL , 0 ) ;
2001-12-21 07:28:03 +03:00
}
2000-10-07 03:01:47 +04:00
2003-04-14 07:59:25 +04:00
/* Ping a samba daemon process */
2000-09-13 11:07:17 +04:00
2007-05-16 17:02:53 +04:00
static void pong_cb ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
2000-09-13 11:07:17 +04:00
{
2014-11-04 15:59:25 +03:00
struct server_id_buf src_string ;
printf ( " PONG from pid %s \n " , server_id_str_buf ( pid , & src_string ) ) ;
2003-04-14 07:59:25 +04:00
num_replies + + ;
2000-10-07 03:01:47 +04:00
}
2012-01-16 19:08:48 +04:00
static bool do_ping ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
2002-12-20 23:21:31 +03:00
{
2003-04-14 07:59:25 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> ping \n " ) ;
return False ;
}
/* Send a message and register our interest in a reply */
2007-05-22 02:17:13 +04:00
if ( ! send_message ( msg_ctx , pid , MSG_PING , NULL , 0 ) )
2003-04-14 07:59:25 +04:00
return False ;
2007-05-16 17:02:53 +04:00
messaging_register ( msg_ctx , NULL , MSG_PONG , pong_cb ) ;
2003-04-14 07:59:25 +04:00
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2003-04-14 07:59:25 +04:00
/* No replies were received within the timeout period */
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2007-05-16 17:02:53 +04:00
messaging_deregister ( msg_ctx , MSG_PONG , NULL ) ;
2003-04-14 07:59:25 +04:00
return num_replies ;
2002-12-20 23:21:31 +03:00
}
2003-04-14 07:59:25 +04:00
/* Set profiling options */
2012-01-16 19:08:48 +04:00
static bool do_profile ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2000-10-07 03:01:47 +04:00
{
2003-04-14 07:59:25 +04:00
int v ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> profile "
" <off|count|on|flush> \n " ) ;
return False ;
}
if ( strcmp ( argv [ 1 ] , " off " ) = = 0 ) {
v = 0 ;
} else if ( strcmp ( argv [ 1 ] , " count " ) = = 0 ) {
v = 1 ;
} else if ( strcmp ( argv [ 1 ] , " on " ) = = 0 ) {
v = 2 ;
} else if ( strcmp ( argv [ 1 ] , " flush " ) = = 0 ) {
v = 3 ;
} else {
fprintf ( stderr , " Unknown profile command '%s' \n " , argv [ 1 ] ) ;
return False ;
}
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_PROFILE , & v , sizeof ( int ) ) ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Return the profiling level */
2007-05-15 18:39:18 +04:00
static void profilelevel_cb ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
2000-11-11 03:33:33 +03:00
{
2003-04-14 07:59:25 +04:00
int level ;
const char * s ;
2000-11-11 03:33:33 +03:00
2003-04-14 07:59:25 +04:00
num_replies + + ;
2007-05-15 18:39:18 +04:00
if ( data - > length ! = sizeof ( int ) ) {
2003-11-07 01:11:08 +03:00
fprintf ( stderr , " invalid message length %ld returned \n " ,
2007-05-15 18:39:18 +04:00
( unsigned long ) data - > length ) ;
2003-04-14 07:59:25 +04:00
return ;
}
2007-05-15 18:39:18 +04:00
memcpy ( & level , data - > data , sizeof ( int ) ) ;
2003-04-14 07:59:25 +04:00
switch ( level ) {
case 0 :
s = " not enabled " ;
break ;
case 1 :
2000-11-11 03:33:33 +03:00
s = " off " ;
break ;
2003-04-14 07:59:25 +04:00
case 3 :
2000-11-11 03:33:33 +03:00
s = " count only " ;
break ;
2003-04-14 07:59:25 +04:00
case 7 :
2000-11-11 03:33:33 +03:00
s = " count and time " ;
break ;
2003-04-14 07:59:25 +04:00
default :
s = " BOGUS " ;
break ;
2000-11-11 03:33:33 +03:00
}
2010-07-19 23:00:31 +04:00
2005-09-30 21:13:37 +04:00
printf ( " Profiling %s on pid %u \n " , s , ( unsigned int ) procid_to_pid ( & pid ) ) ;
2000-11-11 03:33:33 +03:00
}
2007-05-15 18:39:18 +04:00
static void profilelevel_rqst ( struct messaging_context * msg_ctx ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
2001-12-21 07:28:03 +03:00
{
2003-04-14 07:59:25 +04:00
int v = 0 ;
2001-12-21 07:28:03 +03:00
2003-04-14 07:59:25 +04:00
/* Send back a dummy reply */
2007-05-22 02:17:13 +04:00
send_message ( msg_ctx , pid , MSG_PROFILELEVEL , & v , sizeof ( int ) ) ;
2003-04-14 07:59:25 +04:00
}
2001-12-21 07:28:03 +03:00
2012-01-16 19:08:48 +04:00
static bool do_profilelevel ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2000-09-13 11:07:17 +04:00
{
2003-04-14 07:59:25 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> profilelevel \n " ) ;
return False ;
}
2001-05-15 05:28:34 +04:00
2003-04-14 07:59:25 +04:00
/* Send a message and register our interest in a reply */
2007-05-22 02:17:13 +04:00
if ( ! send_message ( msg_ctx , pid , MSG_REQ_PROFILELEVEL , NULL , 0 ) )
2003-04-14 07:59:25 +04:00
return False ;
2007-05-15 18:39:18 +04:00
messaging_register ( msg_ctx , NULL , MSG_PROFILELEVEL , profilelevel_cb ) ;
messaging_register ( msg_ctx , NULL , MSG_REQ_PROFILELEVEL ,
profilelevel_rqst ) ;
2003-04-14 07:59:25 +04:00
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2000-09-13 11:07:17 +04:00
2003-04-14 07:59:25 +04:00
/* No replies were received within the timeout period */
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2007-05-16 17:02:53 +04:00
messaging_deregister ( msg_ctx , MSG_PROFILE , NULL ) ;
2003-04-14 07:59:25 +04:00
return num_replies ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Display debug level settings */
2012-01-16 19:08:48 +04:00
static bool do_debuglevel ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2000-09-13 11:07:17 +04:00
{
2003-04-14 07:59:25 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> debuglevel \n " ) ;
return False ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Send a message and register our interest in a reply */
2000-09-13 11:07:17 +04:00
2007-05-22 02:17:13 +04:00
if ( ! send_message ( msg_ctx , pid , MSG_REQ_DEBUGLEVEL , NULL , 0 ) )
2003-04-14 07:59:25 +04:00
return False ;
2002-01-09 11:27:15 +03:00
2007-05-16 17:02:53 +04:00
messaging_register ( msg_ctx , NULL , MSG_DEBUGLEVEL , print_pid_string_cb ) ;
2002-08-17 18:45:04 +04:00
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2002-08-17 18:45:04 +04:00
2003-04-14 07:59:25 +04:00
/* No replies were received within the timeout period */
2002-08-17 18:45:04 +04:00
2003-04-14 07:59:25 +04:00
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2002-08-17 18:45:04 +04:00
2007-05-16 17:02:53 +04:00
messaging_deregister ( msg_ctx , MSG_DEBUGLEVEL , NULL ) ;
2002-08-17 18:45:04 +04:00
2003-04-14 07:59:25 +04:00
return num_replies ;
2002-08-17 18:45:04 +04:00
}
2002-01-09 11:27:15 +03:00
2003-04-14 07:59:25 +04:00
/* Send a print notify message */
2012-01-16 19:08:48 +04:00
static bool do_printnotify ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2000-09-13 11:07:17 +04:00
{
2003-06-28 00:55:48 +04:00
const char * cmd ;
2003-04-14 07:59:25 +04:00
/* Check for subcommand */
if ( argc = = 1 ) {
fprintf ( stderr , " Must specify subcommand: \n " ) ;
fprintf ( stderr , " \t queuepause <printername> \n " ) ;
fprintf ( stderr , " \t queueresume <printername> \n " ) ;
fprintf ( stderr , " \t jobpause <printername> <unix jobid> \n " ) ;
fprintf ( stderr , " \t jobresume <printername> <unix jobid> \n " ) ;
fprintf ( stderr , " \t jobdelete <printername> <unix jobid> \n " ) ;
fprintf ( stderr , " \t printer <printername> <comment|port| "
" driver> <value> \n " ) ;
2010-07-19 23:00:31 +04:00
2003-04-14 07:59:25 +04:00
return False ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
cmd = argv [ 1 ] ;
2001-06-01 16:04:44 +04:00
2003-04-14 07:59:25 +04:00
if ( strcmp ( cmd , " queuepause " ) = = 0 ) {
2001-02-12 19:18:02 +03:00
2003-04-14 07:59:25 +04:00
if ( argc ! = 3 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" queuepause <printername> \n " ) ;
return False ;
2002-07-15 14:35:28 +04:00
}
2010-07-19 23:00:31 +04:00
2012-01-16 19:14:35 +04:00
notify_printer_status_byname ( ev_ctx , msg_ctx , argv [ 2 ] ,
2010-08-08 18:16:37 +04:00
PRINTER_STATUS_PAUSED ) ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
goto send ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
} else if ( strcmp ( cmd , " queueresume " ) = = 0 ) {
2000-09-13 11:07:17 +04:00
2003-04-14 07:59:25 +04:00
if ( argc ! = 3 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" queuereume <printername> \n " ) ;
return False ;
2000-10-07 03:01:47 +04:00
}
2010-07-19 23:00:31 +04:00
2012-01-16 19:14:35 +04:00
notify_printer_status_byname ( ev_ctx , msg_ctx , argv [ 2 ] ,
2010-08-08 18:16:37 +04:00
PRINTER_STATUS_OK ) ;
2000-10-07 03:01:47 +04:00
2003-04-14 07:59:25 +04:00
goto send ;
2000-09-13 11:07:17 +04:00
2003-04-14 07:59:25 +04:00
} else if ( strcmp ( cmd , " jobpause " ) = = 0 ) {
int jobid ;
2000-11-11 03:33:33 +03:00
2003-04-14 07:59:25 +04:00
if ( argc ! = 4 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" jobpause <printername> <unix-jobid> \n " ) ;
return False ;
2002-12-20 23:21:31 +03:00
}
2003-04-14 07:59:25 +04:00
jobid = atoi ( argv [ 3 ] ) ;
notify_job_status_byname (
2012-01-16 19:14:35 +04:00
ev_ctx , msg_ctx ,
2010-08-08 18:16:37 +04:00
argv [ 2 ] , jobid , JOB_STATUS_PAUSED ,
2003-04-14 07:59:25 +04:00
SPOOLSS_NOTIFY_MSG_UNIX_JOBID ) ;
goto send ;
} else if ( strcmp ( cmd , " jobresume " ) = = 0 ) {
int jobid ;
if ( argc ! = 4 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" jobpause <printername> <unix-jobid> \n " ) ;
return False ;
2000-10-07 03:01:47 +04:00
}
2003-04-14 07:59:25 +04:00
jobid = atoi ( argv [ 3 ] ) ;
notify_job_status_byname (
2012-01-16 19:14:35 +04:00
ev_ctx , msg_ctx ,
2003-04-14 07:59:25 +04:00
argv [ 2 ] , jobid , JOB_STATUS_QUEUED ,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID ) ;
goto send ;
} else if ( strcmp ( cmd , " jobdelete " ) = = 0 ) {
int jobid ;
if ( argc ! = 4 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" jobpause <printername> <unix-jobid> \n " ) ;
return False ;
2000-10-12 04:29:01 +04:00
}
2000-10-07 03:01:47 +04:00
2003-04-14 07:59:25 +04:00
jobid = atoi ( argv [ 3 ] ) ;
notify_job_status_byname (
2012-01-16 19:14:35 +04:00
ev_ctx , msg_ctx ,
2003-04-14 07:59:25 +04:00
argv [ 2 ] , jobid , JOB_STATUS_DELETING ,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID ) ;
2010-07-19 23:00:31 +04:00
2003-04-14 07:59:25 +04:00
notify_job_status_byname (
2012-01-16 19:14:35 +04:00
ev_ctx , msg_ctx ,
2003-04-14 07:59:25 +04:00
argv [ 2 ] , jobid , JOB_STATUS_DELETING |
JOB_STATUS_DELETED ,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID ) ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
goto send ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
} else if ( strcmp ( cmd , " printer " ) = = 0 ) {
2015-04-27 02:02:55 +03:00
uint32_t attribute ;
2010-07-19 23:00:31 +04:00
2003-04-14 07:59:25 +04:00
if ( argc ! = 5 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> printnotify "
" printer <printername> <comment|port|driver> "
" <value> \n " ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
if ( strcmp ( argv [ 3 ] , " comment " ) = = 0 ) {
2009-03-18 19:45:30 +03:00
attribute = PRINTER_NOTIFY_FIELD_COMMENT ;
2003-04-14 07:59:25 +04:00
} else if ( strcmp ( argv [ 3 ] , " port " ) = = 0 ) {
2009-03-18 19:45:30 +03:00
attribute = PRINTER_NOTIFY_FIELD_PORT_NAME ;
2003-04-14 07:59:25 +04:00
} else if ( strcmp ( argv [ 3 ] , " driver " ) = = 0 ) {
2009-03-18 19:45:30 +03:00
attribute = PRINTER_NOTIFY_FIELD_DRIVER_NAME ;
2003-04-14 07:59:25 +04:00
} else {
fprintf ( stderr , " Invalid printer command '%s' \n " ,
argv [ 3 ] ) ;
2002-07-15 14:35:28 +04:00
return False ;
2000-11-11 01:07:57 +03:00
}
2002-02-26 06:12:09 +03:00
2012-01-16 19:14:35 +04:00
notify_printer_byname ( ev_ctx , msg_ctx , argv [ 2 ] , attribute ,
2011-05-06 03:19:49 +04:00
discard_const_p ( char , argv [ 4 ] ) ) ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
goto send ;
}
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " Invalid subcommand '%s' \n " , cmd ) ;
return False ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
send :
2007-05-15 00:31:28 +04:00
print_notify_send_messages ( msg_ctx , 0 ) ;
2003-04-14 07:59:25 +04:00
return True ;
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* Close a share */
2002-07-15 14:35:28 +04:00
2012-01-16 19:08:48 +04:00
static bool do_closeshare ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> close-share "
" <sharename> \n " ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_SMB_FORCE_TDIS , argv [ 1 ] ,
strlen ( argv [ 1 ] ) + 1 ) ;
2003-04-14 07:59:25 +04:00
}
2002-07-15 14:35:28 +04:00
2020-01-13 17:19:58 +03:00
/*
* Close a share if access denied by now
* */
static bool do_close_denied_share (
struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> close-denied-share "
" <sharename> \n " ) ;
return False ;
}
return send_message (
msg_ctx ,
pid ,
MSG_SMB_FORCE_TDIS_DENIED ,
argv [ 1 ] ,
strlen ( argv [ 1 ] ) + 1 ) ;
}
2013-03-15 18:09:18 +04:00
/* Kill a client by IP address */
static bool do_kill_client_by_ip ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> kill-client-ip "
" <IP address> \n " ) ;
return false ;
}
if ( ! is_ipaddress_v4 ( argv [ 1 ] ) & & ! is_ipaddress_v6 ( argv [ 1 ] ) ) {
fprintf ( stderr , " %s is not a valid IP address! \n " , argv [ 1 ] ) ;
return false ;
}
return send_message ( msg_ctx , pid , MSG_SMB_KILL_CLIENT_IP ,
argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 ) ;
}
2010-09-29 14:17:05 +04:00
/* Tell winbindd an IP got dropped */
2012-01-16 19:08:48 +04:00
static bool do_ip_dropped ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2010-09-29 14:17:05 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> ip-dropped "
" <ip-address> \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_WINBIND_IP_DROPPED , argv [ 1 ] ,
strlen ( argv [ 1 ] ) + 1 ) ;
}
2003-04-14 07:59:25 +04:00
/* Display talloc pool usage */
2002-07-15 14:35:28 +04:00
2012-01-16 19:08:48 +04:00
static bool do_poolusage ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2019-08-30 16:08:40 +03:00
const struct server_id dst ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
2019-08-30 16:08:40 +03:00
pid_t pid = procid_to_pid ( & dst ) ;
int stdout_fd = 1 ;
2003-04-14 07:59:25 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> pool-usage \n " ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2019-08-30 16:08:40 +03:00
if ( pid = = 0 ) {
fprintf ( stderr , " Can only send to a specific PID \n " ) ;
return false ;
}
2002-07-15 14:35:28 +04:00
2019-08-30 16:08:40 +03:00
messaging_send_iov (
msg_ctx ,
dst ,
MSG_REQ_POOL_USAGE ,
NULL ,
0 ,
& stdout_fd ,
1 ) ;
2002-07-15 14:35:28 +04:00
2019-08-30 16:08:40 +03:00
return true ;
2003-04-14 07:59:25 +04:00
}
2002-07-15 14:35:28 +04:00
2017-01-08 18:47:30 +03:00
/* Fetch and print the ringbuf log */
static void print_ringbuf_log_cb ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
{
printf ( " %s " , ( const char * ) data - > data ) ;
num_replies + + ;
}
static bool do_ringbuflog ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> ringbuf-log \n " ) ;
return false ;
}
messaging_register ( msg_ctx , NULL , MSG_RINGBUF_LOG ,
print_ringbuf_log_cb ) ;
/* Send a message and register our interest in a reply */
if ( ! send_message ( msg_ctx , pid , MSG_REQ_RINGBUF_LOG , NULL , 0 ) ) {
return false ;
}
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
/* No replies were received within the timeout period */
if ( num_replies = = 0 ) {
printf ( " No replies received \n " ) ;
}
messaging_deregister ( msg_ctx , MSG_RINGBUF_LOG , NULL ) ;
return num_replies ! = 0 ;
}
2003-04-14 07:59:25 +04:00
/* Perform a dmalloc mark */
2002-07-15 14:35:28 +04:00
2012-01-16 19:08:48 +04:00
static bool do_dmalloc_mark ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> dmalloc-mark \n " ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_REQ_DMALLOC_MARK , NULL , 0 ) ;
2003-04-14 07:59:25 +04:00
}
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
/* Perform a dmalloc changed */
2000-11-11 01:07:57 +03:00
2012-01-16 19:08:48 +04:00
static bool do_dmalloc_changed ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> "
" dmalloc-log-changed \n " ) ;
return False ;
}
2001-06-20 07:05:09 +04:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_REQ_DMALLOC_LOG_CHANGED ,
NULL , 0 ) ;
2003-04-14 07:59:25 +04:00
}
2001-08-28 10:38:11 +04:00
2013-05-06 13:23:03 +04:00
static void print_uint32_cb ( struct messaging_context * msg , void * private_data ,
uint32_t msg_type , struct server_id pid ,
DATA_BLOB * data )
{
uint32_t num_children ;
if ( data - > length ! = sizeof ( uint32_t ) ) {
printf ( " Invalid response: %d bytes long \n " ,
( int ) data - > length ) ;
goto done ;
}
num_children = IVAL ( data - > data , 0 ) ;
printf ( " %u children \n " , ( unsigned ) num_children ) ;
done :
num_replies + + ;
}
static bool do_num_children ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> num-children \n " ) ;
return False ;
}
messaging_register ( msg_ctx , NULL , MSG_SMB_NUM_CHILDREN ,
print_uint32_cb ) ;
/* Send a message and register our interest in a reply */
if ( ! send_message ( msg_ctx , pid , MSG_SMB_TELL_NUM_CHILDREN , NULL , 0 ) )
return false ;
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
/* No replies were received within the timeout period */
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2014-01-15 02:45:06 +04:00
messaging_deregister ( msg_ctx , MSG_SMB_NUM_CHILDREN , NULL ) ;
2013-05-06 13:23:03 +04:00
return num_replies ;
}
2014-07-17 15:01:00 +04:00
static bool do_msg_cleanup ( struct tevent_context * ev_ctx ,
2014-04-11 00:09:04 +04:00
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
2014-06-04 18:47:05 +04:00
int ret ;
2014-04-11 00:09:04 +04:00
2014-07-17 15:01:00 +04:00
ret = messaging_cleanup ( msg_ctx , pid . pid ) ;
2014-04-11 00:09:04 +04:00
printf ( " cleanup(%u) returned %s \n " , ( unsigned ) pid . pid ,
2014-06-04 18:47:05 +04:00
ret ? strerror ( ret ) : " ok " ) ;
2014-04-11 00:09:04 +04:00
2014-06-04 18:47:05 +04:00
return ( ret = = 0 ) ;
2014-04-11 00:09:04 +04:00
}
2003-04-14 07:59:25 +04:00
/* Shutdown a server process */
2001-08-28 10:38:11 +04:00
2012-01-16 19:08:48 +04:00
static bool do_shutdown ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> shutdown \n " ) ;
return False ;
}
2001-08-28 10:38:11 +04:00
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_SHUTDOWN , NULL , 0 ) ;
2003-04-14 07:59:25 +04:00
}
2001-08-28 10:38:11 +04:00
2003-04-14 07:59:25 +04:00
/* Notify a driver upgrade */
2001-08-28 10:38:11 +04:00
2012-01-16 19:08:48 +04:00
static bool do_drvupgrade ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> drvupgrade "
" <driver-name> \n " ) ;
return False ;
}
2001-08-28 10:38:11 +04:00
2013-05-23 01:03:13 +04:00
return send_message ( msg_ctx , pid , MSG_PRINTER_DRVUPGRADE , argv [ 1 ] ,
2007-05-22 02:17:13 +04:00
strlen ( argv [ 1 ] ) + 1 ) ;
2003-04-14 07:59:25 +04:00
}
2001-08-28 10:38:11 +04:00
2012-01-16 19:08:48 +04:00
static bool do_winbind_online ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2012-01-16 19:08:48 +04:00
const int argc , const char * * argv )
2006-02-04 01:19:41 +03:00
{
TDB_CONTEXT * tdb ;
2014-11-02 22:21:34 +03:00
char * db_path ;
2006-02-04 01:19:41 +03:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd online \n " ) ;
return False ;
}
2018-08-16 11:51:44 +03:00
db_path = state_path ( talloc_tos ( ) , " winbindd_cache.tdb " ) ;
2014-11-02 22:21:34 +03:00
if ( db_path = = NULL ) {
return false ;
}
2006-02-04 01:19:41 +03:00
/* Remove the entry in the winbindd_cache tdb to tell a later
starting winbindd that we ' re online . */
2014-11-02 22:21:34 +03:00
tdb = tdb_open_log ( db_path , 0 , TDB_DEFAULT , O_RDWR , 0600 ) ;
2006-02-04 01:19:41 +03:00
if ( ! tdb ) {
fprintf ( stderr , " Cannot open the tdb %s for writing. \n " ,
2014-11-02 22:21:34 +03:00
db_path ) ;
TALLOC_FREE ( db_path ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
2014-11-02 22:21:34 +03:00
TALLOC_FREE ( db_path ) ;
2006-02-04 01:19:41 +03:00
tdb_delete_bystring ( tdb , " WINBINDD_OFFLINE " ) ;
tdb_close ( tdb ) ;
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_WINBIND_ONLINE , NULL , 0 ) ;
2006-02-04 01:19:41 +03:00
}
2012-01-16 19:08:48 +04:00
static bool do_winbind_offline ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2012-01-16 19:08:48 +04:00
const int argc , const char * * argv )
2006-02-04 01:19:41 +03:00
{
TDB_CONTEXT * tdb ;
2007-10-19 04:40:25 +04:00
bool ret = False ;
2006-02-04 01:19:41 +03:00
int retry = 0 ;
2014-11-02 22:21:34 +03:00
char * db_path ;
2006-02-04 01:19:41 +03:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd offline \n " ) ;
return False ;
}
2018-08-16 11:51:44 +03:00
db_path = state_path ( talloc_tos ( ) , " winbindd_cache.tdb " ) ;
2014-11-02 22:21:34 +03:00
if ( db_path = = NULL ) {
return false ;
}
2006-02-04 01:19:41 +03:00
/* Create an entry in the winbindd_cache tdb to tell a later
starting winbindd that we ' re offline . We may actually create
it here . . . */
2014-11-02 22:21:34 +03:00
tdb = tdb_open_log ( db_path ,
2006-02-04 01:19:41 +03:00
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE ,
2010-09-27 16:46:07 +04:00
TDB_DEFAULT | TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */ ,
O_RDWR | O_CREAT , 0600 ) ;
2006-02-04 01:19:41 +03:00
if ( ! tdb ) {
fprintf ( stderr , " Cannot open the tdb %s for writing. \n " ,
2014-11-02 22:21:34 +03:00
db_path ) ;
TALLOC_FREE ( db_path ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
2014-11-02 22:21:34 +03:00
TALLOC_FREE ( db_path ) ;
2006-02-04 01:19:41 +03:00
/* There's a potential race condition that if a child
winbindd detects a domain is online at the same time
we ' re trying to tell it to go offline that it might
delete the record we add between us adding it and
sending the message . Minimize this by retrying up to
5 times . */
for ( retry = 0 ; retry < 5 ; retry + + ) {
2015-04-27 02:02:55 +03:00
uint8_t buf [ 4 ] ;
2015-03-07 14:39:05 +03:00
TDB_DATA d = { . dptr = buf , . dsize = sizeof ( buf ) } ;
2006-10-09 19:11:37 +04:00
SIVAL ( buf , 0 , time ( NULL ) ) ;
2006-02-04 01:19:41 +03:00
tdb_store_bystring ( tdb , " WINBINDD_OFFLINE " , d , TDB_INSERT ) ;
2007-05-15 18:39:18 +04:00
ret = send_message ( msg_ctx , pid , MSG_WINBIND_OFFLINE ,
2007-05-22 02:17:13 +04:00
NULL , 0 ) ;
2006-02-04 01:19:41 +03:00
/* Check that the entry "WINBINDD_OFFLINE" still exists. */
d = tdb_fetch_bystring ( tdb , " WINBINDD_OFFLINE " ) ;
2018-09-26 15:47:20 +03:00
if ( d . dptr ! = NULL & & d . dsize = = 4 ) {
2006-10-09 19:11:37 +04:00
SAFE_FREE ( d . dptr ) ;
2006-02-04 01:19:41 +03:00
break ;
}
2018-09-26 15:47:20 +03:00
SAFE_FREE ( d . dptr ) ;
DEBUG ( 10 , ( " do_winbind_offline: offline state not set - retrying. \n " ) ) ;
2006-02-04 01:19:41 +03:00
}
tdb_close ( tdb ) ;
return ret ;
}
2012-01-16 19:08:48 +04:00
static bool do_winbind_onlinestatus ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-05-04 16:37:13 +04:00
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd onlinestatus \n " ) ;
return False ;
}
2007-05-16 17:02:53 +04:00
messaging_register ( msg_ctx , NULL , MSG_WINBIND_ONLINESTATUS ,
print_pid_string_cb ) ;
2006-05-04 16:37:13 +04:00
2018-02-13 16:05:15 +03:00
if ( ! send_message ( msg_ctx , pid , MSG_WINBIND_ONLINESTATUS , NULL , 0 ) ) {
2006-05-04 16:37:13 +04:00
return False ;
2018-02-13 16:05:15 +03:00
}
2006-05-04 16:37:13 +04:00
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2006-05-04 16:37:13 +04:00
/* No replies were received within the timeout period */
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2007-05-16 17:02:53 +04:00
messaging_deregister ( msg_ctx , MSG_WINBIND_ONLINESTATUS , NULL ) ;
2006-05-04 16:37:13 +04:00
return num_replies ;
}
2012-01-16 19:08:48 +04:00
static bool do_winbind_dump_domain_list ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2008-01-24 18:09:20 +03:00
const struct server_id pid ,
const int argc , const char * * argv )
{
const char * domain = NULL ;
int domain_len = 0 ;
if ( argc < 1 | | argc > 2 ) {
2010-09-30 17:17:09 +04:00
fprintf ( stderr , " Usage: smbcontrol <dest> dump-domain-list "
2008-01-24 18:09:20 +03:00
" <domain> \n " ) ;
return false ;
}
if ( argc = = 2 ) {
domain = argv [ 1 ] ;
domain_len = strlen ( argv [ 1 ] ) + 1 ;
}
messaging_register ( msg_ctx , NULL , MSG_WINBIND_DUMP_DOMAIN_LIST ,
print_pid_string_cb ) ;
if ( ! send_message ( msg_ctx , pid , MSG_WINBIND_DUMP_DOMAIN_LIST ,
2018-02-13 16:05:43 +03:00
domain , domain_len ) )
2008-01-24 18:09:20 +03:00
{
return false ;
}
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2008-01-24 18:09:20 +03:00
/* No replies were received within the timeout period */
if ( num_replies = = 0 ) {
printf ( " No replies received \n " ) ;
}
messaging_deregister ( msg_ctx , MSG_WINBIND_DUMP_DOMAIN_LIST , NULL ) ;
return num_replies ;
}
2018-02-28 18:08:44 +03:00
static bool do_msg_disconnect_dc ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> disconnect-dc \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_WINBIND_DISCONNECT_DC , NULL , 0 ) ;
}
2007-08-31 19:24:43 +04:00
static void winbind_validate_cache_cb ( struct messaging_context * msg ,
void * private_data ,
uint32_t msg_type ,
struct server_id pid ,
DATA_BLOB * data )
{
2014-11-04 15:59:25 +03:00
struct server_id_buf src_string ;
2007-08-31 19:24:43 +04:00
printf ( " Winbindd cache is %svalid. (answer from pid %s) \n " ,
2014-11-04 15:59:25 +03:00
( * ( data - > data ) = = 0 ? " " : " NOT " ) ,
server_id_str_buf ( pid , & src_string ) ) ;
2007-08-31 19:24:43 +04:00
num_replies + + ;
}
2012-01-16 19:08:48 +04:00
static bool do_winbind_validate_cache ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-08-31 19:24:43 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
{
2010-07-19 23:04:04 +04:00
struct server_id myid ;
myid = messaging_server_id ( msg_ctx ) ;
2007-08-31 19:24:43 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd validate-cache \n " ) ;
return False ;
}
messaging_register ( msg_ctx , NULL , MSG_WINBIND_VALIDATE_CACHE ,
winbind_validate_cache_cb ) ;
if ( ! send_message ( msg_ctx , pid , MSG_WINBIND_VALIDATE_CACHE , & myid ,
sizeof ( myid ) ) ) {
return False ;
}
2012-01-16 19:11:42 +04:00
wait_replies ( ev_ctx , msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2007-08-31 19:24:43 +04:00
if ( num_replies = = 0 ) {
printf ( " No replies received \n " ) ;
}
messaging_deregister ( msg_ctx , MSG_WINBIND_VALIDATE_CACHE , NULL ) ;
return num_replies ;
}
2006-05-04 16:37:13 +04:00
2012-01-16 19:08:48 +04:00
static bool do_reload_config ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2003-07-15 21:21:21 +04:00
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> reload-config \n " ) ;
return False ;
}
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_SMB_CONF_UPDATED , NULL , 0 ) ;
2003-07-15 21:21:21 +04:00
}
2012-01-10 19:59:38 +04:00
static bool do_reload_printers ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> reload-printers \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_PRINTER_PCAP , NULL , 0 ) ;
}
2005-06-09 02:10:34 +04:00
static void my_make_nmb_name ( struct nmb_name * n , const char * name , int type )
{
fstring unix_name ;
memset ( ( char * ) n , ' \0 ' , sizeof ( struct nmb_name ) ) ;
fstrcpy ( unix_name , name ) ;
2012-08-09 02:35:28 +04:00
( void ) strupper_m ( unix_name ) ;
2005-06-09 02:10:34 +04:00
push_ascii ( n - > name , unix_name , sizeof ( n - > name ) , STR_TERMINATE ) ;
n - > name_type = ( unsigned int ) type & 0xFF ;
2011-06-08 10:27:06 +04:00
push_ascii ( n - > scope , lp_netbios_scope ( ) , 64 , STR_TERMINATE ) ;
2005-06-09 02:10:34 +04:00
}
2012-01-16 19:08:48 +04:00
static bool do_nodestatus ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv )
2005-06-09 02:10:34 +04:00
{
struct packet_struct p ;
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol nmbd nodestatus <ip> \n " ) ;
return False ;
}
ZERO_STRUCT ( p ) ;
2008-10-23 22:41:15 +04:00
p . ip = interpret_addr2 ( argv [ 1 ] ) ;
2005-06-09 02:10:34 +04:00
p . port = 137 ;
p . packet_type = NMB_PACKET ;
p . packet . nmb . header . name_trn_id = 10 ;
p . packet . nmb . header . opcode = 0 ;
p . packet . nmb . header . response = False ;
p . packet . nmb . header . nm_flags . bcast = False ;
p . packet . nmb . header . nm_flags . recursion_available = False ;
p . packet . nmb . header . nm_flags . recursion_desired = False ;
p . packet . nmb . header . nm_flags . trunc = False ;
p . packet . nmb . header . nm_flags . authoritative = False ;
p . packet . nmb . header . rcode = 0 ;
p . packet . nmb . header . qdcount = 1 ;
p . packet . nmb . header . ancount = 0 ;
p . packet . nmb . header . nscount = 0 ;
p . packet . nmb . header . arcount = 0 ;
my_make_nmb_name ( & p . packet . nmb . question . question_name , " * " , 0x00 ) ;
p . packet . nmb . question . question_type = 0x21 ;
p . packet . nmb . question . question_class = 0x1 ;
2007-05-22 02:17:13 +04:00
return send_message ( msg_ctx , pid , MSG_SEND_PACKET , & p , sizeof ( p ) ) ;
2005-06-09 02:10:34 +04:00
}
2012-04-04 16:49:21 +04:00
static bool do_notify_cleanup ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol smbd notify-cleanup \n " ) ;
return false ;
}
return send_message ( msg_ctx , pid , MSG_SMB_NOTIFY_CLEANUP , NULL , 0 ) ;
}
2003-04-14 07:59:25 +04:00
/* A list of message type supported */
2001-08-28 10:38:11 +04:00
2003-04-14 07:59:25 +04:00
static const struct {
const char * name ; /* Option name */
2012-01-16 19:08:48 +04:00
bool ( * fn ) ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2005-09-30 21:13:37 +04:00
const int argc , const char * * argv ) ;
2003-04-14 07:59:25 +04:00
const char * help ; /* Short help text */
} msg_types [ ] = {
2019-01-11 16:22:15 +03:00
{
. name = " debug " ,
. fn = do_debug ,
. help = " Set debuglevel " ,
} ,
{
. name = " idmap " ,
. fn = do_idmap ,
. help = " Manipulate idmap cache " ,
} ,
{
. name = " force-election " ,
. fn = do_election ,
. help = " Force a browse election " ,
} ,
{
. name = " ping " ,
. fn = do_ping ,
. help = " Elicit a response " ,
} ,
{
. name = " profile " ,
. fn = do_profile ,
. help = " " ,
} ,
{
. name = " inject " ,
. fn = do_inject_fault ,
. help = " Inject a fatal signal into a running smbd " } ,
{
. name = " stacktrace " ,
. fn = do_daemon_stack_trace ,
. help = " Display a stack trace of a daemon " ,
} ,
{
. name = " profilelevel " ,
. fn = do_profilelevel ,
. help = " " ,
} ,
{
. name = " debuglevel " ,
. fn = do_debuglevel ,
. help = " Display current debuglevels " ,
} ,
{
. name = " printnotify " ,
. fn = do_printnotify ,
. help = " Send a print notify message " ,
} ,
{
. name = " close-share " ,
. fn = do_closeshare ,
. help = " Forcibly disconnect a share " ,
} ,
2020-01-13 17:19:58 +03:00
{
. name = " close-denied-share " ,
. fn = do_close_denied_share ,
. help = " Forcibly disconnect users from shares disallowed now " ,
} ,
2019-01-11 16:22:15 +03:00
{
. name = " kill-client-ip " ,
. fn = do_kill_client_by_ip ,
. help = " Forcibly disconnect a client with a specific IP address " ,
} ,
{
. name = " ip-dropped " ,
. fn = do_ip_dropped ,
. help = " Tell winbind that an IP got dropped " ,
} ,
{
. name = " pool-usage " ,
. fn = do_poolusage ,
. help = " Display talloc memory usage " ,
} ,
{
. name = " ringbuf-log " ,
. fn = do_ringbuflog ,
. help = " Display ringbuf log " ,
} ,
{
. name = " dmalloc-mark " ,
. fn = do_dmalloc_mark ,
. help = " " ,
} ,
{
. name = " dmalloc-log-changed " ,
. fn = do_dmalloc_changed ,
. help = " " ,
} ,
{
. name = " shutdown " ,
. fn = do_shutdown ,
. help = " Shut down daemon " ,
} ,
{
. name = " drvupgrade " ,
. fn = do_drvupgrade ,
. help = " Notify a printer driver has changed " ,
} ,
{
. name = " reload-config " ,
. fn = do_reload_config ,
. help = " Force smbd or winbindd to reload config file " } ,
{
. name = " reload-printers " ,
. fn = do_reload_printers ,
. help = " Force smbd to reload printers " } ,
{
. name = " nodestatus " ,
. fn = do_nodestatus ,
. help = " Ask nmbd to do a node status request " } ,
{
. name = " online " ,
. fn = do_winbind_online ,
. help = " Ask winbind to go into online state " } ,
{
. name = " offline " ,
. fn = do_winbind_offline ,
. help = " Ask winbind to go into offline state " } ,
{
. name = " onlinestatus " ,
. fn = do_winbind_onlinestatus ,
. help = " Request winbind online status " } ,
{
. name = " validate-cache " ,
. fn = do_winbind_validate_cache ,
. help = " Validate winbind's credential cache " ,
} ,
{
. name = " dump-domain-list " ,
. fn = do_winbind_dump_domain_list ,
. help = " Dump winbind domain list " } ,
{
. name = " disconnect-dc " ,
. fn = do_msg_disconnect_dc ,
} ,
{
. name = " notify-cleanup " ,
. fn = do_notify_cleanup ,
} ,
{
. name = " num-children " ,
. fn = do_num_children ,
. help = " Print number of smbd child processes " ,
} ,
{
. name = " msg-cleanup " ,
. fn = do_msg_cleanup ,
} ,
{
. name = " noop " ,
. fn = do_noop ,
. help = " Do nothing " ,
} ,
{
. name = " sleep " ,
. fn = do_sleep ,
. help = " Cause the target process to sleep " ,
} ,
{ . name = NULL , } ,
2003-04-14 07:59:25 +04:00
} ;
2001-08-28 10:38:11 +04:00
2003-04-14 07:59:25 +04:00
/* Display usage information */
2002-01-09 11:27:15 +03:00
2007-05-19 08:59:00 +04:00
static void usage ( poptContext pc )
2003-04-14 07:59:25 +04:00
{
int i ;
2002-03-29 16:49:48 +03:00
2007-05-19 08:59:00 +04:00
poptPrintHelp ( pc , stderr , 0 ) ;
2003-04-03 19:44:19 +04:00
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " \n " ) ;
2006-02-04 01:19:41 +03:00
fprintf ( stderr , " <destination> is one of \" nmbd \" , \" smbd \" , \" winbindd \" or a "
2003-04-14 07:59:25 +04:00
" process ID \n " ) ;
fprintf ( stderr , " \n " ) ;
fprintf ( stderr , " <message-type> is one of: \n " ) ;
2019-09-08 16:08:54 +03:00
for ( i = 0 ; msg_types [ i ] . name ; i + + ) {
const char * help = msg_types [ i ] . help ;
if ( help = = NULL ) {
help = " " ;
}
fprintf ( stderr , " \t %-30s%s \n " , msg_types [ i ] . name , help ) ;
}
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " \n " ) ;
exit ( 1 ) ;
}
/* Return the pid number for a string destination */
2010-07-19 23:04:04 +04:00
static struct server_id parse_dest ( struct messaging_context * msg ,
const char * dest )
2003-04-14 07:59:25 +04:00
{
2019-01-11 16:22:15 +03:00
struct server_id result = {
. pid = ( uint64_t ) - 1 ,
} ;
2003-04-14 07:59:25 +04:00
pid_t pid ;
2008-08-19 03:18:34 +04:00
/* Zero is a special return value for broadcast to all processes */
2003-04-14 07:59:25 +04:00
2008-08-19 03:18:34 +04:00
if ( strequal ( dest , " all " ) ) {
2007-07-24 13:32:05 +04:00
return interpret_pid ( MSG_BROADCAST_PID_STR ) ;
2005-09-30 21:13:37 +04:00
}
2003-04-14 07:59:25 +04:00
/* Try self - useful for testing */
2005-09-30 21:13:37 +04:00
if ( strequal ( dest , " self " ) ) {
2010-07-19 23:04:04 +04:00
return messaging_server_id ( msg ) ;
2005-09-30 21:13:37 +04:00
}
2003-04-14 07:59:25 +04:00
2006-02-04 01:19:41 +03:00
/* Fix winbind typo. */
if ( strequal ( dest , " winbind " ) ) {
dest = " winbindd " ;
}
2009-08-17 19:31:01 +04:00
/* Check for numeric pid number */
result = interpret_pid ( dest ) ;
2003-04-14 07:59:25 +04:00
2009-08-17 19:31:01 +04:00
/* Zero isn't valid if not "all". */
if ( result . pid & & procid_valid ( & result ) ) {
return result ;
2005-09-30 21:13:37 +04:00
}
2003-04-14 07:59:25 +04:00
/* Look up other destinations in pidfile directory */
2014-02-03 06:57:21 +04:00
if ( ( pid = pidfile_pid ( lp_pid_directory ( ) , dest ) ) ! = 0 ) {
2005-09-30 21:13:37 +04:00
return pid_to_procid ( pid ) ;
}
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " Can't find pid for destination '%s' \n " , dest ) ;
2005-09-30 21:13:37 +04:00
return result ;
2008-08-19 03:18:34 +04:00
}
2003-04-14 07:59:25 +04:00
/* Execute smbcontrol command */
2012-01-16 19:08:48 +04:00
static bool do_command ( struct tevent_context * ev_ctx ,
struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
int argc , const char * * argv )
2003-04-14 07:59:25 +04:00
{
2003-06-28 00:55:48 +04:00
const char * dest = argv [ 0 ] , * command = argv [ 1 ] ;
2007-05-07 13:35:35 +04:00
struct server_id pid ;
2003-04-14 07:59:25 +04:00
int i ;
/* Check destination */
2010-07-19 23:04:04 +04:00
pid = parse_dest ( msg_ctx , dest ) ;
2005-09-30 21:13:37 +04:00
if ( ! procid_valid ( & pid ) ) {
2003-04-14 07:59:25 +04:00
return False ;
2005-09-30 21:13:37 +04:00
}
2003-04-14 07:59:25 +04:00
/* Check command */
for ( i = 0 ; msg_types [ i ] . name ; i + + ) {
if ( strequal ( command , msg_types [ i ] . name ) )
2012-01-16 19:08:48 +04:00
return msg_types [ i ] . fn ( ev_ctx , msg_ctx , pid ,
2007-05-15 00:31:28 +04:00
argc - 1 , argv + 1 ) ;
2000-09-13 11:07:17 +04:00
}
2001-12-21 07:28:03 +03:00
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " smbcontrol: unknown command '%s' \n " , command ) ;
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
return False ;
2000-09-30 00:08:00 +04:00
}
2007-05-19 08:59:00 +04:00
static void smbcontrol_help ( poptContext pc ,
enum poptCallbackReason preason ,
struct poptOption * poption ,
const char * parg ,
void * pdata )
{
if ( poption - > shortName ! = ' ? ' ) {
poptPrintUsage ( pc , stdout , 0 ) ;
} else {
usage ( pc ) ;
}
exit ( 0 ) ;
}
struct poptOption help_options [ ] = {
{ NULL , ' \0 ' , POPT_ARG_CALLBACK , ( void * ) & smbcontrol_help , ' \0 ' ,
NULL , NULL } ,
{ " help " , ' ? ' , 0 , NULL , ' ? ' , " Show this help message " , NULL } ,
{ " usage " , ' \0 ' , 0 , NULL , ' u ' , " Display brief usage message " , NULL } ,
{ NULL }
} ;
2003-04-14 07:59:25 +04:00
/* Main program */
2003-06-28 00:55:48 +04:00
int main ( int argc , const char * * argv )
2000-09-30 00:08:00 +04:00
{
2003-04-14 07:59:25 +04:00
poptContext pc ;
2000-09-30 00:08:00 +04:00
int opt ;
2009-01-21 09:30:13 +03:00
struct tevent_context * evt_ctx ;
2007-05-15 00:31:28 +04:00
struct messaging_context * msg_ctx ;
2000-09-30 00:08:00 +04:00
2007-03-09 22:48:50 +03:00
static struct poptOption long_options [ ] = {
2007-05-19 08:59:00 +04:00
/* POPT_AUTOHELP */
{ NULL , ' \0 ' , POPT_ARG_INCLUDE_TABLE , help_options ,
0 , " Help options: " , NULL } ,
2003-04-14 07:59:25 +04:00
{ " timeout " , ' t ' , POPT_ARG_INT , & timeout , ' t ' ,
" Set timeout value in seconds " , " TIMEOUT " } ,
2007-03-09 22:48:50 +03:00
POPT_COMMON_SAMBA
2003-04-14 07:59:25 +04:00
POPT_TABLEEND
} ;
2007-08-31 14:06:37 +04:00
TALLOC_CTX * frame = talloc_stackframe ( ) ;
int ret = 0 ;
2002-01-08 00:32:22 +03:00
2015-03-21 22:00:06 +03:00
smb_init_locale ( ) ;
2006-01-09 01:00:01 +03:00
2010-10-29 07:19:32 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDOUT ) ;
2015-07-09 01:16:33 +03:00
lp_set_cmdline ( " log level " , " 0 " ) ;
2010-07-19 23:00:31 +04:00
2003-04-14 07:59:25 +04:00
/* Parse command line arguments using popt */
pc = poptGetContext (
2007-03-09 22:48:50 +03:00
" smbcontrol " , argc , ( const char * * ) argv , long_options , 0 ) ;
2003-04-14 07:59:25 +04:00
poptSetOtherOptionHelp ( pc , " [OPTION...] <destination> <message-type> "
" <parameters> " ) ;
if ( argc = = 1 )
2007-05-19 08:59:00 +04:00
usage ( pc ) ;
2000-09-30 00:08:00 +04:00
2003-04-14 07:59:25 +04:00
while ( ( opt = poptGetNextOpt ( pc ) ) ! = - 1 ) {
switch ( opt ) {
case ' t ' : /* --timeout */
2001-09-21 17:37:52 +04:00
break ;
2000-09-30 00:08:00 +04:00
default :
2003-04-14 07:59:25 +04:00
fprintf ( stderr , " Invalid option \n " ) ;
poptPrintHelp ( pc , stderr , 0 ) ;
break ;
2000-09-30 00:08:00 +04:00
}
}
2003-04-14 07:59:25 +04:00
/* We should now have the remaining command line arguments in
argv . The argc parameter should have been decremented to the
correct value in the above switch statement . */
2001-09-21 17:37:52 +04:00
2003-06-28 00:55:48 +04:00
argv = ( const char * * ) poptGetArgs ( pc ) ;
2007-03-09 22:48:50 +03:00
argc = 0 ;
2007-08-31 19:34:26 +04:00
if ( argv ! = NULL ) {
while ( argv [ argc ] ! = NULL ) {
argc + + ;
}
2007-03-09 22:48:50 +03:00
}
2000-09-30 00:08:00 +04:00
2007-08-31 19:34:26 +04:00
if ( argc < = 1 )
2007-05-19 08:59:00 +04:00
usage ( pc ) ;
2002-01-09 11:27:15 +03:00
2018-08-21 22:35:11 +03:00
msg_ctx = cmdline_messaging_context ( get_dyn_CONFIGFILE ( ) ) ;
if ( msg_ctx = = NULL ) {
fprintf ( stderr ,
" Could not init messaging context, not root? \n " ) ;
TALLOC_FREE ( frame ) ;
exit ( 1 ) ;
}
2018-08-21 21:06:16 +03:00
evt_ctx = global_event_context ( ) ;
2018-08-21 22:35:11 +03:00
2011-07-28 12:23:53 +04:00
lp_load_global ( get_dyn_CONFIGFILE ( ) ) ;
2000-09-30 00:08:00 +04:00
2003-04-14 07:59:25 +04:00
/* Need to invert sense of return code -- samba
* routines mostly return True = = 1 for success , but
* shell needs 0. */
2010-07-19 23:00:31 +04:00
2012-01-16 19:08:48 +04:00
ret = ! do_command ( evt_ctx , msg_ctx , argc , argv ) ;
2019-08-19 14:29:03 +03:00
poptFreeContext ( pc ) ;
2007-08-31 14:06:37 +04:00
TALLOC_FREE ( frame ) ;
return ret ;
2000-09-13 11:07:17 +04:00
}