351 lines
7.8 KiB
C
351 lines
7.8 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdarg.h>
|
|
#include <assert.h>
|
|
#include "coc_logfile.h"
|
|
#include "myc_time.h"
|
|
#include "myc_err.h"
|
|
#include "myc_str.h"
|
|
|
|
static FILE *fil=NULL;
|
|
static char lnam[224]="";
|
|
static char filnam[256]="";
|
|
static char ebuf[20000]="";
|
|
static char *statusBuf=NULL;
|
|
static int statusSize;
|
|
static char *eptr=&ebuf[0];
|
|
static int dated=0;
|
|
static int logMask=0;
|
|
static int wrtMask=0;
|
|
static int newLine=1;
|
|
static int logfileStd;
|
|
static int dirty, writeAll;
|
|
static int lastline=1;
|
|
static long int lastpos=0;
|
|
static int lastStamp=0;
|
|
static int openTime;
|
|
static int openDate;
|
|
|
|
void (*logfileOutRtn)(int, char *)=NULL;
|
|
|
|
void logfileOpen(int append) {
|
|
int year;
|
|
|
|
if (logfileStd) {
|
|
fil=stdout;
|
|
str_copy(filnam, "<stdout>");
|
|
return;
|
|
}
|
|
assert(fil==NULL);
|
|
openTime = mycNow();
|
|
openDate = mycDate(openTime); /* date in yyyymmdd decimal encoding */
|
|
openTime = openTime % (24*3600); /* seconds since midnight */
|
|
if (dated) {
|
|
sprintf(filnam, "%s%02d-%02d.log", lnam, openDate % 10000 / 100, openDate % 100);
|
|
} else {
|
|
if (lnam[0]=='\0') {
|
|
str_copy(filnam, "test.log");
|
|
} else {
|
|
str_copy(filnam, lnam);
|
|
str_append(filnam, ".log");
|
|
}
|
|
}
|
|
if (dated) {
|
|
fil=fopen(filnam, "a+");
|
|
if (fil != NULL) {
|
|
fseek(fil, 0, SEEK_SET); /* set position to start */
|
|
year=0;
|
|
fscanf(fil, "%4d", &year);
|
|
if (year != openDate / 10000) {
|
|
fclose(fil);
|
|
fil=fopen(filnam, "w+"); /* overwrite old logfile */
|
|
} else {
|
|
fseek(fil, 0, SEEK_END); /* set position to end */
|
|
}
|
|
}
|
|
} else {
|
|
fil=fopen(filnam, "w+"); /* overwrite last logfile */
|
|
}
|
|
if (fil==NULL) {
|
|
printf("Can not open %s\n", filnam);
|
|
fil=stdout;
|
|
str_copy(filnam, "<stdout>");
|
|
return;
|
|
}
|
|
ErrSetOutFile(fil);
|
|
fprintf(fil, "%04d-%02d-%02d %02d:%02d:%02d opened logfile\n"
|
|
, openDate / 10000, openDate % 10000 / 100, openDate % 100
|
|
, openTime / 3600, openTime / 60 % 60, openTime % 60);
|
|
lastStamp = openTime / 60;
|
|
}
|
|
|
|
void logfileStatusBuffer(char *buffer, int bufsize) {
|
|
statusBuf=buffer;
|
|
statusSize=bufsize-1;
|
|
}
|
|
|
|
char *logfileInit(char *path, int nodate, int use_stdout, int write_all) {
|
|
str_copy(lnam, path);
|
|
logfileStd=use_stdout;
|
|
writeAll=write_all;
|
|
dated=!nodate;
|
|
logfileOpen(1);
|
|
return(filnam);
|
|
}
|
|
|
|
void logfileStamp(char *text) {
|
|
int time, date, stamp;
|
|
|
|
time = mycNow();
|
|
date = mycDate(time); /* date in yyyymmdd decimal encoding */
|
|
time = time % (24*3600); /* seconds since midnight */
|
|
|
|
stamp=time / 60;
|
|
if (date != openDate ) { /* day has changed -> new logfile */
|
|
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
|
lastpos=0;
|
|
lastline=1;
|
|
logfileOpen(1);
|
|
}
|
|
if (text==NULL) {
|
|
if (stamp>lastStamp+1) {
|
|
fprintf(fil, "---\t%02d:%02d:%02d\n", stamp / 60, stamp % 60, time % 60);
|
|
}
|
|
} else {
|
|
fprintf(fil, "\t%02d:%02d:%02d%s", stamp / 60, stamp % 60, time % 60, text);
|
|
}
|
|
dirty=0;
|
|
lastStamp=stamp;
|
|
}
|
|
|
|
void logfileOut(int mask, const char *fmt, ...)
|
|
{ va_list ap;
|
|
char buf[8192], *p;
|
|
int l;
|
|
|
|
va_start(ap, fmt);
|
|
|
|
if (mask & LOG_STAT && statusBuf!=NULL) {
|
|
if (newLine) {
|
|
statusBuf[0]='\0';
|
|
newLine=0;
|
|
}
|
|
buf[statusSize]='\0';
|
|
vsprintf(buf, fmt, ap);
|
|
assert(buf[statusSize]=='\0'); /* check for overflow */
|
|
if (buf[0]=='@') {
|
|
if (buf[1]==' ') {
|
|
str_ncat(statusBuf, buf+2, statusSize);
|
|
} else {
|
|
str_ncat(statusBuf, buf+1, statusSize);
|
|
}
|
|
} else {
|
|
str_ncat(statusBuf, buf, statusSize);
|
|
}
|
|
p=strchr(statusBuf, '\n');
|
|
if (p!=NULL) {
|
|
newLine=1;
|
|
*p='\0';
|
|
}
|
|
}
|
|
if (logfileOutRtn!=NULL) {
|
|
vsprintf(buf, fmt, ap); /* does not check for overflow! */
|
|
logfileOutRtn(mask, buf);
|
|
}
|
|
if (writeAll) {
|
|
vfprintf(fil, fmt, ap);
|
|
wrtMask=LOG_ALL;
|
|
} else if ((mask | LOG_NET) != LOG_NET) { /* do not store LOG_NET info */
|
|
if (eptr!=NULL) {
|
|
if (eptr-ebuf > sizeof(ebuf)-512) {
|
|
sprintf(eptr, "... buffer full ... \1\1");
|
|
eptr=NULL;
|
|
} else {
|
|
vsprintf(eptr, fmt, ap);
|
|
p=strchr(eptr, '\1');
|
|
if (p==NULL) {
|
|
l=strlen(eptr);
|
|
if (l>256) {
|
|
sprintf(buf, "unusual long output %.32s... (%d chars)\n", eptr, l);
|
|
logfileStamp(buf);
|
|
}
|
|
eptr+=l;
|
|
} else {
|
|
eptr=p; /* is in fact an error */
|
|
}
|
|
eptr[0]='\1'; /* put \1 as separator between blocks */
|
|
eptr[1]=mask & 31;
|
|
eptr[2]='\0';
|
|
eptr+=2;
|
|
}
|
|
}
|
|
wrtMask=wrtMask | mask;
|
|
}
|
|
va_end(ap);
|
|
}
|
|
|
|
void logfileMask(int mask) {
|
|
logMask=logMask | mask;
|
|
}
|
|
|
|
void logfileWrite0(int mask) {
|
|
char *s, *next;
|
|
|
|
logMask=logMask | mask;
|
|
if (dirty) logfileStamp(NULL); /* there was something written since last time */
|
|
|
|
s=ebuf;
|
|
if (writeAll || (*s!='\0' && (wrtMask & logMask))) {
|
|
next=strchr(s, '\1');
|
|
while (next!=NULL) {
|
|
*next='\0';
|
|
next++;
|
|
if (*next & logMask) {
|
|
if (*s=='@') { /* write out time */
|
|
logfileStamp(s+1);
|
|
} else {
|
|
logfileStamp(NULL); /* write stamp before write something */
|
|
fprintf(fil, "%s", s);
|
|
dirty=1;
|
|
}
|
|
}
|
|
s=next+1;
|
|
next=strchr(s, '\1');
|
|
}
|
|
}
|
|
ebuf[0]='\0';
|
|
eptr=&ebuf[0];
|
|
logMask=0;
|
|
wrtMask=0;
|
|
}
|
|
|
|
void logfileScan(int date, void (*scanLine)(void*, char*), void *arg) {
|
|
FILE *sFile;
|
|
char buf[256], *res;
|
|
|
|
if (date == openDate) {
|
|
sFile=fil;
|
|
rewind(sFile);
|
|
} else {
|
|
sprintf(buf, "%s%02d-%02d.log", lnam, date % 10000 / 100, date % 100);
|
|
sFile=fopen(buf, "r+");
|
|
if (sFile==NULL) return;
|
|
}
|
|
res=fgets(buf, sizeof(buf), sFile);
|
|
while (res!=NULL) {
|
|
if (res[0]=='\t') {
|
|
scanLine(arg, res+1);
|
|
}
|
|
res=fgets(buf, sizeof(buf), sFile);
|
|
}
|
|
if (sFile==fil) {
|
|
fseek(fil, 0, SEEK_END);
|
|
} else {
|
|
fclose(sFile);
|
|
}
|
|
}
|
|
|
|
void logfileWrite(int mask) {
|
|
logfileWrite0(mask);
|
|
fflush(fil);
|
|
}
|
|
|
|
void logfileShowErr(char *text)
|
|
{
|
|
logfileWrite0(LOG_ALL); /* write all */
|
|
ErrShow(text);
|
|
fflush(fil);
|
|
}
|
|
|
|
void logfileClose()
|
|
{
|
|
logfileWrite0(LOG_MAIN+LOG_INFO);
|
|
lastStamp=-2;
|
|
logfileOut(LOG_MAIN, "closed\n");
|
|
logfileStamp(NULL);
|
|
if (fil!=NULL) { fclose(fil); fil=NULL; }
|
|
filnam[0]='\0';
|
|
}
|
|
|
|
void logfileOutBuf(int mask, StrBuf *buf)
|
|
{ char str[256];
|
|
int rd0;
|
|
char *ret;
|
|
|
|
rd0=buf->rdpos;
|
|
if (buf->rdpos < 0 || buf->rdpos >= buf->dsize
|
|
|| buf->wrpos < 0 || buf->wrpos >= buf->dsize) {
|
|
logfileOut(mask, "<buffer corrupt>"); return;
|
|
}
|
|
while (!StrEnd(buf)) {
|
|
ret=StrGet(buf, str, '\0');
|
|
if (ret==NULL) {
|
|
ret="...";
|
|
buf->rdpos=buf->wrpos;
|
|
}
|
|
if (ret[0]<32 && ret[0]>0) {
|
|
logfileOut(mask, "[%d]%s;", ret[0], ret+1);
|
|
} else {
|
|
logfileOut(mask, "%s;", ret);
|
|
}
|
|
}
|
|
buf->rdpos=rd0;
|
|
}
|
|
|
|
int logfileLength(void) {
|
|
char lin[256];
|
|
int l, ll;
|
|
|
|
if (logfileStd || fil==NULL) return 0;
|
|
fseek(fil, lastpos, SEEK_SET);
|
|
ll=lastpos;
|
|
l=lastline;
|
|
while (NULL!=fgets(lin, sizeof(lin), fil)) {
|
|
lastpos=ll;
|
|
ll=ftell(fil);
|
|
lastline=l;
|
|
l++;
|
|
}
|
|
return(lastline);
|
|
}
|
|
|
|
long int logfilePos(int n) {
|
|
/* set file to the start of n-th last line n, if n<0 then position to the -n-th line */
|
|
int i;
|
|
char lin[256];
|
|
|
|
if (logfileStd || fil==NULL) return 0;
|
|
if (n>0) {
|
|
n=logfileLength()-n+1;
|
|
} else {
|
|
n=-n;
|
|
}
|
|
fseek(fil, 0, SEEK_SET);
|
|
for (i=1; i<n; i++) {
|
|
if (NULL==fgets(lin, sizeof(lin), fil)) return ftell(fil);
|
|
}
|
|
return ftell(fil);
|
|
}
|
|
|
|
|
|
long int logfileGetLines(long int pos, int linmax, char *line, int len_line) {
|
|
int l,i;
|
|
if (logfileStd || fil==NULL) {
|
|
line[0]='\0';
|
|
return 0;
|
|
}
|
|
l=0;
|
|
fseek(fil, pos, SEEK_SET);
|
|
for (i=0; i<linmax; i++) {
|
|
if (NULL==fgets(line+l, len_line-l, fil)) {
|
|
line[l]='\0';
|
|
return ftell(fil);
|
|
}
|
|
l=strlen(line);
|
|
}
|
|
pos=ftell(fil);
|
|
fseek(fil, 0, SEEK_END);
|
|
return pos;
|
|
}
|