2016-07-26 03:22:47 +03:00
# include "precompiled.h"
2016-07-04 09:07:29 +03:00
// Constructor
2017-01-13 02:04:11 +03:00
MPluginList : : MPluginList ( const char * ifile ) : m_max_loaded_count ( 0 )
2016-07-04 09:07:29 +03:00
{
// store filename of ini file
2017-01-13 02:04:11 +03:00
Q_strncpy ( m_inifile , ifile , sizeof m_inifile - 1 ) ;
m_inifile [ sizeof m_inifile - 1 ] = ' \0 ' ;
2016-07-26 03:22:47 +03:00
2016-07-04 09:07:29 +03:00
// initialize array
2017-01-13 02:04:11 +03:00
Q_memset ( m_plist , 0 , sizeof m_plist ) ;
2017-01-07 01:24:40 +03:00
for ( int i = 0 ; i < MAX_PLUGINS ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
m_plist [ i ] . m_index = i + 1 ; // 1-based
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
m_max_loaded_count = 0 ;
}
MPlugin * MPluginList : : getlist ( )
{
return m_plist ;
}
int MPluginList : : getmaxcount ( ) const
{
return m_max_loaded_count ;
2016-07-04 09:07:29 +03:00
}
// Find a plugin based on the plugin handle.
2017-01-07 01:24:40 +03:00
MPlugin * MPluginList : : find ( module_handle_t handle )
2016-07-26 03:22:47 +03:00
{
if ( ! handle )
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2017-01-13 02:04:11 +03:00
if ( handle = = m_plist [ i ] . m_sys_module . gethandle ( ) )
return & m_plist [ i ] ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 15:18:32 +03:00
// Find a plugin based on the plugin index #.
2016-07-26 19:31:47 +03:00
MPlugin * MPluginList : : find ( int pindex )
2016-07-26 03:22:47 +03:00
{
2016-07-26 15:18:32 +03:00
if ( pindex < = 0 )
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
auto pfound = & m_plist [ pindex - 1 ] ;
if ( pfound - > m_status < PL_VALID )
return nullptr ;
return pfound ;
2016-07-04 09:07:29 +03:00
}
// Find a plugin with the given plid.
2016-07-26 19:31:47 +03:00
MPlugin * MPluginList : : find ( plid_t id )
2016-07-26 03:22:47 +03:00
{
if ( ! id )
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_info = = id )
return & m_plist [ i ] ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-04 09:07:29 +03:00
}
// Find a plugin with the given pathname.
2016-07-26 19:31:47 +03:00
MPlugin * MPluginList : : find ( const char * findpath )
2016-07-26 03:22:47 +03:00
{
if ( ! findpath )
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 03:22:47 +03:00
2017-01-09 02:44:49 +03:00
META_DEBUG ( 8 , " Looking for loaded plugin with dlfnamepath: %s " , findpath ) ;
2016-07-26 15:18:32 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 9 , " Looking at: plugin %s loadedpath: %s " , m_plist [ i ] . m_file , m_plist [ i ] . m_pathname ) ;
2016-07-26 15:18:32 +03:00
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( ! Q_strcmp ( m_plist [ i ] . m_pathname , findpath ) )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 8 , " Found loaded plugin %s " , m_plist [ i ] . m_file ) ;
return & m_plist [ i ] ;
2016-07-04 09:07:29 +03:00
}
}
2016-07-26 03:22:47 +03:00
2017-01-09 02:44:49 +03:00
META_DEBUG ( 8 , " No loaded plugin found with path: %s " , findpath ) ;
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-04 09:07:29 +03:00
}
// Find a plugin that uses the given memory location.
2016-07-26 19:31:47 +03:00
MPlugin * MPluginList : : find_memloc ( void * memptr )
2016-07-26 03:22:47 +03:00
{
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + ) {
auto iplug = & m_plist [ i ] ;
2016-07-26 03:22:47 +03:00
2017-01-13 02:04:11 +03:00
if ( iplug - > m_sys_module . contain ( memptr ) )
2017-01-07 01:24:40 +03:00
return iplug ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2017-01-07 01:24:40 +03:00
return nullptr ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
// Find a plugin with non-ambiguous prefix string matching desc, file,
2016-07-04 09:07:29 +03:00
// name, or logtag.
2017-01-13 02:04:11 +03:00
MPlugin * MPluginList : : find_match ( const char * prefix , bool & unique )
2016-07-26 03:22:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( ! prefix ) {
return nullptr ;
2016-07-26 19:31:47 +03:00
}
2017-01-13 02:04:11 +03:00
MPlugin * pfound = nullptr ;
size_t len = Q_strlen ( prefix ) ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
{
auto plug = & m_plist [ i ] ;
if ( plug - > m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( plug - > m_info & & ! Q_strnicmp ( plug - > m_info - > name , prefix , len )
| | ! Q_strnicmp ( plug - > m_desc , prefix , len )
| | ! Q_strnicmp ( plug - > m_file , prefix , len )
| | plug - > m_info & & ! Q_strnicmp ( plug - > m_info - > logtag , prefix , len ) )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( pfound ) {
unique = false ;
break ;
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
pfound = plug ;
unique = true ;
2016-07-04 09:07:29 +03:00
}
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
return pfound ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
// Find a plugin with same file, logtag, desc or significant
2016-07-04 09:07:29 +03:00
// prefix of file. Uses the platform_match() method of MPlugin.
2016-07-26 19:31:47 +03:00
MPlugin * MPluginList : : find_match ( MPlugin * pmatch )
2016-07-26 03:22:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( ! pmatch ) {
return nullptr ;
2016-07-26 19:31:47 +03:00
}
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
auto plug = & m_plist [ i ] ;
if ( pmatch - > platform_match ( plug ) ) {
return plug ;
2016-07-04 09:07:29 +03:00
}
}
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 15:18:32 +03:00
MPlugin * MPluginList : : plugin_addload ( plid_t plid , const char * fname , PLUG_LOADTIME now )
{
2017-01-13 02:04:11 +03:00
auto pl_loader = find ( plid ) ;
if ( ! pl_loader ) {
2017-01-09 02:44:49 +03:00
META_DEBUG ( 1 , " Couldn't find plugin that gave this loading request! " ) ;
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
MPlugin pl_temp = { } ;
if ( ! pl_temp . plugin_parseline ( fname , pl_loader - > m_index ) ) {
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
if ( pl_temp . resolve ( ) ! = true ) {
META_DEBUG ( 1 , " Couldn't resolve given path into a file: %s " , pl_temp . m_file ) ;
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
auto pl_found = find ( pl_temp . m_pathname ) ;
if ( ! pl_found )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Plugin '%s' already in current list; file=%s desc='%s' " , pl_temp . m_file , pl_found - > m_file , pl_found - > m_desc ) ;
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
auto pl_added = add ( & pl_temp ) ;
if ( ! pl_added )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Couldn't add plugin '%s' to list; see log " , pl_temp . m_desc ) ;
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
pl_added - > m_action = PA_LOAD ;
2016-07-26 19:31:47 +03:00
if ( ! pl_added - > load ( now ) )
{
2017-01-13 02:04:11 +03:00
if ( pl_added - > m_status = = PL_OPENED )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Opened plugin '%s', but failed to attach; see log " , pl_added - > m_desc ) ;
2016-07-26 15:18:32 +03:00
}
2016-07-26 19:31:47 +03:00
else
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Couldn't load plugin '%s'; see log " , pl_added - > m_desc ) ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
return nullptr ;
2016-07-26 15:18:32 +03:00
}
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Loaded plugin '%s' successfully " , pl_added - > m_desc ) ;
2016-07-26 15:18:32 +03:00
return pl_added ;
}
2017-01-07 01:24:40 +03:00
MPlugin * MPluginList : : find_empty_slot ( )
{
for ( int i = 0 ; i < MAX_PLUGINS ; i + + ) {
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status = = PL_EMPTY ) {
if ( i > m_max_loaded_count )
m_max_loaded_count = i + 1 ;
2017-01-07 01:24:40 +03:00
2017-01-13 02:04:11 +03:00
return & m_plist [ i ] ;
2017-01-07 01:24:40 +03:00
}
}
return nullptr ;
}
2016-07-04 09:07:29 +03:00
// Add a plugin to the list.
2016-07-26 15:18:32 +03:00
MPlugin * MPluginList : : add ( MPlugin * padd )
2016-07-26 03:22:47 +03:00
{
2017-01-07 01:24:40 +03:00
auto iplug = find_empty_slot ( ) ;
2016-07-04 09:07:29 +03:00
// couldn't find a slot to use
2017-01-07 01:24:40 +03:00
if ( ! iplug )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " Couldn't add plugin '%s' to list; reached max plugins (%d) " , padd - > m_file , MAX_PLUGINS ) ;
2017-01-07 21:03:16 +03:00
return NULL ;
2016-07-04 09:07:29 +03:00
}
// copy filename into this free slot
2017-01-13 02:04:11 +03:00
Q_strncpy ( iplug - > m_filename , padd - > m_filename , sizeof iplug - > m_filename - 1 ) ;
iplug - > m_filename [ sizeof iplug - > m_filename - 1 ] = ' \0 ' ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// Copy file offset ptr.
// Can't just copy ptr, as it points to offset in padd, which will go
// away; need to point to corresponding offset in iplug.
2017-01-13 02:04:11 +03:00
iplug - > m_file = iplug - > m_filename + ( padd - > m_file - padd - > m_filename ) ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// copy description
2017-01-13 02:04:11 +03:00
Q_strncpy ( iplug - > m_desc , padd - > m_desc , sizeof iplug - > m_desc - 1 ) ;
iplug - > m_desc [ sizeof iplug - > m_desc - 1 ] = ' \0 ' ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// copy pathname
2017-01-13 02:04:11 +03:00
Q_strncpy ( iplug - > m_pathname , padd - > m_pathname , sizeof iplug - > m_pathname - 1 ) ;
iplug - > m_pathname [ sizeof iplug - > m_pathname - 1 ] = ' \0 ' ;
normalize_pathname ( iplug - > m_pathname ) ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
iplug - > m_source = padd - > m_source ;
iplug - > m_status = padd - > m_status ;
iplug - > m_source_plugin_index = padd - > m_source_plugin_index ;
2016-07-04 09:07:29 +03:00
2016-07-26 03:22:47 +03:00
return iplug ;
}
2016-07-04 09:07:29 +03:00
2016-07-26 15:18:32 +03:00
2016-07-04 09:07:29 +03:00
// Read plugins.ini at server startup.
2016-07-30 02:03:01 +03:00
bool MPluginList : : ini_startup ( )
2016-07-26 03:22:47 +03:00
{
2016-07-26 19:31:47 +03:00
FILE * fp ;
2016-07-04 09:07:29 +03:00
char line [ MAX_STRBUF_LEN ] ;
int n , ln ;
2016-07-26 19:31:47 +03:00
MPlugin * pmatch ;
2016-07-26 15:18:32 +03:00
2017-01-13 02:04:11 +03:00
if ( ! valid_gamedir_file ( m_inifile ) )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Metamod plugins file empty or missing: %s " , m_inifile ) ;
2017-01-07 21:03:16 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
2017-01-13 02:04:11 +03:00
full_gamedir_path ( m_inifile , m_inifile ) ;
fp = fopen ( m_inifile , " r " ) ;
2016-07-26 19:31:47 +03:00
if ( ! fp )
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Unable to open plugins file '%s': %s " , m_inifile , strerror ( errno ) ) ;
2017-01-07 21:03:16 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Begin reading plugins list: %s " , m_inifile ) ;
2017-01-07 01:24:40 +03:00
for ( n = 0 , ln = 1 ; ! feof ( fp ) & & fgets ( line , sizeof ( line ) , fp ) & & n < MAX_PLUGINS ; ln + + )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Remove line terminations.
2016-07-26 15:18:32 +03:00
char * cp ;
2016-07-26 19:31:47 +03:00
if ( ( cp = Q_strrchr ( line , ' \r ' ) ) )
2016-07-26 03:22:47 +03:00
* cp = ' \0 ' ;
2016-07-26 19:31:47 +03:00
if ( ( cp = Q_strrchr ( line , ' \n ' ) ) )
2016-07-26 03:22:47 +03:00
* cp = ' \0 ' ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// Parse directly into next entry in array
2017-01-13 02:04:11 +03:00
if ( ! m_plist [ n ] . ini_parseline ( line ) )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Skipping malformed line %d of %s " , ln , m_inifile ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
// Check for a duplicate - an existing entry with this pathname.
2017-01-13 02:04:11 +03:00
if ( find ( m_plist [ n ] . m_pathname ) )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Should we check platform specific level here?
2017-01-13 02:04:11 +03:00
META_INFO ( " ini: Skipping duplicate plugin, line %d of %s: %s " , ln , m_inifile , m_plist [ n ] . m_pathname ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// Check for a matching platform with different platform specifics
// level.
2017-01-13 02:04:11 +03:00
if ( NULL ! = ( pmatch = find_match ( & m_plist [ n ] ) ) )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( pmatch - > m_pfspecific > = m_plist [ n ] . m_pfspecific )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d) " , ln , m_inifile , pmatch - > m_pfspecific , m_plist [ n ] . m_pfspecific ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d " , ln , pmatch - > m_pfspecific , m_plist [ n ] . m_pfspecific ) ;
int _index = pmatch - > m_index ;
2016-07-26 19:31:47 +03:00
Q_memset ( pmatch , 0 , sizeof ( MPlugin ) ) ;
2017-01-13 02:04:11 +03:00
pmatch - > m_index = _index ;
2016-07-04 09:07:29 +03:00
}
2017-01-13 02:04:11 +03:00
m_plist [ n ] . m_action = PA_LOAD ;
META_LOG ( " ini: Read plugin config for: %s " , m_plist [ n ] . m_desc ) ;
2016-07-04 09:07:29 +03:00
n + + ;
2017-01-13 02:04:11 +03:00
m_max_loaded_count = n ; // mark end of list
2016-07-04 09:07:29 +03:00
}
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Finished reading plugins list: %s; Found %d plugins to load " , m_inifile , n ) ;
2016-07-04 09:07:29 +03:00
fclose ( fp ) ;
2016-07-26 19:31:47 +03:00
if ( ! n )
{
2016-07-26 15:18:32 +03:00
META_ERROR ( " ini: Warning; no plugins found to load? " ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2016-07-30 02:03:01 +03:00
return true ;
2016-07-04 09:07:29 +03:00
}
// Re-read plugins.ini looking for added/deleted/changed plugins.
2016-07-30 02:03:01 +03:00
bool MPluginList : : ini_refresh ( )
2016-07-26 03:22:47 +03:00
{
2016-07-26 19:31:47 +03:00
FILE * fp ;
2016-07-04 09:07:29 +03:00
char line [ MAX_STRBUF_LEN ] ;
int n , ln ;
MPlugin pl_temp ;
MPlugin * pl_found , * pl_added ;
2017-01-13 02:04:11 +03:00
fp = fopen ( m_inifile , " r " ) ;
2016-07-26 19:31:47 +03:00
if ( ! fp )
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Unable to open plugins file '%s': %s " , m_inifile , strerror ( errno ) ) ;
2017-01-07 21:03:16 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Begin re-reading plugins list: %s " , m_inifile ) ;
2017-01-07 01:24:40 +03:00
for ( n = 0 , ln = 1 ; ! feof ( fp ) & & fgets ( line , sizeof ( line ) , fp ) & & n < MAX_PLUGINS ; ln + + )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Remove line terminations.
2016-07-26 19:31:47 +03:00
char * cp ;
if ( ( cp = Q_strrchr ( line , ' \r ' ) ) )
2016-07-26 03:22:47 +03:00
* cp = ' \0 ' ;
2016-07-26 19:31:47 +03:00
if ( ( cp = Q_strrchr ( line , ' \n ' ) ) )
2016-07-26 03:22:47 +03:00
* cp = ' \0 ' ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
// Parse into a temp plugin
2016-07-26 19:31:47 +03:00
Q_memset ( & pl_temp , 0 , sizeof ( pl_temp ) ) ;
if ( ! pl_temp . ini_parseline ( line ) )
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Skipping malformed line %d of %s " , ln , m_inifile ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
// Try to find plugin with this pathname in the current list of
// plugins.
2017-01-13 02:04:11 +03:00
if ( ! ( pl_found = find ( pl_temp . m_pathname ) ) )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Check for a matching platform with higher platform specifics
// level.
2016-07-26 19:31:47 +03:00
if ( NULL ! = ( pl_found = find_match ( & pl_temp ) ) )
{
2017-01-13 02:04:11 +03:00
if ( pl_found - > m_pfspecific > = pl_temp . m_pfspecific )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d) " , ln , m_inifile , pl_found - > m_pfspecific , pl_temp . m_pfspecific ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
2017-01-13 02:04:11 +03:00
if ( PA_LOAD = = pl_found - > m_action )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d " , ln , pl_found - > m_pfspecific , pl_temp . m_pfspecific ) ;
int _index = pl_found - > m_index ;
2016-07-26 19:31:47 +03:00
Q_memset ( pl_found , 0 , sizeof ( MPlugin ) ) ;
2017-01-13 02:04:11 +03:00
pl_found - > m_index = _index ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
else
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " ini: Plugin in line %d should override existing plugin with lower platform specific level %d, ours %d. Unable to comply. " , ln , pl_found - > m_pfspecific , pl_temp . m_pfspecific ) ;
2016-07-04 09:07:29 +03:00
continue ;
}
}
// new plugin; add to list
2016-07-26 19:31:47 +03:00
if ( ( pl_added = add ( & pl_temp ) ) )
{
2016-07-04 09:07:29 +03:00
// try to load this plugin at the next opportunity
2017-01-13 02:04:11 +03:00
pl_added - > m_action = PA_LOAD ;
2016-07-04 09:07:29 +03:00
}
else
2016-07-26 15:18:32 +03:00
// error details logged in add()
2016-07-04 09:07:29 +03:00
continue ;
}
2016-07-26 19:31:47 +03:00
else
{
2016-07-04 09:07:29 +03:00
// This plugin is already in the current list of plugins.
// Pathname already matches. Recopy desc, if specified in
// plugins.ini.
2017-01-13 02:04:11 +03:00
if ( pl_temp . m_desc [ 0 ] ! = ' < ' )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
Q_strncpy ( pl_found - > m_desc , pl_temp . m_desc , sizeof pl_found - > m_desc - 1 ) ;
pl_found - > m_desc [ sizeof pl_found - > m_desc - 1 ] = ' \0 ' ;
2016-07-26 03:22:47 +03:00
}
2016-07-04 09:07:29 +03:00
// Check the file to see if it looks like it's been modified
// since we last loaded it.
2016-07-26 19:31:47 +03:00
if ( ! pl_found - > newer_file ( ) )
{
2017-01-13 02:04:11 +03:00
pl_found - > m_action = PA_KEEP ;
2016-07-04 09:07:29 +03:00
}
// Newer file on disk.
2017-01-13 02:04:11 +03:00
else if ( pl_found - > m_status > = PL_OPENED )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 2 , " ini: Plugin '%s' has newer file on disk " , pl_found - > m_desc ) ;
pl_found - > m_action = PA_RELOAD ;
2016-07-04 09:07:29 +03:00
}
else
2017-01-13 02:04:11 +03:00
META_ERROR ( " ini: Plugin '%s' has newer file, but unexpected status (%s) " , pl_found - > m_desc , pl_found - > str_status ( ) ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
if ( pl_found )
{
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Read plugin config for: %s " , pl_found - > m_desc ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
else
{
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Read plugin config for: %s " , pl_temp . m_desc ) ;
2016-07-04 09:07:29 +03:00
}
n + + ;
}
2017-01-13 02:04:11 +03:00
META_LOG ( " ini: Finished reading plugins list: %s; Found %d plugins " , m_inifile , n ) ;
2016-07-04 09:07:29 +03:00
fclose ( fp ) ;
2016-07-26 19:31:47 +03:00
if ( ! n )
{
2016-07-26 15:18:32 +03:00
META_ERROR ( " ini: Warning; no plugins found to load? " ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2016-07-30 02:03:01 +03:00
return true ;
2016-07-04 09:07:29 +03:00
}
// Load a plugin from a console command.
2016-07-30 02:03:01 +03:00
bool MPluginList : : cmd_addload ( const char * args )
2016-07-26 03:22:47 +03:00
{
2016-07-30 02:03:01 +03:00
MPlugin pl_temp = { } ;
2016-07-04 09:07:29 +03:00
MPlugin * pl_found , * pl_added ;
2016-07-26 03:22:47 +03:00
2016-07-30 02:03:01 +03:00
if ( pl_temp . cmd_parseline ( args ) ! = true )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
META_CONS ( " Couldn't parse 'meta load' arguments: %s " , args ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
// resolve given path into a file; accepts various "shortcut"
// pathnames.
2016-07-30 02:03:01 +03:00
if ( pl_temp . resolve ( ) ! = true )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Couldn't find a matching file on disk
2017-01-13 02:04:11 +03:00
META_CONS ( " Couldn't resolve given path into a file: %s " , pl_temp . m_file ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
// Try to find plugin with this pathname in the current list of
// plugins.
2017-01-13 02:04:11 +03:00
if ( ( pl_found = find ( pl_temp . m_pathname ) ) )
2016-07-26 19:31:47 +03:00
{
2016-07-04 09:07:29 +03:00
// Already in list
2017-01-13 02:04:11 +03:00
META_CONS ( " Plugin '%s' already in current list; file=%s desc='%s' " , pl_temp . m_file , pl_found - > m_file , pl_found - > m_desc ) ;
2017-01-07 21:03:16 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
// new plugin; add to list
2016-07-26 19:31:47 +03:00
if ( ! ( pl_added = add ( & pl_temp ) ) )
{
2017-01-13 02:04:11 +03:00
META_CONS ( " Couldn't add plugin '%s' to list; see log " , pl_temp . m_desc ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
// try to load new plugin
2017-01-13 02:04:11 +03:00
pl_added - > m_action = PA_LOAD ;
2016-07-26 19:31:47 +03:00
if ( ! pl_added - > load ( PT_ANYTIME ) )
{
2016-07-04 09:07:29 +03:00
// load failed
2017-01-13 02:04:11 +03:00
if ( pl_added - > m_status = = PL_OPENED )
META_CONS ( " Opened plugin '%s', but failed to attach; see log " , pl_added - > m_desc ) ;
2016-07-04 09:07:29 +03:00
else
2017-01-13 02:04:11 +03:00
META_CONS ( " Couldn't load plugin '%s'; see log " , pl_added - > m_desc ) ;
2016-07-26 19:31:47 +03:00
2016-07-26 15:18:32 +03:00
show ( 0 ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
META_CONS ( " Loaded plugin '%s' successfully " , pl_added - > m_desc ) ;
2016-07-30 02:03:01 +03:00
META_CONS ( " Rebuilding callbacks... " ) ;
meta_rebuild_callbacks ( ) ;
2016-07-26 15:18:32 +03:00
show ( 0 ) ;
2016-07-26 19:31:47 +03:00
2016-07-30 02:03:01 +03:00
return true ;
2016-07-04 09:07:29 +03:00
}
// Load plugins at startup.
2016-07-30 02:03:01 +03:00
bool MPluginList : : load ( )
2016-07-26 03:22:47 +03:00
{
2016-07-26 19:31:47 +03:00
int n = 0 ;
if ( ! ini_startup ( ) )
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " Problem loading plugins.ini: %s " , m_inifile ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
META_LOG ( " dll: Loading plugins... " ) ;
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . load ( PT_STARTUP ) = = true )
2016-07-04 09:07:29 +03:00
n + + ;
else
2016-07-26 19:31:47 +03:00
// all plugins should be loadable at startup...
2017-01-13 02:04:11 +03:00
META_ERROR ( " dll: Failed to load plugin '%s' " , m_plist [ i ] . m_file ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2016-07-30 02:03:01 +03:00
META_LOG ( " dll: Rebuilding callbacks... " ) ;
meta_rebuild_callbacks ( ) ;
2016-07-04 09:07:29 +03:00
META_LOG ( " dll: Finished loading %d plugins " , n ) ;
2016-07-30 02:03:01 +03:00
return true ;
2016-07-04 09:07:29 +03:00
}
// Update list of loaded plugins from ini file, and load any new/changed plugins.
2016-07-30 02:03:01 +03:00
bool MPluginList : : refresh ( PLUG_LOADTIME now )
2016-07-26 03:22:47 +03:00
{
int i , ndone = 0 , nkept = 0 , nloaded = 0 , nunloaded = 0 , nreloaded = 0 , ndelayed = 0 ;
2016-07-26 15:18:32 +03:00
MPlugin * iplug ;
2016-07-04 09:07:29 +03:00
2016-07-26 19:31:47 +03:00
if ( ! ini_refresh ( ) )
{
2017-01-13 02:04:11 +03:00
META_ERROR ( " dll: Problem reloading plugins.ini: %s " , m_inifile ) ;
2016-07-30 02:03:01 +03:00
return false ;
2016-07-04 09:07:29 +03:00
}
META_LOG ( " dll: Updating plugins... " ) ;
2017-01-13 02:04:11 +03:00
for ( i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
iplug = & m_plist [ i ] ;
if ( iplug - > m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
switch ( iplug - > m_action )
2016-07-26 19:31:47 +03:00
{
2016-07-26 03:22:47 +03:00
case PA_KEEP :
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Keeping plugin '%s' " , iplug - > m_desc ) ;
iplug - > m_action = PA_NONE ;
2016-07-26 03:22:47 +03:00
nkept + + ;
break ;
case PA_LOAD :
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Loading plugin '%s' " , iplug - > m_desc ) ;
2016-07-26 03:22:47 +03:00
if ( iplug - > load ( now ) )
nloaded + + ;
2017-01-13 02:04:11 +03:00
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed + + ; */
2016-07-26 03:22:47 +03:00
break ;
case PA_RELOAD :
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Reloading plugin '%s' " , iplug - > m_desc ) ;
2016-07-26 03:22:47 +03:00
if ( iplug - > reload ( now , PNL_FILE_NEWER ) )
nreloaded + + ;
2017-01-13 02:04:11 +03:00
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed + + ; */
2016-07-26 03:22:47 +03:00
break ;
case PA_NONE :
// If previously loaded from ini, but apparently removed from new ini.
2017-01-13 02:04:11 +03:00
if ( iplug - > m_source = = PS_INI & & iplug - > m_status > = PL_RUNNING )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Unloading plugin '%s' " , iplug - > m_desc ) ;
iplug - > m_action = PA_UNLOAD ;
2016-07-26 03:22:47 +03:00
if ( iplug - > unload ( now , PNL_INI_DELETED , PNL_INI_DELETED ) )
2016-07-04 09:07:29 +03:00
nunloaded + + ;
2017-01-13 02:04:11 +03:00
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed + + ; */
2016-07-26 03:22:47 +03:00
}
break ;
case PA_ATTACH :
// Previously requested attach, but was delayed?
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Retrying attach plugin '%s' " , iplug - > m_desc ) ;
2016-07-26 03:22:47 +03:00
if ( iplug - > retry ( now , PNL_DELAYED ) )
nloaded + + ;
2017-01-13 02:04:11 +03:00
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed + + ; */
2016-07-26 03:22:47 +03:00
break ;
case PA_UNLOAD :
// Previously requested unload, but was delayed?
2017-01-13 02:04:11 +03:00
META_DEBUG ( 1 , " Retrying unload plugin '%s' " , iplug - > m_desc ) ;
2016-07-26 03:22:47 +03:00
if ( iplug - > retry ( now , PNL_DELAYED ) )
nunloaded + + ;
2017-01-13 02:04:11 +03:00
/*else if (meta_errno == ME_DELAYED) TODO
ndelayed + + ; */
2016-07-26 03:22:47 +03:00
break ;
case PA_NULL :
2017-01-13 02:04:11 +03:00
META_ERROR ( " dll: Unexpected action for plugin '%s': '%s' " , iplug - > m_desc , iplug - > str_action ( ) ) ;
2016-07-26 03:22:47 +03:00
break ;
default :
2017-01-13 02:04:11 +03:00
META_ERROR ( " dll: Unrecognized action for plugin '%s': '%s' " , iplug - > m_desc , iplug - > str_action ( ) ) ;
2016-07-26 03:22:47 +03:00
break ;
2016-07-04 09:07:29 +03:00
}
ndone + + ;
}
2016-07-26 19:31:47 +03:00
2016-07-30 02:03:01 +03:00
META_LOG ( " dll: Rebuilding callbacks... " ) ;
meta_rebuild_callbacks ( ) ;
2016-07-26 19:31:47 +03:00
META_LOG ( " dll: Finished updating %d plugins; kept %d, loaded %d, unloaded %d, reloaded %d, delayed %d " , ndone , nkept , nloaded , nunloaded , nreloaded , ndelayed ) ;
2016-07-30 02:03:01 +03:00
return true ;
2016-07-04 09:07:29 +03:00
}
// Re-enable any plugins currently paused.
2016-07-26 15:18:32 +03:00
void MPluginList : : unpause_all ( void )
2016-07-26 03:22:47 +03:00
{
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
auto iplug = & m_plist [ i ] ;
if ( iplug - > m_status = = PL_PAUSED )
2016-07-04 09:07:29 +03:00
iplug - > unpause ( ) ;
}
}
// Retry any pending actions on plugins, for instance load/unload delayed
// until changelevel.
2016-07-26 03:22:47 +03:00
void MPluginList : : retry_all ( PLUG_LOADTIME now )
{
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
auto iplug = & m_plist [ i ] ;
if ( iplug - > m_action ! = PA_NONE )
2016-07-04 09:07:29 +03:00
iplug - > retry ( now , PNL_DELAYED ) ;
}
}
// List plugins and information about them in a formatted table.
2016-07-26 03:22:47 +03:00
void MPluginList : : show ( int source_index )
{
2016-07-26 19:31:47 +03:00
int n = 0 , r = 0 ;
MPlugin * pl ;
char desc [ 15 + 1 ] , file [ 16 + 1 ] , vers [ 7 + 1 ] ; // plus 1 for term null
2016-07-26 03:22:47 +03:00
if ( source_index < = 0 )
2016-07-04 09:07:29 +03:00
META_CONS ( " Currently loaded plugins: " ) ;
else
META_CONS ( " Child plugins: " ) ;
2016-07-26 03:22:47 +03:00
2016-07-26 19:31:47 +03:00
META_CONS ( " %*s %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s " , WIDTH_MAX_PLUGINS , " " , sizeof ( desc ) - 1 , " description " , " stat " , " pend " ,
sizeof ( file ) - 1 , " file " , sizeof ( vers ) - 1 , " ers " , 2 + WIDTH_MAX_PLUGINS , " src " , " load " , " unlod " ) ;
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
pl = & m_plist [ i ] ;
if ( pl - > m_status < PL_VALID )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( source_index > 0 & & pl - > m_source_plugin_index ! = source_index )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
Q_strncpy ( desc , pl - > m_desc , sizeof ( desc ) - 1 ) ;
2016-07-26 19:31:47 +03:00
desc [ sizeof ( desc ) - 1 ] = ' \0 ' ;
2017-01-13 02:04:11 +03:00
Q_strncpy ( file , pl - > m_file , sizeof ( file ) - 1 ) ;
2016-07-26 19:31:47 +03:00
file [ sizeof ( file ) - 1 ] = ' \0 ' ;
2017-01-13 02:04:11 +03:00
if ( pl - > m_info & & pl - > m_info - > version )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
Q_strncpy ( vers , pl - > m_info - > version , sizeof ( vers ) - 1 ) ;
2016-07-26 19:31:47 +03:00
vers [ sizeof ( vers ) - 1 ] = ' \0 ' ;
2016-07-26 03:22:47 +03:00
}
2016-07-26 19:31:47 +03:00
else
{
Q_strncpy ( vers , " - " , sizeof ( vers ) - 1 ) ;
vers [ sizeof ( vers ) - 1 ] = ' \0 ' ;
2016-07-26 03:22:47 +03:00
}
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
META_CONS ( " [%*d] %-*s %-4s %-4s %-*s v%-*s %-*s %-5s %-5s " , WIDTH_MAX_PLUGINS , pl - > m_index ,
2016-07-26 19:31:47 +03:00
sizeof ( desc ) - 1 , desc , pl - > str_status ( ST_SHOW ) , pl - > str_action ( SA_SHOW ) , sizeof ( file ) - 1 , file , sizeof ( vers ) - 1 , vers ,
2 + WIDTH_MAX_PLUGINS , pl - > str_source ( SO_SHOW ) , pl - > str_loadable ( SL_SHOW ) , pl - > str_unloadable ( SL_SHOW ) ) ;
2017-01-13 02:04:11 +03:00
if ( pl - > m_status = = PL_RUNNING )
2016-07-04 09:07:29 +03:00
r + + ;
n + + ;
}
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
META_CONS ( " %d plugins, %d running " , n , r ) ;
}
// List plugins and information to Player/client entity. Differs from the
// "meta list" console command in that:
// - Shows only "running" plugins, skipping any failed or paused plugins.
2016-07-26 19:31:47 +03:00
// - Limited info about each plugin, mostly the "public" info (name, author,
2016-07-04 09:07:29 +03:00
// etc).
2016-07-26 19:31:47 +03:00
void MPluginList : : show_client ( edict_t * pEntity )
2016-07-26 03:22:47 +03:00
{
2016-07-26 19:31:47 +03:00
int n = 0 ;
MPlugin * pl ;
2016-07-04 09:07:29 +03:00
META_CLIENT ( pEntity , " Currently running plugins: " ) ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
pl = & m_plist [ i ] ;
if ( pl - > m_status ! = PL_RUNNING | | ! pl - > m_info )
2016-07-04 09:07:29 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
n + + ;
2016-07-26 19:31:47 +03:00
META_CLIENT ( pEntity , " [%3d] %s, v%s, %s, by %s, see %s " , n ,
2017-01-13 02:04:11 +03:00
pl - > m_info - > name ? pl - > m_info - > name : " <unknown> " ,
pl - > m_info - > version ? pl - > m_info - > version : " <?> " ,
pl - > m_info - > date ? pl - > m_info - > date : " <../../..> " ,
pl - > m_info - > author ? pl - > m_info - > author : " <unknown> " ,
pl - > m_info - > url ? pl - > m_info - > url : " <unknown> " ) ;
2016-07-04 09:07:29 +03:00
}
2016-07-26 19:31:47 +03:00
2016-07-04 09:07:29 +03:00
META_CLIENT ( pEntity , " %d plugins " , n ) ;
}
2016-07-26 15:18:32 +03:00
2016-07-30 02:03:01 +03:00
bool MPluginList : : found_child_plugins ( int source_index ) const
2016-07-26 15:18:32 +03:00
{
if ( source_index < = 0 )
2016-07-30 02:03:01 +03:00
return false ;
2016-07-26 15:18:32 +03:00
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-26 15:18:32 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_source_plugin_index = = source_index )
2016-07-30 02:03:01 +03:00
return true ;
2016-07-26 15:18:32 +03:00
}
2016-07-30 02:03:01 +03:00
return false ;
2016-07-26 15:18:32 +03:00
}
void MPluginList : : clear_source_plugin_index ( int source_index )
{
if ( source_index < = 0 )
return ;
2017-01-13 02:04:11 +03:00
for ( int i = 0 ; i < m_max_loaded_count ; i + + )
2016-07-26 19:31:47 +03:00
{
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_status < PL_VALID )
2016-07-26 15:18:32 +03:00
continue ;
2016-07-26 19:31:47 +03:00
2017-01-13 02:04:11 +03:00
if ( m_plist [ i ] . m_source_plugin_index = = source_index )
m_plist [ i ] . m_source_plugin_index = - 1 ;
2016-07-26 15:18:32 +03:00
}
}