/** * This is a means to listen into the stream of log messages from the logv2 * logging system. * * Mark Koennecke, May 2016 */ #include #include #include /* From logv2.c */ extern int subsystemFromText(const char *text); /*=============================================================================*/ static int listenerList; static int callbackRegistered = 0; typedef struct { SConnection *pCon; char subsystem[64]; } ListenEntry; /*-----------------------------------------------------------------------------*/ static void LogListenCallback(unsigned int severity, const char *timeStamp, const char *subsystem, const char *message, void *userData) { ListenEntry current; int status, cleanupNeeded = 0; if(logFilter(severity,subsystem,message) == 1) { return; } status = LLDnodePtr2First(listenerList); while(status != 0){ LLDnodeDataTo(listenerList,¤t); if(strcmp(current.subsystem,subsystem) == 0) { if(SCisConnected(current.pCon)){ SCPureSockWrite(current.pCon,(char *)message,eValue); } else { cleanupNeeded = 1; } } status = LLDnodePtr2Next(listenerList); } /* lld lists sometimes get confused when deleting nodes on the fly. This is why this has been put into a separate loop */ if(cleanupNeeded){ status = LLDnodePtr2First(listenerList); while(status != 0){ LLDnodeDataTo(listenerList,¤t); if(!SCisConnected(current.pCon)){ SCDeleteConnection(current.pCon); LLDnodeDelete(listenerList); } status = LLDnodePtr2Next(listenerList); } } } /*-----------------------------------------------------------------------------*/ static int LogListenAction(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { ListenEntry listLog; if(argc < 2){ SCWrite(pCon,"ERROR: need subsystem argument for loglisten", eError); return 0; } if(subsystemFromText(argv[1]) < 0){ SCPrintf(pCon,eError, "ERROR: invalid subsystem %s specified", argv[1]); return 0; } listLog.pCon = SCCopyConnection(pCon); strncpy(listLog.subsystem,argv[1],sizeof(listLog.subsystem)); LLDnodeAppendFrom(listenerList,&listLog); if(!callbackRegistered){ RegisterLogCallback(LogListenCallback,NULL); callbackRegistered = 1; } SCSendOK(pCon); return 1; } /*-----------------------------------------------------------------------------*/ void LogListenInit(void) { listenerList = LLDcreate(sizeof(ListenEntry)); AddCmd("loglisten", LogListenAction); }