1999-04-01 09:35:22 +04:00
/*
Unix SMB / Netbios implementation .
Version 1.9 .
store smbd profiling information in shared memory
Copyright ( C ) Andrew Tridgell 1999
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"
2000-05-10 15:08:08 +04:00
# include <sys/shm.h>
1999-04-01 09:35:22 +04:00
extern int DEBUGLEVEL ;
# define IPC_PERMS ((SHM_R | SHM_W) | (SHM_R>>3) | (SHM_R>>6))
static int shm_id ;
static BOOL read_only ;
struct profile_struct * profile_p ;
2000-10-06 22:13:52 +04:00
BOOL do_profile_flag = False ;
2000-10-07 03:01:47 +04:00
BOOL do_profile_times = False ;
2000-10-06 22:13:52 +04:00
struct timeval profile_starttime ;
struct timeval profile_endtime ;
2000-10-07 03:01:47 +04:00
/****************************************************************************
receive a set profile level message
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void profile_message ( int msg_type , pid_t src , void * buf , size_t len )
{
int level ;
memcpy ( & level , buf , sizeof ( int ) ) ;
switch ( level ) {
case 0 :
do_profile_flag = False ;
do_profile_times = False ;
break ;
case 1 :
do_profile_flag = True ;
do_profile_times = False ;
break ;
case 2 :
do_profile_flag = True ;
do_profile_times = True ;
break ;
}
DEBUG ( 1 , ( " Profile level set to %d from pid %d \n " , level , ( int ) src ) ) ;
}
1999-04-01 09:35:22 +04:00
/*******************************************************************
open the profiling shared memory area
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
BOOL profile_setup ( BOOL rdonly )
{
struct shmid_ds shm_ds ;
read_only = rdonly ;
again :
/* try to use an existing key */
1999-12-13 16:27:58 +03:00
shm_id = shmget ( PROF_SHMEM_KEY , 0 , 0 ) ;
1999-04-01 09:35:22 +04:00
/* if that failed then create one. There is a race condition here
if we are running from inetd . Bad luck . */
if ( shm_id = = - 1 ) {
if ( read_only ) return False ;
1999-12-13 16:27:58 +03:00
shm_id = shmget ( PROF_SHMEM_KEY , sizeof ( * profile_p ) ,
1999-04-01 09:35:22 +04:00
IPC_CREAT | IPC_EXCL | IPC_PERMS ) ;
}
if ( shm_id = = - 1 ) {
DEBUG ( 0 , ( " Can't create or use IPC area. Error was %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
profile_p = ( struct profile_struct * ) shmat ( shm_id , 0 ,
read_only ? SHM_RDONLY : 0 ) ;
if ( ( long ) profile_p = = - 1 ) {
DEBUG ( 0 , ( " Can't attach to IPC area. Error was %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
/* find out who created this memory area */
if ( shmctl ( shm_id , IPC_STAT , & shm_ds ) ! = 0 ) {
DEBUG ( 0 , ( " ERROR shmctl : can't IPC_STAT. Error was %s \n " ,
strerror ( errno ) ) ) ;
return False ;
}
if ( shm_ds . shm_perm . cuid ! = 0 | | shm_ds . shm_perm . cgid ! = 0 ) {
DEBUG ( 0 , ( " ERROR: root did not create the shmem \n " ) ) ;
return False ;
}
if ( shm_ds . shm_segsz ! = sizeof ( * profile_p ) ) {
DEBUG ( 0 , ( " WARNING: profile size is %d (expected %d). Deleting \n " ,
( int ) shm_ds . shm_segsz , sizeof ( * profile_p ) ) ) ;
if ( shmctl ( shm_id , IPC_RMID , & shm_ds ) = = 0 ) {
goto again ;
} else {
return False ;
}
}
if ( ! read_only & & ( shm_ds . shm_nattch = = 1 ) ) {
memset ( ( char * ) profile_p , 0 , sizeof ( * profile_p ) ) ;
1999-12-13 16:27:58 +03:00
profile_p - > prof_shm_magic = PROF_SHM_MAGIC ;
profile_p - > prof_shm_version = PROF_SHM_VERSION ;
1999-04-01 09:35:22 +04:00
DEBUG ( 3 , ( " Initialised profile area \n " ) ) ;
}
2000-10-07 03:01:47 +04:00
message_register ( MSG_PROFILE , profile_message ) ;
1999-04-01 09:35:22 +04:00
return True ;
}