- Added strlcpy and strlcat to SICS - Added a driver for the POLDI power supplies SKIPPED: psi/A1931.c psi/autowin.c psi/bruker.c psi/docho.c psi/dornier2.c psi/dspcode.c psi/ease.c psi/ecb.c psi/ecbcounter.c psi/ecbdriv.c psi/el734dc.c psi/el734driv.c psi/el734hp.c psi/el737driv.c psi/el737hpdriv.c psi/el737hpdrivsps.c psi/el737hpv2driv.c psi/el755driv.c psi/eurodriv.c psi/haakedriv.c psi/itc4driv.c psi/julcho.c psi/linadriv.c psi/lmd200.c psi/lscsupport.c psi/ltc11.c psi/make_gen psi/oicom.c psi/oxinst.c psi/pimotor.c psi/pipiezo.c psi/polterwrite.c psi/psi.c psi/sanscook.c psi/sanslirebin.c psi/sanswave.c psi/sinqhmdriv.c psi/sinqhttp.c psi/slsecho.c psi/slsmagnet.c psi/slsvme.c psi/sps.c psi/swmotor.c psi/swmotor2.c psi/tabledrive.c psi/tasscan.c psi/tdchm.c psi/velodorn.c psi/velodornier.c
296 lines
8.0 KiB
C
296 lines
8.0 KiB
C
/*---------------------------------------------------------------------------
|
|
|
|
Implementation for the server log.
|
|
|
|
Is a bit tricky. Writes 1000 lines to a file, than increments
|
|
and opens a new one. Wraps arounf after 3. This is a compromise
|
|
between error tracking and use of diskspace.
|
|
|
|
|
|
|
|
Mark Koennecke, October 1996
|
|
|
|
Copyright:
|
|
|
|
Labor fuer Neutronenstreuung
|
|
Paul Scherrer Institut
|
|
CH-5423 Villigen-PSI
|
|
|
|
|
|
The authors hereby grant permission to use, copy, modify, distribute,
|
|
and license this software and its documentation for any purpose, provided
|
|
that existing copyright notices are retained in all copies and that this
|
|
notice is included verbatim in any distributions. No written agreement,
|
|
license, or royalty fee is required for any of the authorized uses.
|
|
Modifications to this software may be copyrighted by their authors
|
|
and need not follow the licensing terms described here, provided that
|
|
the new terms are clearly indicated on the first page of each file where
|
|
they apply.
|
|
|
|
IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY
|
|
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
|
|
ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY
|
|
DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE
|
|
POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES,
|
|
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
|
|
FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE
|
|
IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE
|
|
NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR
|
|
MODIFICATIONS.
|
|
|
|
Modified: Paul Hathaway, June 2004
|
|
SICSLogWrite
|
|
- no longer asserts existence of the log file, writing
|
|
to stderr and skipping further file writes.
|
|
- NETWrites log message (if enabled) before attempt to write to file
|
|
- uses OpenVerifyLogFile helper function (removed duplicate code)
|
|
-----------------------------------------------------------------------------*/
|
|
#include "fortify.h"
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <ctype.h>
|
|
#include <strlutil.h>
|
|
|
|
#include "ifile.h"
|
|
#include "conman.h"
|
|
#include "servlog.h"
|
|
#include "network.h"
|
|
|
|
/* define this, if you do not want a server log
|
|
|
|
#define NOLOG 1
|
|
*/
|
|
/* -------------------------------------------------------------------------
|
|
The server log output can be captured by a client. In order to implement
|
|
this the following code is necessary.
|
|
*/
|
|
typedef struct __LogLog {
|
|
SConnection *pCon;
|
|
OutCode iOut;
|
|
int iAllFlag;
|
|
struct __LogLog *pNext;
|
|
struct __LogLog *pPrevious;
|
|
} CaptureEntry, *pCaptureEntry;
|
|
|
|
static pCaptureEntry pCapture = NULL;
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
int KillCapture(SConnection * pCon)
|
|
{
|
|
pCaptureEntry pCurrent, pTemp;
|
|
|
|
/* find first */
|
|
pCurrent = pCapture;
|
|
while (pCurrent != NULL) {
|
|
if (pCon == pCurrent->pCon) {
|
|
/* relink */
|
|
if (pCurrent->pPrevious) {
|
|
pCurrent->pPrevious->pNext = pCurrent->pNext;
|
|
} else {
|
|
pCapture = pCurrent->pNext;
|
|
}
|
|
if (pCurrent->pNext) {
|
|
pCurrent->pNext->pPrevious = pCurrent->pPrevious;
|
|
}
|
|
pTemp = pCurrent->pNext;
|
|
/* get rid of pCurrent */
|
|
free(pCurrent);
|
|
pCurrent = pTemp;
|
|
} else {
|
|
pCurrent = pCurrent->pNext;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------------
|
|
the command function:
|
|
Syntax:
|
|
Kill kills all logging
|
|
Log OutCode starts loggin OutCode events
|
|
All starts logging all events
|
|
-------------------------------------------------------------------------- */
|
|
#include "outcode.c" /* for pCode */
|
|
|
|
int LogCapture(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pCaptureEntry pNew = NULL;
|
|
char pBueffel[512];
|
|
int i;
|
|
|
|
/* check no af args */
|
|
if (argc < 2) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "Insufficient number of argumenst to %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
argtolower(argc, argv);
|
|
|
|
/* Branch according to argv[1] */
|
|
if (strcmp(argv[1], "kill") == 0) {
|
|
KillCapture(pCon);
|
|
return 1;
|
|
} else if (strcmp(argv[1], "all") == 0) {
|
|
pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry));
|
|
if (!pNew) {
|
|
SICSLogWrite("Out of memory in LogCapture", eInternal);
|
|
return 0;
|
|
}
|
|
if (pCapture) {
|
|
pCapture->pPrevious = pNew;
|
|
}
|
|
pNew->pPrevious = NULL;
|
|
pNew->pNext = pCapture;
|
|
pCapture = pNew;
|
|
pNew->iAllFlag = 1;
|
|
pNew->pCon = pCon;
|
|
return 1;
|
|
} else {
|
|
/* must be outcode, try find it */
|
|
i = 0;
|
|
while (pCode[i] != NULL) {
|
|
if (strcmp(argv[1], pCode[i]) == 0) {
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if (i > iNoCodes) {
|
|
snprintf(pBueffel,sizeof(pBueffel)-1, "OutPutCode %s not recognized in %s", argv[1],
|
|
argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
/* create a new one */
|
|
pNew = (pCaptureEntry) malloc(sizeof(CaptureEntry));
|
|
if (!pNew) {
|
|
SICSLogWrite("Out of memory in LogCapture", eInternal);
|
|
return 0;
|
|
}
|
|
if (pCapture) {
|
|
pCapture->pPrevious = pNew;
|
|
}
|
|
pNew->pPrevious = NULL;
|
|
pNew->pNext = pCapture;
|
|
pCapture = pNew;
|
|
pNew->iAllFlag = 0;
|
|
pNew->pCon = pCon;
|
|
pNew->iOut = i;
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static int HasLineFeed(char *pText)
|
|
{
|
|
int i;
|
|
|
|
for (i = strlen(pText); i > 0; i--) {
|
|
if (pText[i] == '\n') {
|
|
return 1;
|
|
}
|
|
if (isalpha(pText[i])) {
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#define MAXLOG 10000
|
|
#define MAXFILES 20
|
|
|
|
static FILE *fLogFile = NULL;
|
|
static int iFile = 0;
|
|
static int iLineCount = 0;
|
|
static int iLogUsable = 1;
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int OpenVerifyLogFile()
|
|
{
|
|
char pFile[256];
|
|
char filnam[512];
|
|
char *pChar = NULL;
|
|
|
|
pChar = IFindOption(pSICSOptions, "LogFileBaseName");
|
|
if (!pChar) { /* Try to write to file "server" in */
|
|
strcpy(pFile, "server");
|
|
} else {
|
|
strlcpy(pFile, pChar, 255);
|
|
}
|
|
snprintf(filnam, 511, "%s%2.2d.log", pFile, iFile);
|
|
fLogFile = fopen(filnam, "w");
|
|
if (!fLogFile) {
|
|
fprintf(stderr, "ERROR: Cannot open logfile %s for writing\n", pFile);
|
|
fLogFile = NULL;
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void SICSLogEnable(int flag)
|
|
{
|
|
iLogUsable = flag;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
void SICSLogWrite(char *pText, OutCode eOut)
|
|
{
|
|
char pFile[256];
|
|
char *pChar = NULL;
|
|
pCaptureEntry pCurrent;
|
|
char pBueffel[256];
|
|
|
|
#ifdef NOLOG
|
|
return;
|
|
#endif
|
|
|
|
/* do all captured */
|
|
pCurrent = pCapture;
|
|
while (pCurrent) {
|
|
if ((pCurrent->iOut == eOut) || (pCurrent->iAllFlag == 1)) {
|
|
ANETwrite(pCurrent->pCon->sockHandle, pText, strlen(pText));
|
|
ANETwrite(pCurrent->pCon->sockHandle, "\n", 1);
|
|
}
|
|
pCurrent = pCurrent->pNext;
|
|
}
|
|
|
|
if (0 == iLogUsable)
|
|
return;
|
|
|
|
if (fLogFile == NULL) { /* first time of use */
|
|
/* no options: startup or serious trouble, print to stdout */
|
|
if (!pSICSOptions) {
|
|
printf("WARNING: Cannot log(%s)\n", pText);
|
|
return;
|
|
}
|
|
iLogUsable = OpenVerifyLogFile();
|
|
}
|
|
|
|
/* switch file if too many lines */
|
|
if (iLineCount >= MAXLOG) {
|
|
fclose(fLogFile);
|
|
fLogFile = NULL;
|
|
iFile++;
|
|
iLineCount = 0;
|
|
if (iFile >= MAXFILES) {
|
|
iFile = 0;
|
|
}
|
|
iLogUsable = OpenVerifyLogFile();
|
|
}
|
|
|
|
if (1 == iLogUsable) {
|
|
fprintf(fLogFile, "%s\n", pText);
|
|
fflush(fLogFile);
|
|
iLineCount++;
|
|
}
|
|
}
|