2016-07-26 15:18:32 +03:00
|
|
|
// vi: set ts=4 sw=4 :
|
|
|
|
// vim: set tw=75 :
|
|
|
|
|
|
|
|
// mlist.cpp - functions for list of plugins (class MPluginList)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (c) 2001-2003 Will Day <willday@hpgx.net>
|
|
|
|
*
|
|
|
|
* This file is part of Metamod.
|
|
|
|
*
|
|
|
|
* Metamod 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.
|
|
|
|
*
|
|
|
|
* Metamod 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 Metamod; if not, write to the Free Software Foundation,
|
|
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* In addition, as a special exception, the author gives permission to
|
|
|
|
* link the code of this program with the Half-Life Game g_engine ("HL
|
|
|
|
* g_engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
|
|
* respects for all of the code used other than the HL g_engine and MODs
|
|
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
|
|
* you do not wish to do so, delete this exception statement from your
|
|
|
|
* version.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
#include "precompiled.h"
|
2016-07-04 09:07:29 +03:00
|
|
|
|
|
|
|
// Constructor
|
2016-07-26 15:18:32 +03:00
|
|
|
MPluginList::MPluginList(const char* ifile) : size(MAX_PLUGINS), endlist(0)
|
2016-07-04 09:07:29 +03:00
|
|
|
{
|
|
|
|
// store filename of ini file
|
2016-07-26 15:18:32 +03:00
|
|
|
strncpy(inifile, ifile, sizeof inifile - 1);
|
|
|
|
inifile[sizeof inifile - 1] = '\0';
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
// initialize array
|
2016-07-26 15:18:32 +03:00
|
|
|
memset(plist, 0, sizeof(plist));
|
|
|
|
for (int i = 0; i < size; i++) {
|
|
|
|
plist[i].index = i + 1; // 1-based
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
endlist = 0;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find a plugin based on the plugin handle.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT invalid pindex
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find(DLHANDLE handle)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
|
|
|
if (!handle)
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
for (int i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].handle == handle)
|
|
|
|
return &plist[i];
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
// Find a plugin based on the plugin index #.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT invalid pindex
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
|
|
|
MPlugin* MPluginList::find(int pindex)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
if (pindex <= 0)
|
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
auto pfound = &plist[pindex - 1];
|
|
|
|
if (pfound->status < PL_VALID)
|
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
else
|
|
|
|
return pfound;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Find a plugin with the given plid.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT null plid_t
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find(plid_t id)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
|
|
|
if (!id)
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
for (int i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].info == id)
|
|
|
|
return &plist[i];
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find a plugin with the given pathname.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT null path
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find(const char* findpath)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
|
|
|
if (!findpath)
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(8, ("Looking for loaded plugin with dlfnamepath: %s", findpath));
|
2016-07-26 15:18:32 +03:00
|
|
|
|
|
|
|
for (int i = 0; i < endlist; i++) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(9, ("Looking at: plugin %s loadedpath: %s", plist[i].file, plist[i].pathname));
|
2016-07-26 15:18:32 +03:00
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!strcmp(plist[i].pathname, findpath)) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(8, ("Found loaded plugin %s", plist[i].file));
|
2016-07-26 03:22:47 +03:00
|
|
|
return &plist[i];
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(8, ("No loaded plugin found with path: %s", findpath));
|
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Find a plugin that uses the given memory location.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT null memptr
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
|
|
|
// - errno's from DLFNAME()
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find_memloc(void* memptr)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
const char* dlfile;
|
2016-07-04 09:07:29 +03:00
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
if (!memptr)
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!(dlfile = DLFNAME(memptr))) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(8, ("DLFNAME failed to find memloc %d", memptr));
|
2016-07-26 03:22:47 +03:00
|
|
|
// meta_errno should be already set in DLFNAME
|
|
|
|
return NULL;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
return find(dlfile);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
// Find a plugin with non-ambiguous prefix string matching desc, file,
|
2016-07-04 09:07:29 +03:00
|
|
|
// name, or logtag.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT null prefix
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
|
|
|
// - ME_NOTUNIQ found multiple matches; no unique match
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find_match(const char* prefix)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i, len;
|
2016-07-04 09:07:29 +03:00
|
|
|
MPlugin *iplug, *pfound;
|
2016-07-26 15:18:32 +03:00
|
|
|
char buf[NAME_MAX ];
|
2016-07-04 09:07:29 +03:00
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
if (!prefix)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
|
|
pfound = NULL;
|
|
|
|
len = strlen(prefix);
|
|
|
|
snprintf(buf, sizeof(buf), "mm_%s", prefix);
|
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug = &plist[i];
|
|
|
|
if (iplug->status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
if (iplug->info && _strnicmp(iplug->info->name, prefix, len) == 0) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
2016-07-26 03:22:47 +03:00
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (_strnicmp(iplug->desc, prefix, len) == 0) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
2016-07-26 03:22:47 +03:00
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (_strnicmp(iplug->file, prefix, len) == 0) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
2016-07-26 03:22:47 +03:00
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (_strnicmp(iplug->file, buf, strlen(buf)) == 0) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
2016-07-26 03:22:47 +03:00
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (iplug->info
|
|
|
|
&& _strnicmp(iplug->info->logtag, prefix, len) == 0) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTUNIQ);
|
2016-07-26 03:22:47 +03:00
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
return (pfound);
|
|
|
|
else
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +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.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_ARGUMENT null prefix
|
|
|
|
// - ME_NOTFOUND couldn't find a matching plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::find_match(MPlugin* pmatch)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i;
|
2016-07-04 09:07:29 +03:00
|
|
|
MPlugin *iplug, *pfound;
|
2016-07-26 03:22:47 +03:00
|
|
|
if (!pmatch)
|
2016-07-26 15:18:32 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_ARGUMENT);
|
|
|
|
pfound = NULL;
|
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug = &plist[i];
|
2016-07-26 15:18:32 +03:00
|
|
|
if (pmatch->platform_match(iplug)) {
|
|
|
|
pfound = iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pfound)
|
2016-07-26 15:18:32 +03:00
|
|
|
return (pfound);
|
|
|
|
else
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::plugin_addload(plid_t plid, const char* fname, PLUG_LOADTIME now)
|
|
|
|
{
|
|
|
|
MPlugin pl_temp;
|
|
|
|
MPlugin *pl_found, *pl_added, *pl_loader;
|
|
|
|
|
|
|
|
if (!(pl_loader = find(plid))) {
|
|
|
|
META_DEBUG(1, ("Couldn't find plugin that gave this loading request!"));
|
|
|
|
RETURN_ERRNO(NULL, ME_BADREQ);
|
|
|
|
}
|
|
|
|
|
|
|
|
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
|
|
|
|
|
|
if (!pl_temp.plugin_parseline(fname, pl_loader->index)) {
|
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pl_temp.resolve() != mTRUE) {
|
|
|
|
META_DEBUG(1, ("Couldn't resolve given path into a file: %s", pl_temp.file));
|
|
|
|
RETURN_ERRNO(NULL, ME_NOTFOUND);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((pl_found = find(pl_temp.pathname))) {
|
|
|
|
META_DEBUG(1, ("Plugin '%s' already in current list; file=%s desc='%s'",
|
|
|
|
pl_temp.file, pl_found->file, pl_found->desc));
|
|
|
|
RETURN_ERRNO(NULL, ME_ALREADY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(pl_added = add(&pl_temp))) {
|
|
|
|
META_DEBUG(1, ("Couldn't add plugin '%s' to list; see log", pl_temp.desc));
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pl_added->action = PA_LOAD;
|
|
|
|
if (!pl_added->load(now)) {
|
|
|
|
if (meta_errno == ME_NOTALLOWED || meta_errno == ME_DELAYED) {
|
|
|
|
META_DEBUG(1, ("Plugin '%s' couldn't attach; only allowed %s",
|
|
|
|
pl_added->desc, pl_added->str_loadable(SL_ALLOWED)));
|
|
|
|
pl_added->clear();
|
|
|
|
}
|
|
|
|
else if (pl_added->status == PL_OPENED) {
|
|
|
|
META_DEBUG(1, ("Opened plugin '%s', but failed to attach; see log", pl_added->desc));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
META_DEBUG(1, ("Couldn't load plugin '%s'; see log", pl_added->desc));
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
META_DEBUG(1, ("Loaded plugin '%s' successfully", pl_added->desc));
|
|
|
|
meta_errno = ME_NOERROR;
|
|
|
|
|
|
|
|
return pl_added;
|
|
|
|
}
|
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
// Add a plugin to the list.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_MAXREACHED reached max plugins
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* MPluginList::add(MPlugin* padd)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-04 09:07:29 +03:00
|
|
|
int i;
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* iplug;
|
2016-07-04 09:07:29 +03:00
|
|
|
|
|
|
|
// Find either:
|
|
|
|
// - a slot in the list that's not being used
|
|
|
|
// - the end of the list
|
2016-07-26 15:18:32 +03:00
|
|
|
for (i = 0; i < endlist && plist[i].status != PL_EMPTY; i++);
|
2016-07-04 09:07:29 +03:00
|
|
|
|
|
|
|
// couldn't find a slot to use
|
2016-07-26 15:18:32 +03:00
|
|
|
if (i == size) {
|
|
|
|
META_ERROR("Couldn't add plugin '%s' to list; reached max plugins (%d)",
|
|
|
|
padd->file, i);
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(NULL, ME_MAXREACHED);
|
|
|
|
}
|
|
|
|
|
|
|
|
// if we found the end of the list, advance end marker
|
2016-07-26 03:22:47 +03:00
|
|
|
if (i == endlist)
|
2016-07-04 09:07:29 +03:00
|
|
|
endlist++;
|
|
|
|
iplug = &plist[i];
|
|
|
|
|
|
|
|
// copy filename into this free slot
|
2016-07-26 15:18:32 +03:00
|
|
|
strncpy(iplug->filename, padd->filename, sizeof iplug->filename - 1);
|
|
|
|
iplug->filename[sizeof iplug->filename - 1] = '\0';
|
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.
|
|
|
|
iplug->file = iplug->filename + (padd->file - padd->filename);
|
|
|
|
// copy description
|
2016-07-26 15:18:32 +03:00
|
|
|
strncpy(iplug->desc, padd->desc, sizeof iplug->desc - 1);
|
|
|
|
iplug->desc[sizeof iplug->desc - 1] = '\0';
|
2016-07-04 09:07:29 +03:00
|
|
|
// copy pathname
|
2016-07-26 15:18:32 +03:00
|
|
|
strncpy(iplug->pathname, padd->pathname, sizeof iplug->pathname - 1);
|
|
|
|
iplug->pathname[sizeof iplug->pathname - 1] = '\0';
|
2016-07-04 09:07:29 +03:00
|
|
|
// copy source
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug->source = padd->source;
|
2016-07-04 09:07:29 +03:00
|
|
|
// copy status
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug->status = padd->status;
|
2016-07-26 15:18:32 +03:00
|
|
|
//copy other things
|
|
|
|
iplug->source_plugin_index = padd->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.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_NOFILE ini file missing or empty
|
2016-07-26 03:22:47 +03:00
|
|
|
mBOOL MPluginList::ini_startup()
|
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
FILE* fp;
|
2016-07-04 09:07:29 +03:00
|
|
|
char line[MAX_STRBUF_LEN];
|
|
|
|
int n, ln;
|
2016-07-26 15:18:32 +03:00
|
|
|
MPlugin* pmatch;
|
|
|
|
|
|
|
|
if (!valid_gamedir_file(inifile)) {
|
|
|
|
META_ERROR("ini: Metamod plugins file empty or missing: %s", inifile);
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
|
|
}
|
|
|
|
full_gamedir_path(inifile, inifile);
|
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
fp = fopen(inifile, "r");
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!fp) {
|
|
|
|
META_ERROR("ini: Unable to open plugins file '%s': %s", inifile,
|
|
|
|
strerror(errno));
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
META_LOG("ini: Begin reading plugins list: %s", inifile);
|
2016-07-26 15:18:32 +03:00
|
|
|
for (n = 0 , ln = 1;
|
|
|
|
!feof(fp) && fgets(line, sizeof(line), fp) && n < size;
|
|
|
|
ln++) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Remove line terminations.
|
2016-07-26 15:18:32 +03:00
|
|
|
char* cp;
|
|
|
|
if ((cp = strrchr(line, '\r')))
|
2016-07-26 03:22:47 +03:00
|
|
|
*cp = '\0';
|
2016-07-26 15:18:32 +03:00
|
|
|
if ((cp = strrchr(line, '\n')))
|
2016-07-26 03:22:47 +03:00
|
|
|
*cp = '\0';
|
2016-07-04 09:07:29 +03:00
|
|
|
// Parse directly into next entry in array
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!plist[n].ini_parseline(line)) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (meta_errno == ME_FORMAT)
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("ini: Skipping malformed line %d of %s", ln,
|
|
|
|
inifile);
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Check for a duplicate - an existing entry with this pathname.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (find(plist[n].pathname)) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Should we check platform specific level here?
|
2016-07-26 15:18:32 +03:00
|
|
|
META_INFO("ini: Skipping duplicate plugin, line %d of %s: %s",
|
|
|
|
ln, inifile, plist[n].pathname);
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Check for a matching platform with different platform specifics
|
|
|
|
// level.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (NULL != (pmatch = find_match(&plist[n]))) {
|
|
|
|
if (pmatch->pfspecific >= plist[n].pfspecific) {
|
|
|
|
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
|
|
|
ln, inifile, pmatch->pfspecific, plist[n].pfspecific));
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
META_DEBUG(1, ("ini: Plugin in line %d overrides existing plugin with lower platform specific level %d, ours %d",
|
|
|
|
ln, pmatch->pfspecific, plist[n].pfspecific));
|
|
|
|
int _index = pmatch->index;
|
|
|
|
memset(pmatch, 0, sizeof(MPlugin));
|
|
|
|
pmatch->index = _index;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
plist[n].action = PA_LOAD;
|
2016-07-04 09:07:29 +03:00
|
|
|
META_LOG("ini: Read plugin config for: %s", plist[n].desc);
|
|
|
|
n++;
|
2016-07-26 15:18:32 +03:00
|
|
|
endlist = n; // mark end of list
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins to load",
|
|
|
|
inifile, n);
|
2016-07-04 09:07:29 +03:00
|
|
|
|
|
|
|
fclose(fp);
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!n) {
|
|
|
|
META_ERROR("ini: Warning; no plugins found to load?");
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mTRUE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Re-read plugins.ini looking for added/deleted/changed plugins.
|
|
|
|
// meta_errno values:
|
|
|
|
// - ME_NOFILE ini file missing or empty
|
2016-07-26 03:22:47 +03:00
|
|
|
mBOOL MPluginList::ini_refresh()
|
|
|
|
{
|
2016-07-26 15:18:32 +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;
|
|
|
|
|
2016-07-26 03:22:47 +03:00
|
|
|
fp = fopen(inifile, "r");
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!fp) {
|
|
|
|
META_ERROR("ini: Unable to open plugins file '%s': %s", inifile,
|
|
|
|
strerror(errno));
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(mFALSE, ME_NOFILE);
|
|
|
|
}
|
|
|
|
|
|
|
|
META_LOG("ini: Begin re-reading plugins list: %s", inifile);
|
2016-07-26 15:18:32 +03:00
|
|
|
for (n = 0 , ln = 1;
|
|
|
|
!feof(fp) && fgets(line, sizeof(line), fp) && n < size;
|
|
|
|
ln++) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Remove line terminations.
|
2016-07-26 15:18:32 +03:00
|
|
|
char* cp;
|
|
|
|
if ((cp = strrchr(line, '\r')))
|
2016-07-26 03:22:47 +03:00
|
|
|
*cp = '\0';
|
2016-07-26 15:18:32 +03:00
|
|
|
if ((cp = strrchr(line, '\n')))
|
2016-07-26 03:22:47 +03:00
|
|
|
*cp = '\0';
|
2016-07-04 09:07:29 +03:00
|
|
|
// Parse into a temp plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
|
|
if (!pl_temp.ini_parseline(line)) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (meta_errno == ME_FORMAT)
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("ini: Skipping malformed line %d of %s",
|
|
|
|
ln, inifile);
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Try to find plugin with this pathname in the current list of
|
|
|
|
// plugins.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!(pl_found = find(pl_temp.pathname))) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Check for a matching platform with higher platform specifics
|
|
|
|
// level.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (NULL != (pl_found = find_match(&pl_temp))) {
|
|
|
|
if (pl_found->pfspecific >= pl_temp.pfspecific) {
|
|
|
|
META_DEBUG(1, ("ini: Skipping plugin, line %d of %s: plugin with higher platform specific level already exists. (%d >= %d)",
|
|
|
|
ln, inifile, pl_found->pfspecific, pl_temp.pfspecific));
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
if (PA_LOAD == pl_found->action) {
|
|
|
|
META_DEBUG(1, ("ini: Plugin in line %d overrides loading of plugin with lower platform specific level %d, ours %d",
|
|
|
|
ln, pl_found->pfspecific, pl_temp.pfspecific));
|
|
|
|
int _index = pl_found->index;
|
|
|
|
memset(pl_found, 0, sizeof(MPlugin));
|
|
|
|
pl_found->index = _index;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else {
|
|
|
|
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->pfspecific, pl_temp.pfspecific));
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// new plugin; add to list
|
2016-07-26 15:18:32 +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
|
2016-07-26 03:22:47 +03:00
|
|
|
pl_added->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 15:18:32 +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.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (pl_temp.desc[0] != '<') {
|
|
|
|
strncpy(pl_found->desc, pl_temp.desc, sizeof pl_found->desc - 1);
|
|
|
|
pl_found->desc[sizeof pl_found->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 15:18:32 +03:00
|
|
|
if (!pl_found->newer_file()) {
|
|
|
|
if (meta_errno == ME_NOFILE) {
|
|
|
|
META_ERROR("ini: Skipping plugin, couldn't stat file '%s': %s",
|
|
|
|
pl_found->pathname, strerror(errno));
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else {
|
2016-07-04 09:07:29 +03:00
|
|
|
// File hasn't been updated.
|
|
|
|
// Keep plugin (don't let refresh() unload it).
|
2016-07-26 03:22:47 +03:00
|
|
|
pl_found->action = PA_KEEP;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Newer file on disk.
|
2016-07-26 15:18:32 +03:00
|
|
|
else if (pl_found->status >= PL_OPENED) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_DEBUG(2, ("ini: Plugin '%s' has newer file on disk", pl_found->desc));
|
2016-07-26 03:22:47 +03:00
|
|
|
pl_found->action = PA_RELOAD;
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
else
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("ini: Plugin '%s' has newer file, but unexpected status (%s)",
|
|
|
|
pl_found->desc, pl_found->str_status());
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
if (NULL != pl_found) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_LOG("ini: Read plugin config for: %s", pl_found->desc);
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_LOG("ini: Read plugin config for: %s", pl_temp.desc);
|
|
|
|
}
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
META_LOG("ini: Finished reading plugins list: %s; Found %d plugins", inifile, n);
|
|
|
|
|
|
|
|
fclose(fp);
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!n) {
|
|
|
|
META_ERROR("ini: Warning; no plugins found to load?");
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mTRUE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Load a plugin from a console command.
|
|
|
|
// meta_errno values:
|
|
|
|
// - errno's from cmd_parseline()
|
|
|
|
// - errno's from resolve()
|
|
|
|
// - ME_ALREADY this plugin already loaded
|
|
|
|
// - errno's from add()
|
|
|
|
// - errno's from load()
|
2016-07-26 15:18:32 +03:00
|
|
|
mBOOL MPluginList::cmd_addload(const char* args)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-04 09:07:29 +03:00
|
|
|
MPlugin pl_temp;
|
|
|
|
MPlugin *pl_found, *pl_added;
|
2016-07-26 03:22:47 +03:00
|
|
|
|
2016-07-04 09:07:29 +03:00
|
|
|
// XXX move back to comands_meta ?
|
|
|
|
|
|
|
|
// parse into a temp plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
memset(&pl_temp, 0, sizeof(pl_temp));
|
|
|
|
if (pl_temp.cmd_parseline(args) != mTRUE) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_CONS("Couldn't parse 'meta load' arguments: %s", args);
|
|
|
|
// meta_errno should be already set in cmd_parseline()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// resolve given path into a file; accepts various "shortcut"
|
|
|
|
// pathnames.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (pl_temp.resolve() != mTRUE) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Couldn't find a matching file on disk
|
2016-07-26 03:22:47 +03:00
|
|
|
META_CONS("Couldn't resolve given path into a file: %s",
|
2016-07-26 15:18:32 +03:00
|
|
|
pl_temp.file);
|
2016-07-04 09:07:29 +03:00
|
|
|
// meta_errno should be already set in resolve()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Try to find plugin with this pathname in the current list of
|
|
|
|
// plugins.
|
2016-07-26 15:18:32 +03:00
|
|
|
if ((pl_found = find(pl_temp.pathname))) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// Already in list
|
2016-07-26 03:22:47 +03:00
|
|
|
META_CONS("Plugin '%s' already in current list; file=%s desc='%s'",
|
2016-07-26 15:18:32 +03:00
|
|
|
pl_temp.file, pl_found->file, pl_found->desc);
|
2016-07-04 09:07:29 +03:00
|
|
|
RETURN_ERRNO(mFALSE, ME_ALREADY);
|
|
|
|
}
|
|
|
|
// new plugin; add to list
|
2016-07-26 15:18:32 +03:00
|
|
|
if (!(pl_added = add(&pl_temp))) {
|
2016-07-04 09:07:29 +03:00
|
|
|
META_CONS("Couldn't add plugin '%s' to list; see log", pl_temp.desc);
|
|
|
|
// meta_errno should be already set in add()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// try to load new plugin
|
2016-07-26 15:18:32 +03:00
|
|
|
pl_added->action = PA_LOAD;
|
|
|
|
if (!pl_added->load(PT_ANYTIME)) {
|
2016-07-04 09:07:29 +03:00
|
|
|
// load failed
|
2016-07-26 15:18:32 +03:00
|
|
|
if (meta_errno == ME_DELAYED)
|
|
|
|
META_CONS("Loaded plugin '%s', but will wait to become active, %s",
|
|
|
|
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
|
|
|
else if (meta_errno == ME_NOTALLOWED) {
|
|
|
|
META_CONS("Plugin '%s' couldn't attach; only allowed %s",
|
|
|
|
pl_added->desc, pl_added->str_loadable(SL_ALLOWED));
|
2016-07-04 09:07:29 +03:00
|
|
|
pl_added->clear();
|
|
|
|
}
|
2016-07-26 03:22:47 +03:00
|
|
|
else if (pl_added->status == PL_OPENED)
|
2016-07-04 09:07:29 +03:00
|
|
|
META_CONS("Opened plugin '%s', but failed to attach; see log", pl_added->desc);
|
|
|
|
else
|
|
|
|
META_CONS("Couldn't load plugin '%s'; see log", pl_added->desc);
|
2016-07-26 15:18:32 +03:00
|
|
|
show(0);
|
2016-07-04 09:07:29 +03:00
|
|
|
// meta_errno should be already set in load()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
META_CONS("Loaded plugin '%s' successfully", pl_added->desc);
|
2016-07-26 15:18:32 +03:00
|
|
|
show(0);
|
|
|
|
return (mTRUE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Load plugins at startup.
|
|
|
|
// meta_errno values:
|
|
|
|
// - errno's from ini_startup()
|
2016-07-26 03:22:47 +03:00
|
|
|
mBOOL MPluginList::load()
|
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i, n;
|
|
|
|
|
|
|
|
if (!ini_startup()) {
|
|
|
|
META_ERROR("Problem loading plugins.ini: %s", inifile);
|
2016-07-04 09:07:29 +03:00
|
|
|
// meta_errno should be already set in ini_startup()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
META_LOG("dll: Loading plugins...");
|
2016-07-26 15:18:32 +03:00
|
|
|
for (i = 0 , n = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 03:22:47 +03:00
|
|
|
if (plist[i].load(PT_STARTUP) == mTRUE)
|
2016-07-04 09:07:29 +03:00
|
|
|
n++;
|
|
|
|
else
|
2016-07-26 15:18:32 +03:00
|
|
|
// all plugins should be loadable at startup...
|
|
|
|
META_ERROR("dll: Failed to load plugin '%s'", plist[i].file);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
META_LOG("dll: Finished loading %d plugins", n);
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mTRUE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Update list of loaded plugins from ini file, and load any new/changed plugins.
|
|
|
|
// meta_errno values:
|
|
|
|
// - errno's from ini_refresh()
|
2016-07-26 03:22:47 +03:00
|
|
|
mBOOL MPluginList::refresh(PLUG_LOADTIME now)
|
|
|
|
{
|
|
|
|
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 15:18:32 +03:00
|
|
|
if (!ini_refresh()) {
|
|
|
|
META_ERROR("dll: Problem reloading plugins.ini: %s", inifile);
|
2016-07-04 09:07:29 +03:00
|
|
|
// meta_errno should be already set in ini_refresh()
|
2016-07-26 15:18:32 +03:00
|
|
|
return (mFALSE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
META_LOG("dll: Updating plugins...");
|
2016-07-26 15:18:32 +03:00
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug = &plist[i];
|
|
|
|
if (iplug->status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
switch (iplug->action) {
|
2016-07-26 03:22:47 +03:00
|
|
|
case PA_KEEP:
|
|
|
|
META_DEBUG(1, ("Keeping plugin '%s'", iplug->desc));
|
|
|
|
iplug->action = PA_NONE;
|
|
|
|
nkept++;
|
|
|
|
break;
|
|
|
|
case PA_LOAD:
|
|
|
|
META_DEBUG(1, ("Loading plugin '%s'", iplug->desc));
|
|
|
|
if (iplug->load(now))
|
|
|
|
nloaded++;
|
|
|
|
else if (meta_errno == ME_DELAYED)
|
|
|
|
ndelayed++;
|
|
|
|
break;
|
|
|
|
case PA_RELOAD:
|
|
|
|
META_DEBUG(1, ("Reloading plugin '%s'", iplug->desc));
|
|
|
|
if (iplug->reload(now, PNL_FILE_NEWER))
|
|
|
|
nreloaded++;
|
|
|
|
else if (meta_errno == ME_DELAYED)
|
|
|
|
ndelayed++;
|
|
|
|
break;
|
|
|
|
case PA_NONE:
|
|
|
|
// If previously loaded from ini, but apparently removed from new ini.
|
2016-07-26 15:18:32 +03:00
|
|
|
if (iplug->source == PS_INI && iplug->status >= PL_RUNNING) {
|
2016-07-26 03:22:47 +03:00
|
|
|
META_DEBUG(1, ("Unloading plugin '%s'", iplug->desc));
|
|
|
|
iplug->action = PA_UNLOAD;
|
|
|
|
if (iplug->unload(now, PNL_INI_DELETED, PNL_INI_DELETED))
|
2016-07-04 09:07:29 +03:00
|
|
|
nunloaded++;
|
2016-07-26 03:22:47 +03:00
|
|
|
else if (meta_errno == ME_DELAYED)
|
2016-07-04 09:07:29 +03:00
|
|
|
ndelayed++;
|
2016-07-26 03:22:47 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case PA_ATTACH:
|
|
|
|
// Previously requested attach, but was delayed?
|
|
|
|
META_DEBUG(1, ("Retrying attach plugin '%s'", iplug->desc));
|
|
|
|
if (iplug->retry(now, PNL_DELAYED))
|
|
|
|
nloaded++;
|
|
|
|
else if (meta_errno == ME_DELAYED)
|
|
|
|
ndelayed++;
|
|
|
|
break;
|
|
|
|
case PA_UNLOAD:
|
|
|
|
// Previously requested unload, but was delayed?
|
|
|
|
META_DEBUG(1, ("Retrying unload plugin '%s'", iplug->desc));
|
|
|
|
if (iplug->retry(now, PNL_DELAYED))
|
|
|
|
nunloaded++;
|
|
|
|
else if (meta_errno == ME_DELAYED)
|
|
|
|
ndelayed++;
|
|
|
|
break;
|
|
|
|
case PA_NULL:
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("dll: Unexpected action for plugin '%s': '%s'", iplug->desc, iplug->str_action());
|
2016-07-26 03:22:47 +03:00
|
|
|
break;
|
|
|
|
default:
|
2016-07-26 15:18:32 +03:00
|
|
|
META_ERROR("dll: Unrecognized action for plugin '%s': '%s'", iplug->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 15:18:32 +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);
|
|
|
|
return (mTRUE);
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Re-enable any plugins currently paused.
|
|
|
|
// meta_errno values:
|
|
|
|
// - none
|
2016-07-26 15:18:32 +03:00
|
|
|
void MPluginList::unpause_all(void)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i;
|
|
|
|
MPlugin* iplug;
|
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug = &plist[i];
|
|
|
|
if (iplug->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.
|
|
|
|
// meta_errno values:
|
|
|
|
// - none
|
2016-07-26 03:22:47 +03:00
|
|
|
void MPluginList::retry_all(PLUG_LOADTIME now)
|
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i;
|
|
|
|
MPlugin* iplug;
|
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
iplug = &plist[i];
|
|
|
|
if (iplug->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.
|
|
|
|
// meta_errno values:
|
|
|
|
// - none
|
2016-07-26 03:22:47 +03:00
|
|
|
void MPluginList::show(int source_index)
|
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i, 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 15:18:32 +03:00
|
|
|
META_CONS(" %*s %-*s %-4s %-4s %-*s v%-*s %-3s %-5s %-5s",
|
|
|
|
WIDTH_MAX_PLUGINS, "",
|
|
|
|
sizeof(desc) - 1, "description",
|
|
|
|
"stat", "pend",
|
|
|
|
sizeof(file) - 1, "file", sizeof(vers) - 1, "ers",
|
|
|
|
"src", "load ", "unlod");
|
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
pl = &plist[i];
|
|
|
|
if (pl->status < PL_VALID)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
if ((source_index > 0) && (pl->source_plugin_index != source_index))
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
2016-07-26 15:18:32 +03:00
|
|
|
strncpy(desc, pl->desc, sizeof desc - 1);
|
|
|
|
desc[sizeof desc - 1] = '\0';
|
|
|
|
strncpy(file, pl->file, sizeof file - 1);
|
|
|
|
file[sizeof file - 1] = '\0';
|
|
|
|
if (pl->info && pl->info->version) {
|
|
|
|
strncpy(vers, pl->info->version, sizeof vers - 1);
|
|
|
|
vers[sizeof vers - 1] = '\0';
|
2016-07-26 03:22:47 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
else {
|
|
|
|
strncpy(vers, " -", sizeof vers - 1);
|
|
|
|
vers[sizeof vers - 1] = '\0';
|
2016-07-26 03:22:47 +03:00
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
META_CONS(" [%*d] %-*s %-4s %-4s %-*s v%-*s %-3s %-5s %-5s",
|
|
|
|
WIDTH_MAX_PLUGINS, pl->index,
|
|
|
|
sizeof(desc) - 1, desc,
|
|
|
|
pl->str_status(ST_SHOW), pl->str_action(SA_SHOW),
|
|
|
|
sizeof(file) - 1, file, sizeof(vers) - 1, vers,
|
|
|
|
pl->str_source(SO_SHOW),
|
|
|
|
pl->str_loadable(SL_SHOW), pl->str_unloadable(SL_SHOW));
|
2016-07-26 03:22:47 +03:00
|
|
|
if (pl->status == PL_RUNNING)
|
2016-07-04 09:07:29 +03:00
|
|
|
r++;
|
|
|
|
n++;
|
|
|
|
}
|
|
|
|
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 15:18:32 +03:00
|
|
|
// - Limited info about each plugin, mostly the "public" info (name, author,
|
2016-07-04 09:07:29 +03:00
|
|
|
// etc).
|
|
|
|
// meta_errno values:
|
|
|
|
// - none
|
2016-07-26 15:18:32 +03:00
|
|
|
void MPluginList::show_client(edict_t* pEntity)
|
2016-07-26 03:22:47 +03:00
|
|
|
{
|
2016-07-26 15:18:32 +03:00
|
|
|
int i, n = 0;
|
|
|
|
MPlugin* pl;
|
2016-07-04 09:07:29 +03:00
|
|
|
META_CLIENT(pEntity, "Currently running plugins:");
|
2016-07-26 15:18:32 +03:00
|
|
|
for (i = 0; i < endlist; i++) {
|
2016-07-26 03:22:47 +03:00
|
|
|
pl = &plist[i];
|
2016-07-26 15:18:32 +03:00
|
|
|
if (pl->status != PL_RUNNING)
|
2016-07-04 09:07:29 +03:00
|
|
|
continue;
|
|
|
|
n++;
|
2016-07-26 15:18:32 +03:00
|
|
|
META_CLIENT(pEntity, " [%3d] %s, v%s, %s, by %s, see %s",
|
|
|
|
n,
|
|
|
|
pl->info->name ? pl->info->name : "<unknown>",
|
|
|
|
pl->info->version ? pl->info->version : "<?>",
|
|
|
|
pl->info->date ? pl->info->date : "<../../..>",
|
|
|
|
pl->info->author ? pl->info->author : "<unknown>",
|
|
|
|
pl->info->url ? pl->info->url : "<unknown>");
|
2016-07-04 09:07:29 +03:00
|
|
|
}
|
|
|
|
META_CLIENT(pEntity, "%d plugins", n);
|
|
|
|
}
|
2016-07-26 15:18:32 +03:00
|
|
|
|
|
|
|
mBOOL MPluginList::found_child_plugins(int source_index)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (source_index <= 0)
|
|
|
|
return mFALSE;
|
|
|
|
|
|
|
|
for (i = 0; i < endlist; i++) {
|
|
|
|
if (plist[i].status < PL_VALID)
|
|
|
|
continue;
|
|
|
|
if (plist[i].source_plugin_index == source_index)
|
|
|
|
return mTRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return mFALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MPluginList::clear_source_plugin_index(int source_index)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (source_index <= 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < endlist; i++) {
|
|
|
|
if (plist[i].status < PL_VALID)
|
|
|
|
continue;
|
|
|
|
if (plist[i].source_plugin_index == source_index)
|
|
|
|
plist[i].source_plugin_index = -1;
|
|
|
|
}
|
|
|
|
}
|