Skip to content

Commit

Permalink
Log|libcore|libdoomsday: Interactive script output bypasses filtering
Browse files Browse the repository at this point in the history
When the user enters commands in the console, and the commands produce
output, it is better to allow these entries to bypass the chosen
filters. Log entries created during execution of console commands
whose source is either "console" or "cmdline" are now flagged as
Interactive, and LogFilter allows these to pass in the Script domain.

This is not a perfect solution, though, because not all console
commands (yet) use SCR when printing output.

IssueID #2074
  • Loading branch information
skyjake committed Nov 26, 2015
1 parent a15bc67 commit b7eef70
Show file tree
Hide file tree
Showing 8 changed files with 136 additions and 93 deletions.
8 changes: 4 additions & 4 deletions doomsday/apps/client/src/dd_main.cpp
Expand Up @@ -2939,21 +2939,21 @@ D_CMD(Version)
{
DENG2_UNUSED3(src, argc, argv);

LOG_NOTE(_E(D) DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_FULLTEXT);
LOG_MSG(_E(l) "Homepage: " _E(.) _E(i) DOOMSDAY_HOMEURL _E(.)
LOG_SCR_NOTE(_E(D) DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_FULLTEXT);
LOG_SCR_MSG(_E(l) "Homepage: " _E(.) _E(i) DOOMSDAY_HOMEURL _E(.)
"\n" _E(l) "Project: " _E(.) _E(i) DENGPROJECT_HOMEURL);

// Print the version info of the current game if loaded.
if(App_GameLoaded())
{
LOG_MSG(_E(l) "Game: " _E(.) "%s") << (char const *) gx.GetVariable(DD_PLUGIN_VERSION_LONG);
LOG_SCR_MSG(_E(l) "Game: " _E(.) "%s") << (char const *) gx.GetVariable(DD_PLUGIN_VERSION_LONG);
}

// Additional information for developers.
Version const ver;
if(!ver.gitDescription.isEmpty())
{
LOGDEV_MSG(_E(l) "Git revision: " _E(.) "%s") << ver.gitDescription;
LOGDEV_SCR_MSG(_E(l) "Git revision: " _E(.) "%s") << ver.gitDescription;
}
return true;
}
Expand Down
Expand Up @@ -13,7 +13,7 @@
* 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, see:
* http://www.gnu.org/licenses</small>
* http://www.gnu.org/licenses</small>
*/

#include "ui/widgets/consolecommandwidget.h"
Expand Down
89 changes: 34 additions & 55 deletions doomsday/apps/libdoomsday/src/console/exec.cpp
Expand Up @@ -37,6 +37,8 @@
#include <de/game/Game>
#include <de/LogBuffer>
#include <de/Time>
#include <de/Log>
#include "doomsday/doomsdayapp.h"
#include "doomsday/console/knownword.h"
#include "doomsday/console/cmd.h"
#include "doomsday/console/var.h"
Expand Down Expand Up @@ -368,45 +370,45 @@ static dd_bool Con_CheckExecBuffer(void)
{
#define BUFFSIZE 1024 /// @todo Rewrite all of this; use de::String. -jk

// dd_bool allDone;
dd_bool ret = true;
int i; //, count = 0;
int i;
char storage[BUFFSIZE];

storage[255] = 0;

// do // We'll keep checking until all is done.
{
//allDone = true;
TimeDelta const now = TimeDelta::sinceStartOfProcess();

TimeDelta const now = TimeDelta::sinceStartOfProcess();
// Execute the commands whose time has come.
for(i = 0; i < exBuffSize; ++i)
{
execbuff_t *ptr = exBuff + i;

// Execute the commands whose time has come.
for(i = 0; i < exBuffSize; ++i)
{
execbuff_t *ptr = exBuff + i;
if(!ptr->used || ptr->when > now)
continue;

if(!ptr->used || ptr->when > now)
continue;
// We'll now execute this command.
curExec = ptr;
ptr->used = false;
strncpy(storage, ptr->subCmd, BUFFSIZE - 1);

// We'll now execute this command.
curExec = ptr;
ptr->used = false;
strncpy(storage, ptr->subCmd, BUFFSIZE-1);
bool const isInteractive =
(ptr->source == CMDS_CONSOLE ||
ptr->source == CMDS_CMDLINE);
if(isInteractive)
{
Log::threadLog().beginInteractive();
}

if(!executeSubCmd(storage, ptr->source, ptr->isNetCmd))
ret = false;
//allDone = false;
if(!executeSubCmd(storage, ptr->source, ptr->isNetCmd))
{
ret = false;
}

// if(count++ > 100) break; // Don't hang here.
/* {
DENG_ASSERT(!"Execution buffer overflow");
LOG_SCR_ERROR("Console execution buffer overflow! Everything canceled!");
Con_ClearExecBuffer();
break;
}*/
} //while(!allDone);
if(isInteractive)
{
Log::threadLog().endInteractive();
}
}

return ret;
#undef BUFFSIZE
Expand Down Expand Up @@ -484,30 +486,6 @@ static int executeSubCmd(const char *subCmd, byte src, dd_bool isNetCmd)
if(!args.argc)
return true;

/*
if(args.argc == 1) // Possibly a control command?
{
if(P_ControlExecute(args.argv[0]))
{
// It was a control command. No further processing is
// necessary.
return true;
}
}
*/

#if 0
#ifdef __CLIENT__
// If logged in, send command to server at this point.
if(!isServer && netLoggedIn)
{
// We have logged in on the server. Send the command there.
Con_Send(subCmd, src, ConsoleSilent);
return true;
}
#endif
#endif

// Try to find a matching console command.
ccmd = Con_FindCommandMatchArgs(&args);
if(ccmd != NULL)
Expand Down Expand Up @@ -854,17 +832,18 @@ static void Con_SplitIntoSubCommands(const char *command,

int Con_Execute(byte src, const char *command, int silent, dd_bool netCmd)
{
int ret;

if(silent)
{
ConsoleSilent = true;
}

Con_SplitIntoSubCommands(command, 0, src, netCmd);
ret = Con_CheckExecBuffer();
int ret = Con_CheckExecBuffer();

if(silent)
{
ConsoleSilent = false;

}
return ret;
}

Expand Down
26 changes: 21 additions & 5 deletions doomsday/sdk/libcore/include/de/core/log.h
Expand Up @@ -14,7 +14,7 @@
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this program; if not, see:
* http://www.gnu.org/licenses</small>
* http://www.gnu.org/licenses</small>
*/

#ifndef LIBDENG2_LOG_H
Expand Down Expand Up @@ -50,8 +50,7 @@
* is valid.
*/
#define LOG_AS_STRING(str) \
de::String __logSectionName = str; \
de::Block __logSectionUtf8 = __logSectionName.toUtf8(); \
de::Block __logSectionUtf8 { de::String(str).toUtf8() }; \
LOG_AS(__logSectionUtf8.constData());

/*
Expand Down Expand Up @@ -297,6 +296,8 @@ class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable
regardless of log filtering, in a separate overlay.
Use this for whatever you are currently working on
(so there is no need to rely on qDebug). */
Interactive = 0x02000000, /**< Output from a command entered manually by the user.
Typically these should never be filtered. */

AllDomains = 0x00ff0000,
DomainMask = AllDomains,
Expand Down Expand Up @@ -382,7 +383,7 @@ class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable
LowestLogLevel = XVerbose,
HighestLogLevel = Critical,
LevelMask = 0x7
};
};

static String levelToText(duint32 level)
{
Expand Down Expand Up @@ -599,7 +600,7 @@ class DENG2_PUBLIC LogEntry : public Lockable, public ISerializable
*
* @return Composed textual representation of the entry.
*/
String asText(Flags const &flags = 0, int shortenSection = 0) const;
String asText(Flags const &flags = 0, int shortenSection = 0) const;

// Implements ISerializable.
void operator >> (Writer &to) const;
Expand Down Expand Up @@ -694,6 +695,21 @@ class DENG2_PUBLIC Log
*/
void endSection(char const *name);

/**
* Begins an interactive section. All entries added while interactive get
* flagged as such. You must call endInteractive() to end the section.
* Interactive sections can be nested.
*/
void beginInteractive();

/**
* Ends an interactive section. The number of endInteractive() calls must
* match the number of beginInteractive() calls.
*/
void endInteractive();

bool isInteractive() const;

/**
* Creates a new log entry with the default (Message) level, targeted to the end-user.
*
Expand Down

0 comments on commit b7eef70

Please sign in to comment.