1996-05-04 11:50:46 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
status reporting
1998-01-22 16:27:43 +03:00
Copyright ( C ) Andrew Tridgell 1994 - 1998
1996-05-04 11:50:46 +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 .
1996-08-15 19:11:34 +04:00
Revision History :
12 aug 96 : Erik . Devriendt @ te6 . siemens . be
added support for shared memory implementation of share mode locking
1998-07-24 05:08:31 +04:00
21 - Jul - 1998 : rsharpe @ ns . aus . com ( Richard Sharpe )
Added - L ( locks only ) - S ( shares only ) flags and code
1996-05-04 11:50:46 +04:00
*/
/*
* This program reports current SMB connections
*/
1998-07-29 07:08:05 +04:00
# define NO_SYSLOG
1996-05-04 11:50:46 +04:00
# include "includes.h"
1997-05-09 01:17:59 +04:00
struct session_record {
1999-12-13 16:27:58 +03:00
pid_t pid ;
uid_t uid ;
1997-05-09 01:17:59 +04:00
char machine [ 31 ] ;
time_t start ;
struct session_record * next ;
} * srecs ;
1996-05-04 11:50:46 +04:00
extern int DEBUGLEVEL ;
extern FILE * dbf ;
static pstring Ucrit_username = " " ; /* added by OH */
1999-12-21 07:54:30 +03:00
static pid_t Ucrit_pid [ 100 ] ; /* Ugly !!! */ /* added by OH */
static int Ucrit_MaxPid = 0 ; /* added by OH */
static unsigned int Ucrit_IsActive = 0 ; /* added by OH */
static int verbose , brief ;
static int shares_only = 0 ; /* Added by RJS */
static int locks_only = 0 ; /* Added by RJS */
static BOOL processes_only = False ;
2000-01-16 14:14:44 +03:00
static int show_brl ;
1998-07-24 05:08:31 +04:00
1997-10-20 12:46:00 +04:00
/* we need these because we link to locking*.o */
2001-03-11 03:32:10 +03:00
void become_root ( void ) { }
void unbecome_root ( void ) { }
1997-05-20 04:32:51 +04:00
1998-08-10 05:25:32 +04:00
/* added by OH */
static void Ucrit_addUsername ( char * username )
{
pstrcpy ( Ucrit_username , username ) ;
if ( strlen ( Ucrit_username ) > 0 )
Ucrit_IsActive = 1 ;
}
static unsigned int Ucrit_checkUsername ( char * username )
{
if ( ! Ucrit_IsActive ) return 1 ;
if ( strcmp ( Ucrit_username , username ) = = 0 ) return 1 ;
return 0 ;
}
1999-12-13 16:27:58 +03:00
static void Ucrit_addPid ( pid_t pid )
1998-08-10 05:25:32 +04:00
{
int i ;
if ( ! Ucrit_IsActive ) return ;
for ( i = 0 ; i < Ucrit_MaxPid ; i + + )
if ( pid = = Ucrit_pid [ i ] ) return ;
Ucrit_pid [ Ucrit_MaxPid + + ] = pid ;
}
1999-12-13 16:27:58 +03:00
static unsigned int Ucrit_checkPid ( pid_t pid )
1998-08-10 05:25:32 +04:00
{
int i ;
if ( ! Ucrit_IsActive ) return 1 ;
for ( i = 0 ; i < Ucrit_MaxPid ; i + + )
if ( pid = = Ucrit_pid [ i ] ) return 1 ;
return 0 ;
}
1997-10-20 12:46:00 +04:00
static void print_share_mode ( share_mode_entry * e , char * fname )
{
static int count ;
if ( count = = 0 ) {
printf ( " Locked files: \n " ) ;
printf ( " Pid DenyMode R/W Oplock Name \n " ) ;
printf ( " -------------------------------------------------- \n " ) ;
}
count + + ;
1998-05-30 06:25:11 +04:00
if ( Ucrit_checkPid ( e - > pid ) ) {
1999-12-13 16:27:58 +03:00
printf ( " %-5d " , ( int ) e - > pid ) ;
2000-01-16 15:27:20 +03:00
switch ( GET_DENY_MODE ( e - > share_mode ) ) {
1998-05-30 06:25:11 +04:00
case DENY_NONE : printf ( " DENY_NONE " ) ; break ;
case DENY_ALL : printf ( " DENY_ALL " ) ; break ;
case DENY_DOS : printf ( " DENY_DOS " ) ; break ;
case DENY_READ : printf ( " DENY_READ " ) ; break ;
case DENY_WRITE : printf ( " DENY_WRITE " ) ; break ;
2000-01-16 14:14:44 +03:00
case DENY_FCB : printf ( " DENY_FCB " ) ; break ;
1998-05-30 06:25:11 +04:00
}
switch ( e - > share_mode & 0xF ) {
case 0 : printf ( " RDONLY " ) ; break ;
case 1 : printf ( " WRONLY " ) ; break ;
case 2 : printf ( " RDWR " ) ; break ;
}
if ( ( e - > op_type &
( EXCLUSIVE_OPLOCK | BATCH_OPLOCK ) ) = =
( EXCLUSIVE_OPLOCK | BATCH_OPLOCK ) )
1997-10-20 12:46:00 +04:00
printf ( " EXCLUSIVE+BATCH " ) ;
1998-05-30 06:25:11 +04:00
else if ( e - > op_type & EXCLUSIVE_OPLOCK )
1997-10-20 12:46:00 +04:00
printf ( " EXCLUSIVE " ) ;
1998-05-30 06:25:11 +04:00
else if ( e - > op_type & BATCH_OPLOCK )
1997-10-20 12:46:00 +04:00
printf ( " BATCH " ) ;
1999-12-13 16:27:58 +03:00
else if ( e - > op_type & LEVEL_II_OPLOCK )
printf ( " LEVEL_II " ) ;
1998-05-30 06:25:11 +04:00
else
1997-10-20 12:46:00 +04:00
printf ( " NONE " ) ;
1999-12-13 16:27:58 +03:00
printf ( " %s %s " , dos_to_unix ( fname , False ) ,
asctime ( LocalTime ( ( time_t * ) & e - > time . tv_sec ) ) ) ;
1998-05-30 06:25:11 +04:00
}
1997-10-20 12:46:00 +04:00
}
1997-05-20 04:32:51 +04:00
2000-01-16 14:14:44 +03:00
static void print_brl ( SMB_DEV_T dev , SMB_INO_T ino , int pid ,
enum brl_type lock_type ,
br_off start , br_off size )
{
static int count ;
if ( count = = 0 ) {
printf ( " Byte range locks: \n " ) ;
printf ( " Pid dev:inode R/W start size \n " ) ;
printf ( " ------------------------------------------------ \n " ) ;
}
count + + ;
printf ( " %6d %05x:%05x %s %9.0f %9.0f \n " ,
( int ) pid , ( int ) dev , ( int ) ino ,
lock_type = = READ_LOCK ? " R " : " W " ,
( double ) start , ( double ) size ) ;
}
1997-05-20 04:32:51 +04:00
1999-04-01 09:22:58 +04:00
/*******************************************************************
dump the elements of the profile structure
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static int profile_dump ( void )
{
# ifndef WITH_PROFILE
fprintf ( stderr , " ERROR: not compiled with profile support \n " ) ;
return - 1 ;
# else
if ( ! profile_setup ( True ) ) {
fprintf ( stderr , " Failed to initialise profile memory \n " ) ;
return - 1 ;
}
printf ( " smb_count: \t %u \n " , profile_p - > smb_count ) ;
printf ( " uid_changes: \t %u \n " , profile_p - > uid_changes ) ;
return 0 ;
# endif
}
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
(This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a)
2000-02-04 07:59:31 +03:00
static int traverse_fn1 ( TDB_CONTEXT * tdb , TDB_DATA kbuf , TDB_DATA dbuf , void * state )
1999-12-21 07:54:30 +03:00
{
static pid_t last_pid ;
struct session_record * ptr ;
struct connections_data crec ;
2001-05-15 22:12:02 +04:00
if ( dbuf . dsize ! = sizeof ( crec ) )
return 0 ;
1999-12-21 07:54:30 +03:00
memcpy ( & crec , dbuf . dptr , sizeof ( crec ) ) ;
2001-05-15 22:12:02 +04:00
if ( crec . cnum = = - 1 )
return 0 ;
1999-12-21 07:54:30 +03:00
if ( ! process_exists ( crec . pid ) | | ! Ucrit_checkUsername ( uidtoname ( crec . uid ) ) ) {
return 0 ;
}
if ( brief ) {
ptr = srecs ;
while ( ptr ! = NULL ) {
if ( ( ptr - > pid = = crec . pid ) & & ( strncmp ( ptr - > machine , crec . machine , 30 ) = = 0 ) ) {
if ( ptr - > start > crec . start )
ptr - > start = crec . start ;
break ;
}
ptr = ptr - > next ;
}
if ( ptr = = NULL ) {
ptr = ( struct session_record * ) malloc ( sizeof ( struct session_record ) ) ;
ptr - > uid = crec . uid ;
ptr - > pid = crec . pid ;
ptr - > start = crec . start ;
strncpy ( ptr - > machine , crec . machine , 30 ) ;
ptr - > machine [ 30 ] = ' \0 ' ;
ptr - > next = srecs ;
srecs = ptr ;
}
} else {
Ucrit_addPid ( crec . pid ) ;
if ( processes_only ) {
if ( last_pid ! = crec . pid )
printf ( " %d \n " , ( int ) crec . pid ) ;
last_pid = crec . pid ; /* XXXX we can still get repeats, have to
add a sort at some time */
} else {
printf ( " %-10.10s %-8s %-8s %5d %-8s (%s) %s " ,
crec . name , uidtoname ( crec . uid ) , gidtoname ( crec . gid ) , ( int ) crec . pid ,
crec . machine , crec . addr ,
asctime ( LocalTime ( & crec . start ) ) ) ;
}
}
return 0 ;
}
1997-05-20 04:32:51 +04:00
1996-06-04 10:42:03 +04:00
int main ( int argc , char * argv [ ] )
1996-05-04 11:50:46 +04:00
{
1999-12-21 07:54:30 +03:00
pstring fname ;
int c ;
static pstring servicesf = CONFIGFILE ;
extern char * optarg ;
int profile_only = 0 ;
TDB_CONTEXT * tdb ;
struct session_record * ptr ;
TimeInit ( ) ;
setup_logging ( argv [ 0 ] , True ) ;
charset_initialise ( ) ;
DEBUGLEVEL = 0 ;
dbf = stderr ;
if ( getuid ( ) ! = geteuid ( ) ) {
printf ( " smbstatus should not be run setuid \n " ) ;
return ( 1 ) ;
1998-07-24 05:08:31 +04:00
}
1999-12-21 07:54:30 +03:00
2000-01-16 14:14:44 +03:00
while ( ( c = getopt ( argc , argv , " pdLSs:u:bPB " ) ) ! = EOF ) {
1999-12-21 07:54:30 +03:00
switch ( c ) {
case ' b ' :
brief = 1 ;
1999-12-13 16:27:58 +03:00
break ;
2000-01-16 14:14:44 +03:00
case ' B ' :
show_brl = 1 ;
break ;
1999-12-21 07:54:30 +03:00
case ' d ' :
verbose = 1 ;
break ;
case ' L ' :
locks_only = 1 ;
break ;
case ' p ' :
processes_only = 1 ;
break ;
case ' P ' :
profile_only = 1 ;
break ;
case ' S ' :
shares_only = 1 ;
break ;
case ' s ' :
pstrcpy ( servicesf , optarg ) ;
break ;
2000-01-03 02:00:27 +03:00
case ' u ' :
Ucrit_addUsername ( optarg ) ;
1999-12-21 07:54:30 +03:00
break ;
default :
2000-01-03 02:00:27 +03:00
fprintf ( stderr , " Usage: %s [-P] [-d] [-L] [-p] [-S] [-s configfile] [-u username] \n " , * argv ) ;
1999-12-21 07:54:30 +03:00
return ( - 1 ) ;
1999-12-13 16:27:58 +03:00
}
1999-12-21 07:54:30 +03:00
}
if ( ! lp_load ( servicesf , False , False , False ) ) {
fprintf ( stderr , " Can't load %s - run testparm to debug it \n " , servicesf ) ;
return ( - 1 ) ;
}
if ( verbose ) {
printf ( " using configfile = %s \n " , servicesf ) ;
}
if ( profile_only ) {
return profile_dump ( ) ;
}
2001-06-04 09:13:59 +04:00
tdb = tdb_open_log ( lock_path ( " connections.tdb " ) , 0 , 0 , O_RDONLY , 0 ) ;
1999-12-21 07:54:30 +03:00
if ( ! tdb ) {
1999-12-21 12:33:45 +03:00
printf ( " connections.tdb not initialised \n " ) ;
1999-12-21 07:54:30 +03:00
if ( ! lp_status ( - 1 ) )
printf ( " You need to have status=yes in your smb config file \n " ) ;
return ( 0 ) ;
} else if ( verbose ) {
printf ( " Opened status file %s \n " , fname ) ;
}
if ( locks_only ) goto locks ;
1999-12-21 12:25:59 +03:00
printf ( " \n Samba version %s \n " , VERSION ) ;
if ( brief ) {
printf ( " PID Username Machine Time logged in \n " ) ;
printf ( " ------------------------------------------------------------------- \n " ) ;
} else {
printf ( " Service uid gid pid machine \n " ) ;
printf ( " ---------------------------------------------- \n " ) ;
}
1) added void* state argument to tdb_traverse. guess what! there were
two places i found where it was appropriate to _use_ that third argument,
in locking.c and brlock.c! there was a static traverse_function and
i removed the static variable, typecast it to a void*, passed it to
tdb_traverse and re-cast it back to the traverse_function inside the
tdb_traverse function. this makes the use of tdb_traverse() reentrant,
which is never going to happen, i know, i just don't like to see
statics lying about when there's no need for them.
as i had to do in samba-tng, all uses of tdb_traverse modified to take
the new void* state argument.
2) disabled rpcclient: referring people to use SAMBA_TNG rpcclient.
i don't know how the other samba team members would react if i deleted
rpcclient from cvs main. damn, that code's so old, it's unreal.
20 rpcclient commands, instead of about 70 in SAMBA_TNG.
(This used to be commit 49d7f0afbc1c5425d53019e234d54ddf205c8e9a)
2000-02-04 07:59:31 +03:00
tdb_traverse ( tdb , traverse_fn1 , NULL ) ;
2001-05-15 05:28:34 +04:00
tdb_close ( tdb ) ;
1999-12-21 07:54:30 +03:00
locks :
if ( processes_only ) exit ( 0 ) ;
1997-05-09 01:17:59 +04:00
1999-12-21 07:54:30 +03:00
if ( brief ) {
ptr = srecs ;
while ( ptr ! = NULL ) {
printf ( " %-8d%-10.10s%-30.30s%s " ,
( int ) ptr - > pid , uidtoname ( ptr - > uid ) ,
ptr - > machine ,
asctime ( LocalTime ( & ( ptr - > start ) ) ) ) ;
ptr = ptr - > next ;
}
printf ( " \n " ) ;
exit ( 0 ) ;
}
printf ( " \n " ) ;
if ( ! shares_only ) {
1999-12-22 04:36:27 +03:00
int ret ;
1999-12-21 07:54:30 +03:00
if ( ! locking_init ( 1 ) ) {
2000-05-04 10:29:13 +04:00
printf ( " Can't initialise locking module - exiting \n " ) ;
1999-12-21 07:54:30 +03:00
exit ( 1 ) ;
}
1999-12-22 04:36:27 +03:00
ret = share_mode_forall ( print_share_mode ) ;
if ( ret = = 0 ) {
1999-12-21 07:54:30 +03:00
printf ( " No locked files \n " ) ;
1999-12-22 04:36:27 +03:00
} else if ( ret = = - 1 ) {
printf ( " locked file list truncated \n " ) ;
}
1999-12-21 07:54:30 +03:00
printf ( " \n " ) ;
2000-01-16 14:14:44 +03:00
if ( show_brl ) {
brl_forall ( print_brl ) ;
}
1999-12-21 07:54:30 +03:00
locking_end ( ) ;
}
1997-05-20 04:32:51 +04:00
1999-12-21 07:54:30 +03:00
return ( 0 ) ;
1996-05-04 11:50:46 +04:00
}