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
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
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
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
2005-09-30 21:13:37 +04:00
static BOOL send_message ( struct process_id pid , int msg_type ,
const void * buf , int len ,
2003-04-14 07:59:25 +04:00
BOOL duplicates )
{
TDB_CONTEXT * tdb ;
BOOL ret ;
int n_sent = 0 ;
if ( ! message_init ( ) )
return False ;
2005-09-30 21:13:37 +04:00
if ( procid_to_pid ( & pid ) ! = 0 )
2003-04-14 07:59:25 +04:00
return message_send_pid ( pid , msg_type , buf , len , duplicates ) ;
tdb = tdb_open_log ( lock_path ( " connections.tdb " ) , 0 ,
TDB_DEFAULT , O_RDWR , 0 ) ;
if ( ! tdb ) {
fprintf ( stderr , " Failed to open connections database "
" : %s \n " , strerror ( errno ) ) ;
return False ;
}
ret = message_send_all ( tdb , msg_type , buf , len , duplicates ,
& n_sent ) ;
DEBUG ( 10 , ( " smbcontrol/send_message: broadcast message to "
" %d processes \n " , n_sent ) ) ;
tdb_close ( tdb ) ;
return ret ;
}
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
/* Wait for one or more reply messages */
static void wait_replies ( BOOL multiple_replies )
{
time_t start_time = time ( NULL ) ;
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
/* Wait around a bit. This is pretty disgusting - we have to
busy - wait here as there is no nicer way to do it . */
2002-11-26 03:46:31 +03:00
2003-04-14 07:59:25 +04:00
do {
message_dispatch ( ) ;
if ( num_replies > 0 & & ! multiple_replies )
break ;
sleep ( 1 ) ;
} while ( timeout - ( time ( NULL ) - start_time ) > 0 ) ;
}
2004-04-30 03:05:58 +04:00
/* Message handler callback that displays the PID and a string on stdout */
2005-09-30 21:13:37 +04:00
static void print_pid_string_cb ( int msg_type , struct process_id pid , void * buf , size_t len )
2004-04-30 03:05:58 +04:00
{
2005-09-30 21:13:37 +04:00
printf ( " PID %u: %.*s " , ( unsigned int ) procid_to_pid ( & pid ) ,
( int ) len , ( const char * ) buf ) ;
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 */
2005-09-30 21:13:37 +04:00
static void print_string_cb ( int msg_type , struct process_id pid ,
void * buf , size_t len )
2000-09-13 11:07:17 +04:00
{
2003-04-14 07:59:25 +04:00
printf ( " %.*s " , ( int ) len , ( const char * ) buf ) ;
num_replies + + ;
}
/* Send no message. Useful for testing. */
2005-09-30 21:13:37 +04:00
static BOOL do_noop ( const struct process_id pid ,
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 */
2005-09-30 21:13:37 +04:00
static BOOL do_debug ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_DEBUG , argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 , False ) ;
}
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 ) ;
}
static int stack_trace_connection ( TDB_CONTEXT * tdb , TDB_DATA key ,
TDB_DATA data , void * priv )
{
struct connections_data conn ;
if ( data . dsize ! = sizeof ( conn ) )
return 0 ;
memcpy ( & conn , data . dptr , sizeof ( conn ) ) ;
print_stack_trace ( procid_to_pid ( & conn . pid ) , ( int * ) priv ) ;
return 0 ;
}
static BOOL do_daemon_stack_trace ( const struct process_id pid ,
const int argc , const char * * argv )
{
fprintf ( stderr ,
" Daemon stack tracing is not supported on this platform \n " ) ;
return False ;
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 {
TDB_CONTEXT * tdb ;
tdb = tdb_open_log ( lock_path ( " connections.tdb " ) , 0 ,
TDB_DEFAULT , O_RDONLY , 0 ) ;
if ( ! tdb ) {
fprintf ( stderr ,
" Failed to open connections database: %s \n " ,
strerror ( errno ) ) ;
return False ;
}
tdb_traverse ( tdb , stack_trace_connection , & count ) ;
tdb_close ( tdb ) ;
}
return True ;
}
# else /* defined(HAVE_LIBUNWIND_PTRACE) && defined(HAVE_LINUX_PTRACE) */
static BOOL do_daemon_stack_trace ( const struct process_id pid ,
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
static BOOL do_inject_fault ( const struct process_id pid ,
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 ;
}
return send_message ( pid , MSG_SMB_INJECT_FAULT ,
& sig , sizeof ( int ) , False ) ;
}
# endif /* DEVELOPER */
}
2003-04-14 07:59:25 +04:00
/* Force a browser election */
2005-09-30 21:13:37 +04:00
static BOOL do_election ( const struct process_id pid ,
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
return send_message (
pid , MSG_FORCE_ELECTION , NULL , 0 , False ) ;
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
2005-09-30 21:13:37 +04:00
static void pong_cb ( int msg_type , struct process_id pid , void * buf , size_t len )
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
}
2005-09-30 21:13:37 +04:00
static BOOL do_ping ( const struct process_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 */
if ( ! send_message ( pid , MSG_PING , NULL , 0 , False ) )
return False ;
message_register ( MSG_PONG , pong_cb ) ;
2005-09-30 21:13:37 +04:00
wait_replies ( 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 " ) ;
message_deregister ( MSG_PONG ) ;
return num_replies ;
2002-12-20 23:21:31 +03:00
}
2003-04-14 07:59:25 +04:00
/* Set profiling options */
2005-09-30 21:13:37 +04:00
static BOOL do_profile ( const struct process_id pid ,
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 ;
}
return send_message ( pid , MSG_PROFILE , & v , sizeof ( int ) , False ) ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Return the profiling level */
2005-09-30 21:13:37 +04:00
static void profilelevel_cb ( int msg_type , struct process_id pid , void * buf , size_t len )
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 + + ;
if ( len ! = sizeof ( int ) ) {
2003-11-07 01:11:08 +03:00
fprintf ( stderr , " invalid message length %ld returned \n " ,
( unsigned long ) len ) ;
2003-04-14 07:59:25 +04:00
return ;
}
memcpy ( & level , buf , sizeof ( int ) ) ;
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
}
2003-04-14 07:59:25 +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
}
2005-09-30 21:13:37 +04:00
static void profilelevel_rqst ( int msg_type , struct process_id pid ,
void * buf , size_t len )
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 */
send_message ( pid , MSG_PROFILELEVEL , & v , sizeof ( int ) , False ) ;
}
2001-12-21 07:28:03 +03:00
2005-09-30 21:13:37 +04:00
static BOOL do_profilelevel ( const struct process_id pid ,
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 */
if ( ! send_message ( pid , MSG_REQ_PROFILELEVEL , NULL , 0 , False ) )
return False ;
message_register ( MSG_PROFILELEVEL , profilelevel_cb ) ;
message_register ( MSG_REQ_PROFILELEVEL , profilelevel_rqst ) ;
2005-09-30 21:13:37 +04:00
wait_replies ( 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 " ) ;
message_deregister ( MSG_PROFILE ) ;
return num_replies ;
2000-09-13 11:07:17 +04:00
}
2003-04-14 07:59:25 +04:00
/* Display debug level settings */
2005-09-30 21:13:37 +04:00
static BOOL do_debuglevel ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
if ( ! send_message ( pid , MSG_REQ_DEBUGLEVEL , NULL , 0 , False ) )
return False ;
2002-01-09 11:27:15 +03:00
2004-04-30 03:05:58 +04:00
message_register ( MSG_DEBUGLEVEL , print_pid_string_cb ) ;
2002-08-17 18:45:04 +04:00
2005-09-30 21:13:37 +04:00
wait_replies ( 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
2003-04-14 07:59:25 +04:00
message_deregister ( MSG_DEBUGLEVEL ) ;
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 */
2005-09-30 21:13:37 +04:00
static BOOL do_printnotify ( const struct process_id pid ,
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 " ) ;
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
}
2003-04-14 07:59:25 +04:00
notify_printer_status_byname ( 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
}
2003-04-14 07:59:25 +04:00
notify_printer_status_byname ( 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 (
argv [ 2 ] , jobid , JOB_STATUS_PAUSED ,
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 (
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 (
argv [ 2 ] , jobid , JOB_STATUS_DELETING ,
SPOOLSS_NOTIFY_MSG_UNIX_JOBID ) ;
notify_job_status_byname (
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 ;
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 ) {
attribute = PRINTER_NOTIFY_COMMENT ;
} else if ( strcmp ( argv [ 3 ] , " port " ) = = 0 ) {
attribute = PRINTER_NOTIFY_PORT_NAME ;
} else if ( strcmp ( argv [ 3 ] , " driver " ) = = 0 ) {
attribute = PRINTER_NOTIFY_DRIVER_NAME ;
} 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
2005-09-30 21:13:37 +04:00
notify_printer_byname ( argv [ 2 ] , attribute ,
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 :
print_notify_send_messages ( 0 ) ;
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
2005-09-30 21:13:37 +04:00
static BOOL do_closeshare ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_SMB_FORCE_TDIS , argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 , False ) ;
}
2002-07-15 14:35:28 +04:00
2003-04-14 07:59:25 +04:00
/* Force a SAM synchronisation */
2002-07-15 14:35:28 +04:00
2005-09-30 21:13:37 +04:00
static BOOL do_samsync ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_SMB_SAM_SYNC , NULL , 0 , False ) ;
}
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
2005-09-30 21:13:37 +04:00
static BOOL do_samrepl ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_SMB_SAM_REPL , NULL , 0 , False ) ;
}
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
2005-09-30 21:13:37 +04:00
static BOOL do_poolusage ( const struct process_id pid ,
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
2005-11-30 02:01:39 +03:00
message_register ( MSG_POOL_USAGE , print_string_cb ) ;
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
2003-04-14 07:59:25 +04:00
if ( ! send_message ( pid , MSG_REQ_POOL_USAGE , NULL , 0 , False ) )
return False ;
2002-07-15 14:35:28 +04:00
2005-09-30 21:13:37 +04:00
wait_replies ( 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
2003-04-14 07:59:25 +04:00
message_deregister ( MSG_POOL_USAGE ) ;
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
2005-09-30 21:13:37 +04:00
static BOOL do_dmalloc_mark ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_REQ_DMALLOC_MARK , NULL , 0 , False ) ;
}
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
2005-09-30 21:13:37 +04:00
static BOOL do_dmalloc_changed ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_REQ_DMALLOC_LOG_CHANGED , NULL , 0 , False ) ;
}
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
2005-09-30 21:13:37 +04:00
static BOOL do_shutdown ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message ( pid , MSG_SHUTDOWN , NULL , 0 , False ) ;
}
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
2005-09-30 21:13:37 +04:00
static BOOL do_drvupgrade ( const struct process_id pid ,
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
2003-04-14 07:59:25 +04:00
return send_message (
pid , MSG_DEBUG , argv [ 1 ] , strlen ( argv [ 1 ] ) + 1 , False ) ;
}
2001-08-28 10:38:11 +04:00
2006-02-04 01:19:41 +03:00
static BOOL do_winbind_online ( const struct process_id pid ,
const int argc , const char * * argv )
{
TDB_CONTEXT * tdb ;
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd online \n " ) ;
return False ;
}
if ( ! lp_winbind_offline_logon ( ) ) {
fprintf ( stderr , " The parameter \" winbind offline logon \" must "
" be set in the [global] section of smb.conf for this "
" command to be allowed. \n " ) ;
return False ;
}
/* Remove the entry in the winbindd_cache tdb to tell a later
starting winbindd that we ' re online . */
tdb = tdb_open_log ( lock_path ( " winbindd_cache.tdb " ) , 0 , TDB_DEFAULT , O_RDWR , 0600 ) ;
if ( ! tdb ) {
fprintf ( stderr , " Cannot open the tdb %s for writing. \n " ,
lock_path ( " winbindd_cache.tdb " ) ) ;
return False ;
}
tdb_delete_bystring ( tdb , " WINBINDD_OFFLINE " ) ;
tdb_close ( tdb ) ;
return send_message ( pid , MSG_WINBIND_ONLINE , NULL , 0 , False ) ;
}
static BOOL do_winbind_offline ( const struct process_id pid ,
const int argc , const char * * argv )
{
TDB_CONTEXT * tdb ;
BOOL ret = False ;
int retry = 0 ;
if ( argc ! = 1 ) {
fprintf ( stderr , " Usage: smbcontrol winbindd offline \n " ) ;
return False ;
}
if ( ! lp_winbind_offline_logon ( ) ) {
fprintf ( stderr , " The parameter \" winbind offline logon \" must "
" be set in the [global] section of smb.conf for this "
" command to be allowed. \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 . . . */
tdb = tdb_open_log ( lock_path ( " winbindd_cache.tdb " ) ,
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE ,
TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */ , O_RDWR | O_CREAT , 0600 ) ;
if ( ! tdb ) {
fprintf ( stderr , " Cannot open the tdb %s for writing. \n " ,
lock_path ( " winbindd_cache.tdb " ) ) ;
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 + + ) {
int err ;
TDB_DATA d ;
ZERO_STRUCT ( d ) ;
tdb_store_bystring ( tdb , " WINBINDD_OFFLINE " , d , TDB_INSERT ) ;
ret = send_message ( pid , MSG_WINBIND_OFFLINE , NULL , 0 , False ) ;
/* Check that the entry "WINBINDD_OFFLINE" still exists. */
tdb - > ecode = 0 ;
d = tdb_fetch_bystring ( tdb , " WINBINDD_OFFLINE " ) ;
/* As this is a key with no data we don't need to free, we
check for existence by looking at tdb_err . */
err = tdb_error ( tdb ) ;
if ( err = = TDB_ERR_NOEXIST ) {
DEBUG ( 10 , ( " do_winbind_offline: offline state not set - retrying. \n " ) ) ;
} else {
break ;
}
}
tdb_close ( tdb ) ;
return ret ;
}
2005-09-30 21:13:37 +04:00
static BOOL do_reload_config ( const struct process_id pid ,
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 ;
}
return send_message ( pid , MSG_SMB_CONF_UPDATED , NULL , 0 , False ) ;
}
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 ) ;
}
2005-09-30 21:13:37 +04:00
static BOOL do_nodestatus ( const struct process_id pid ,
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 ) ;
p . ip = * interpret_addr2 ( argv [ 1 ] ) ;
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 ;
return send_message ( pid , MSG_SEND_PACKET , & p , sizeof ( p ) , False ) ;
}
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 */
2005-09-30 21:13:37 +04:00
BOOL ( * fn ) ( const struct process_id pid ,
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 " } ,
{ " 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 " } ,
{ " 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 " } ,
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
2003-04-14 07:59:25 +04:00
static void usage ( poptContext * pc )
{
int i ;
2002-03-29 16:49:48 +03:00
2003-04-14 07:59:25 +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 */
2005-09-30 21:13:37 +04:00
static struct process_id parse_dest ( const char * dest )
2003-04-14 07:59:25 +04:00
{
2006-04-20 18:14:12 +04:00
struct process_id result = { - 1 } ;
2003-04-14 07:59:25 +04:00
pid_t pid ;
/* Zero is a special return value for broadcast smbd */
2005-09-30 21:13:37 +04:00
if ( strequal ( dest , " smbd " ) ) {
return interpret_pid ( " 0 " ) ;
}
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 " ) ) {
return pid_to_procid ( sys_getpid ( ) ) ;
}
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 " ;
}
2006-02-26 18:02:16 +03:00
if ( ! ( strequal ( dest , " winbindd " ) | | strequal ( dest , " nmbd " ) ) ) {
/* Check for numeric pid number */
2003-04-14 07:59:25 +04:00
2006-02-26 18:02:16 +03:00
result = interpret_pid ( dest ) ;
2006-02-04 01:19:41 +03:00
2006-02-26 18:02:16 +03:00
/* Zero isn't valid if not smbd. */
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 ;
2003-04-14 07:59:25 +04:00
}
/* Execute smbcontrol command */
2003-06-28 00:55:48 +04:00
static BOOL do_command ( 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 ] ;
2005-09-30 21:13:37 +04:00
struct process_id pid ;
2003-04-14 07:59:25 +04:00
int i ;
/* Check destination */
2005-09-30 21:13:37 +04:00
pid = parse_dest ( dest ) ;
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 ) )
return msg_types [ i ] . fn ( 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
}
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 ;
2003-04-30 17:22:02 +04:00
static struct poptOption wbinfo_options [ ] = {
2003-04-14 07:59:25 +04:00
{ " timeout " , ' t ' , POPT_ARG_INT , & timeout , ' t ' ,
" Set timeout value in seconds " , " TIMEOUT " } ,
{ " configfile " , ' s ' , POPT_ARG_STRING , NULL , ' s ' ,
" Use alternative configuration file " , " CONFIGFILE " } ,
POPT_TABLEEND
} ;
struct poptOption options [ ] = {
{ NULL , 0 , POPT_ARG_INCLUDE_TABLE , wbinfo_options , 0 ,
" Options " } ,
POPT_AUTOHELP
POPT_COMMON_VERSION
POPT_TABLEEND
} ;
2002-01-08 00:32:22 +03:00
2006-01-09 01:00:01 +03:00
load_case_tables ( ) ;
2000-09-30 00:08:00 +04:00
setup_logging ( argv [ 0 ] , True ) ;
2003-04-14 07:59:25 +04:00
/* Parse command line arguments using popt */
pc = poptGetContext (
" smbcontrol " , argc , ( const char * * ) argv , options , 0 ) ;
poptSetOtherOptionHelp ( pc , " [OPTION...] <destination> <message-type> "
" <parameters> " ) ;
if ( argc = = 1 )
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 */
argc - = 2 ;
2000-09-30 00:08:00 +04:00
break ;
2003-04-14 07:59:25 +04:00
case ' s ' : /* --configfile */
2004-01-06 23:01:48 +03:00
pstrcpy ( dyn_CONFIGFILE , poptGetOptArg ( pc ) ) ;
2003-04-14 07:59:25 +04:00
argc - = 2 ;
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 ) ;
2003-04-14 07:59:25 +04:00
argc - - ; /* Don't forget about argv[0] */
2000-09-30 00:08:00 +04:00
2003-04-14 07:59:25 +04:00
if ( argc = = 1 )
usage ( & pc ) ;
2002-01-09 11:27:15 +03:00
2006-01-29 01:53:04 +03:00
lp_load ( 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. */
return ! do_command ( argc , argv ) ;
2000-09-13 11:07:17 +04:00
}