2000-09-13 11:07:17 +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"
2010-08-05 12:49:53 +04:00
# include "popt_common.h"
2010-05-05 03:39:16 +04:00
# include "librpc/gen_ndr/messaging.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"
2000-09-13 11:07:17 +04:00
2006-05-04 04:35:05 +04:00
# if HAVE_LIBUNWIND_H
# include <libunwind.h>
# endif
# if HAVE_LIBUNWIND_PTRACE_H
# include <libunwind-ptrace.h>
# endif
# if HAVE_SYS_PTRACE_H
# 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
{
2007-10-19 04:40:25 +04:00
bool ret ;
2003-04-14 07:59:25 +04:00
int n_sent = 0 ;
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 ,
( uint8 * ) buf , len ) ) ;
2003-04-14 07:59:25 +04:00
2007-05-22 02:17:13 +04:00
ret = message_send_all ( msg_ctx , msg_type , buf , len , & n_sent ) ;
2003-04-14 07:59:25 +04:00
DEBUG ( 10 , ( " smbcontrol/send_message: broadcast message to "
" %d processes \n " , n_sent ) ) ;
2010-07-19 23:00:31 +04:00
2003-04-14 07:59:25 +04:00
return ret ;
}
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 */
2007-05-16 17:02:53 +04:00
static void wait_replies ( 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
2009-01-21 09:30:13 +03:00
if ( ! ( te = tevent_add_timer ( messaging_event_context ( msg_ctx ) , NULL ,
timeval_current_ofs ( timeout , 0 ) ,
smbcontrol_timeout , ( void * ) & timed_out ) ) ) {
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 ;
2009-01-21 09:30:13 +03:00
ret = tevent_loop_once ( messaging_event_context ( msg_ctx ) ) ;
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
{
2010-03-05 19:06:08 +03:00
char * pidstr ;
pidstr = procid_str ( talloc_tos ( ) , & pid ) ;
printf ( " PID %s: %.*s " , pidstr , ( int ) data - > length ,
( const char * ) data - > data ) ;
TALLOC_FREE ( pidstr ) ;
2004-04-30 03:05:58 +04:00
num_replies + + ;
}
2003-04-14 07:59:25 +04:00
/* Message handler callback that displays a string on stdout */
2007-05-16 17:02:53 +04:00
static void print_string_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
{
2010-01-18 01:07:39 +03:00
printf ( " %*s " , ( int ) data - > length , ( const char * ) data - > data ) ;
2003-04-14 07:59:25 +04:00
num_replies + + ;
}
/* Send no message. Useful for testing. */
2007-10-19 04:40:25 +04:00
static bool do_noop ( 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 */
2007-10-19 04:40:25 +04:00
static bool do_debug ( 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
static bool do_idmap ( struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
static const char * usage = " Usage: "
" smbcontrol <dest> idmap <cmd> [arg] \n "
" \t cmd: \t flush [gid|uid] \n "
" \t \t delete \" UID <uid> \" | \" GID <gid> \" |<sid> \n "
" \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 ;
}
if ( strcmp ( argv [ 1 ] , " flush " ) = = 0 ) {
msg_type = MSG_IDMAP_FLUSH ;
}
else if ( strcmp ( argv [ 1 ] , " delete " ) = = 0 ) {
msg_type = MSG_IDMAP_DELETE ;
}
else if ( strcmp ( argv [ 1 ] , " kill " ) = = 0 ) {
msg_type = MSG_IDMAP_KILL ;
}
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,
* but that ' s probably moot since this whole stack tracing implementatino is
* 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 ) ;
}
2010-03-01 16:28:22 +03:00
static int stack_trace_connection ( const struct connections_key * key ,
2007-05-28 15:38:42 +04:00
const struct connections_data * crec ,
void * priv )
2006-05-04 04:35:05 +04:00
{
2007-07-23 17:47:17 +04:00
print_stack_trace ( procid_to_pid ( & crec - > pid ) , ( int * ) priv ) ;
2006-05-04 04:35:05 +04:00
return 0 ;
}
2007-10-19 04:40:25 +04:00
static bool do_daemon_stack_trace ( struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-05-04 04:35:05 +04:00
const int argc , const char * * argv )
{
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 {
2010-03-01 16:28:22 +03:00
connections_forall_read ( stack_trace_connection , & count ) ;
2006-05-04 04:35:05 +04:00
}
return True ;
}
# else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
2007-10-19 04:40:25 +04:00
static bool do_daemon_stack_trace ( struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-05-04 04:35:05 +04:00
const int argc , const char * * argv )
{
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
2007-10-19 04:40:25 +04:00
static bool do_inject_fault ( struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-04-04 04:27:50 +04:00
const int argc , const char * * argv )
{
if ( argc ! = 2 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> inject "
" <bus|hup|term|internal|segv> \n " ) ;
return False ;
}
# ifndef DEVELOPER
2006-04-04 05:07:28 +04:00
fprintf ( stderr , " Fault injection is only available in "
2006-04-04 04:59:50 +04:00
" developer builds \n " ) ;
2006-04-04 04:27:50 +04:00
return False ;
# else /* DEVELOPER */
{
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
}
# endif /* DEVELOPER */
}
2003-04-14 07:59:25 +04:00
/* Force a browser election */
2007-10-19 04:40:25 +04:00
static bool do_election ( 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
{
2005-09-30 21:13:37 +04:00
char * src_string = procid_str ( NULL , & pid ) ;
printf ( " PONG from pid %s \n " , src_string ) ;
2006-02-20 20:59:58 +03:00
TALLOC_FREE ( src_string ) ;
2003-04-14 07:59:25 +04:00
num_replies + + ;
2000-10-07 03:01:47 +04:00
}
2007-10-19 04:40:25 +04:00
static bool do_ping ( 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
2007-05-16 17:02:53 +04:00
wait_replies ( 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 */
2007-10-19 04:40:25 +04:00
static bool do_profile ( 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
2007-10-19 04:40:25 +04:00
static bool do_profilelevel ( 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
2007-05-16 17:02:53 +04:00
wait_replies ( 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 */
2007-10-19 04:40:25 +04:00
static bool do_debuglevel ( 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
2007-05-16 17:02:53 +04:00
wait_replies ( 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 */
2007-10-19 04:40:25 +04:00
static bool do_printnotify ( 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
2010-08-08 18:16:37 +04:00
notify_printer_status_byname ( messaging_event_context ( msg_ctx ) ,
msg_ctx , argv [ 2 ] ,
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
2010-08-08 18:16:37 +04:00
notify_printer_status_byname ( messaging_event_context ( msg_ctx ) ,
msg_ctx , argv [ 2 ] ,
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 (
2010-08-08 18:21:42 +04:00
messaging_event_context ( msg_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 (
2010-08-08 18:21:42 +04:00
messaging_event_context ( msg_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 (
2010-08-08 18:21:42 +04:00
messaging_event_context ( msg_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 (
2010-08-08 18:21:42 +04:00
messaging_event_context ( msg_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 ) {
uint32 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
2010-08-08 18:42:59 +04:00
notify_printer_byname ( messaging_event_context ( msg_ctx ) ,
msg_ctx , argv [ 2 ] , attribute ,
2005-09-30 21:13:37 +04:00
CONST_DISCARD ( 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
2007-10-19 04:40:25 +04:00
static bool do_closeshare ( 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
2010-09-29 14:17:05 +04:00
/* Tell winbindd an IP got dropped */
static bool do_ip_dropped ( struct messaging_context * msg_ctx ,
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 ) ;
}
2007-05-29 18:49:19 +04:00
/* force a blocking lock retry */
2007-10-19 04:40:25 +04:00
static bool do_lockretry ( struct messaging_context * msg_ctx ,
2007-05-29 18:49:19 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> lockretry \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_SMB_UNLOCK , NULL , 0 ) ;
}
/* force a validation of all brl entries, including re-sends. */
2007-10-19 04:40:25 +04:00
static bool do_brl_revalidate ( struct messaging_context * msg_ctx ,
2007-05-29 18:49:19 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
{
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> brl-revalidate \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_SMB_BRL_VALIDATE , NULL , 0 ) ;
}
2003-04-14 07:59:25 +04:00
/* Force a SAM synchronisation */
2002-07-15 14:35:28 +04:00
2007-10-19 04:40:25 +04:00
static bool do_samsync ( 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> samsync \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_SAM_SYNC , NULL , 0 ) ;
2003-04-14 07:59:25 +04:00
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* Force a SAM replication */
2002-07-15 14:35:28 +04:00
2007-10-19 04:40:25 +04:00
static bool do_samrepl ( 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> samrepl \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_SAM_REPL , NULL , 0 ) ;
2003-04-14 07:59:25 +04:00
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* Display talloc pool usage */
2002-07-15 14:35:28 +04:00
2007-10-19 04:40:25 +04:00
static bool do_poolusage ( 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> pool-usage \n " ) ;
return False ;
}
2002-07-15 14:35:28 +04:00
2007-05-16 17:02:53 +04:00
messaging_register ( msg_ctx , NULL , MSG_POOL_USAGE , print_string_cb ) ;
2005-11-30 02:01:39 +03:00
2003-04-14 07:59:25 +04:00
/* Send a message and register our interest in a reply */
2002-07-15 14:35:28 +04:00
2007-05-22 02:17:13 +04:00
if ( ! send_message ( msg_ctx , pid , MSG_REQ_POOL_USAGE , NULL , 0 ) )
2003-04-14 07:59:25 +04:00
return False ;
2002-07-15 14:35:28 +04:00
2007-05-16 17:02:53 +04:00
wait_replies ( msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* No replies were received within the timeout period */
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
if ( num_replies = = 0 )
printf ( " No replies received \n " ) ;
2002-07-15 14:35:28 +04:00
2007-05-16 17:02:53 +04:00
messaging_deregister ( msg_ctx , MSG_POOL_USAGE , NULL ) ;
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
return num_replies ;
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* Perform a dmalloc mark */
2002-07-15 14:35:28 +04:00
2007-10-19 04:40:25 +04:00
static bool do_dmalloc_mark ( 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
2007-10-19 04:40:25 +04:00
static bool do_dmalloc_changed ( 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
2003-04-14 07:59:25 +04:00
/* Shutdown a server process */
2001-08-28 10:38:11 +04:00
2007-10-19 04:40:25 +04:00
static bool do_shutdown ( 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
2007-10-19 04:40:25 +04:00
static bool do_drvupgrade ( 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
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
}
2001-08-28 10:38:11 +04:00
2007-10-19 04:40:25 +04:00
static bool do_winbind_online ( struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-02-04 01:19:41 +03:00
const int argc , const char * * argv )
{
TDB_CONTEXT * tdb ;
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd online \n " ) ;
return False ;
}
/* Remove the entry in the winbindd_cache tdb to tell a later
starting winbindd that we ' re online . */
2009-01-16 02:31:17 +03:00
tdb = tdb_open_log ( cache_path ( " winbindd_cache.tdb " ) , 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 " ,
2009-01-16 02:31:17 +03:00
cache_path ( " winbindd_cache.tdb " ) ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
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
}
2007-10-19 04:40:25 +04:00
static bool do_winbind_offline ( struct messaging_context * msg_ctx ,
2007-05-15 00:31:28 +04:00
const struct server_id pid ,
2006-02-04 01:19:41 +03:00
const int argc , const char * * argv )
{
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 ;
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd offline \n " ) ;
return False ;
}
/* Create an entry in the winbindd_cache tdb to tell a later
starting winbindd that we ' re offline . We may actually create
it here . . . */
2009-01-16 02:31:17 +03:00
tdb = tdb_open_log ( cache_path ( " winbindd_cache.tdb " ) ,
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 " ,
2009-01-16 02:31:17 +03:00
cache_path ( " winbindd_cache.tdb " ) ) ;
2006-02-04 01:19:41 +03:00
return False ;
}
/* 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 + + ) {
TDB_DATA d ;
2007-03-29 13:35:51 +04:00
uint8 buf [ 4 ] ;
2006-10-09 19:11:37 +04:00
2006-02-04 01:19:41 +03:00
ZERO_STRUCT ( d ) ;
2006-10-09 19:11:37 +04:00
SIVAL ( buf , 0 , time ( NULL ) ) ;
d . dptr = buf ;
d . dsize = 4 ;
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 " ) ;
2010-07-19 23:00:31 +04:00
2006-10-09 19:11:37 +04:00
if ( ! d . dptr | | d . dsize ! = 4 ) {
SAFE_FREE ( d . dptr ) ;
2006-02-04 01:19:41 +03:00
DEBUG ( 10 , ( " do_winbind_offline: offline state not set - retrying. \n " ) ) ;
} else {
2006-10-09 19:11:37 +04:00
SAFE_FREE ( d . dptr ) ;
2006-02-04 01:19:41 +03:00
break ;
}
}
tdb_close ( tdb ) ;
return ret ;
}
2007-10-19 04:40:25 +04:00
static bool do_winbind_onlinestatus ( 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 )
{
2007-05-07 13:35:35 +04:00
struct server_id myid ;
2006-05-04 16:37:13 +04:00
2010-07-19 23:04:04 +04:00
myid = messaging_server_id ( msg_ctx ) ;
2006-05-04 16:37:13 +04:00
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
2007-05-15 18:39:18 +04:00
if ( ! send_message ( msg_ctx , pid , MSG_WINBIND_ONLINESTATUS , & myid ,
2007-05-22 02:17:13 +04:00
sizeof ( myid ) ) )
2006-05-04 16:37:13 +04:00
return False ;
2007-05-16 17:02:53 +04:00
wait_replies ( 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 ;
}
2007-10-19 04:40:25 +04:00
static bool do_dump_event_list ( struct messaging_context * msg_ctx ,
2007-06-21 17:04:28 +04:00
const struct server_id pid ,
const int argc , const char * * argv )
{
struct server_id myid ;
2010-07-19 23:04:04 +04:00
myid = messaging_server_id ( msg_ctx ) ;
2007-06-21 17:04:28 +04:00
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol <dest> dump-event-list \n " ) ;
return False ;
}
return send_message ( msg_ctx , pid , MSG_DUMP_EVENT_LIST , NULL , 0 ) ;
}
2008-01-24 18:09:20 +03:00
static bool do_winbind_dump_domain_list ( struct messaging_context * msg_ctx ,
const struct server_id pid ,
const int argc , const char * * argv )
{
const char * domain = NULL ;
int domain_len = 0 ;
struct server_id myid ;
uint8_t * buf = NULL ;
int buf_len = 0 ;
2010-07-19 23:04:04 +04:00
myid = messaging_server_id ( msg_ctx ) ;
2008-01-24 18:09:20 +03:00
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 ) ;
buf_len = sizeof ( myid ) + domain_len ;
2008-02-23 12:52:12 +03:00
buf = SMB_MALLOC_ARRAY ( uint8_t , buf_len ) ;
2008-01-24 18:09:20 +03:00
if ( ! buf ) {
return false ;
}
memcpy ( buf , & myid , sizeof ( myid ) ) ;
memcpy ( & buf [ sizeof ( myid ) ] , domain , domain_len ) ;
if ( ! send_message ( msg_ctx , pid , MSG_WINBIND_DUMP_DOMAIN_LIST ,
buf , buf_len ) )
{
SAFE_FREE ( buf ) ;
return false ;
}
wait_replies ( msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
/* No replies were received within the timeout period */
SAFE_FREE ( buf ) ;
if ( num_replies = = 0 ) {
printf ( " No replies received \n " ) ;
}
messaging_deregister ( msg_ctx , MSG_WINBIND_DUMP_DOMAIN_LIST , NULL ) ;
return num_replies ;
}
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 )
{
char * src_string = procid_str ( NULL , & pid ) ;
printf ( " Winbindd cache is %svalid. (answer from pid %s) \n " ,
( * ( data - > data ) = = 0 ? " " : " NOT " ) , src_string ) ;
TALLOC_FREE ( src_string ) ;
num_replies + + ;
}
2007-10-19 04:40:25 +04:00
static bool do_winbind_validate_cache ( 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 ;
}
wait_replies ( msg_ctx , procid_to_pid ( & pid ) = = 0 ) ;
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
2007-10-19 04:40:25 +04:00
static bool do_reload_config ( 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
}
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 ) ;
strupper_m ( unix_name ) ;
push_ascii ( n - > name , unix_name , sizeof ( n - > name ) , STR_TERMINATE ) ;
n - > name_type = ( unsigned int ) type & 0xFF ;
push_ascii ( n - > scope , global_scope ( ) , 64 , STR_TERMINATE ) ;
}
2007-10-19 04:40:25 +04:00
static bool do_nodestatus ( 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
}
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 */
2007-10-19 04:40:25 +04:00
bool ( * fn ) ( 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 [ ] = {
{ " debug " , do_debug , " Set debuglevel " } ,
2011-02-03 18:30:29 +03:00
{ " idmap " , do_idmap , " Manipulate idmap cache " } ,
2003-04-14 07:59:25 +04:00
{ " force-election " , do_election ,
" Force a browse election " } ,
{ " ping " , do_ping , " Elicit a response " } ,
{ " profile " , do_profile , " " } ,
2006-04-04 04:27:50 +04:00
{ " inject " , do_inject_fault ,
" Inject a fatal signal into a running smbd " } ,
2006-05-04 04:35:05 +04:00
{ " stacktrace " , do_daemon_stack_trace ,
" Display a stack trace of a daemon " } ,
2003-04-14 07:59:25 +04:00
{ " profilelevel " , do_profilelevel , " " } ,
{ " debuglevel " , do_debuglevel , " Display current debuglevels " } ,
{ " printnotify " , do_printnotify , " Send a print notify message " } ,
{ " close-share " , do_closeshare , " Forcibly disconnect a share " } ,
2010-09-29 14:17:05 +04:00
{ " ip-dropped " , do_ip_dropped , " Tell winbind that an IP got dropped " } ,
2007-05-29 18:49:19 +04:00
{ " lockretry " , do_lockretry , " Force a blocking lock retry " } ,
{ " brl-revalidate " , do_brl_revalidate , " Revalidate all brl entries " } ,
2003-04-14 07:59:25 +04:00
{ " samsync " , do_samsync , " Initiate SAM synchronisation " } ,
{ " samrepl " , do_samrepl , " Initiate SAM replication " } ,
{ " pool-usage " , do_poolusage , " Display talloc memory usage " } ,
{ " dmalloc-mark " , do_dmalloc_mark , " " } ,
{ " dmalloc-log-changed " , do_dmalloc_changed , " " } ,
{ " shutdown " , do_shutdown , " Shut down daemon " } ,
{ " drvupgrade " , do_drvupgrade , " Notify a printer driver has changed " } ,
2003-07-15 21:21:21 +04:00
{ " reload-config " , do_reload_config , " Force smbd or winbindd to reload config file " } ,
2005-06-09 02:10:34 +04:00
{ " nodestatus " , do_nodestatus , " Ask nmbd to do a node status request " } ,
2006-02-04 01:19:41 +03:00
{ " online " , do_winbind_online , " Ask winbind to go into online state " } ,
{ " offline " , do_winbind_offline , " Ask winbind to go into offline state " } ,
2006-05-04 16:37:13 +04:00
{ " onlinestatus " , do_winbind_onlinestatus , " Request winbind online status " } ,
2007-06-21 17:04:28 +04:00
{ " dump-event-list " , do_dump_event_list , " Dump event list " } ,
2007-08-31 19:24:43 +04:00
{ " validate-cache " , do_winbind_validate_cache ,
" Validate winbind's credential cache " } ,
2008-01-24 18:09:20 +03:00
{ " dump-domain-list " , do_winbind_dump_domain_list , " Dump winbind domain list " } ,
2003-04-14 07:59:25 +04:00
{ " noop " , do_noop , " Do nothing " } ,
{ NULL }
} ;
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 " ) ;
for ( i = 0 ; msg_types [ i ] . name ; i + + )
fprintf ( stderr , " \t %-30s%s \n " , msg_types [ i ] . name ,
msg_types [ i ] . help ) ;
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
{
2007-05-07 13:35:35 +04:00
struct server_id result = { - 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 */
2005-09-30 21:13:37 +04:00
if ( ( pid = pidfile_pid ( dest ) ) ! = 0 ) {
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 */
2007-10-19 04:40:25 +04:00
static bool do_command ( 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 ) )
2007-05-15 00:31:28 +04:00
return msg_types [ i ] . fn ( msg_ctx , pid ,
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
2006-01-09 01:00:01 +03:00
load_case_tables ( ) ;
2010-10-29 07:19:32 +04:00
setup_logging ( argv [ 0 ] , DEBUG_STDOUT ) ;
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
2007-12-10 22:30:37 +03:00
lp_load ( get_dyn_CONFIGFILE ( ) , False , False , False , True ) ;
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
2009-01-21 09:30:13 +03:00
if ( ! ( evt_ctx = tevent_context_init ( NULL ) ) | |
2010-02-23 17:04:10 +03:00
! ( msg_ctx = messaging_init ( NULL , procid_self ( ) , evt_ctx ) ) ) {
2007-05-15 00:31:28 +04:00
fprintf ( stderr , " could not init messaging context \n " ) ;
2007-08-31 14:06:37 +04:00
TALLOC_FREE ( frame ) ;
2007-05-15 00:31:28 +04:00
exit ( 1 ) ;
}
2010-07-19 23:00:31 +04:00
2007-08-31 14:06:37 +04:00
ret = ! do_command ( msg_ctx , argc , argv ) ;
TALLOC_FREE ( frame ) ;
return ret ;
2000-09-13 11:07:17 +04:00
}