2020-10-08 00:03:59 +08:00
|
|
|
/*
|
|
|
|
3APA3A simpliest proxy server
|
2020-10-09 20:42:34 +08:00
|
|
|
(c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru>
|
2020-10-08 00:03:59 +08:00
|
|
|
|
|
|
|
please read License Agreement
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "proxy.h"
|
2020-10-09 20:42:34 +08:00
|
|
|
pthread_mutex_t log_mutex;
|
2020-10-08 00:03:59 +08:00
|
|
|
int havelog = 0;
|
|
|
|
|
2020-10-09 20:42:34 +08:00
|
|
|
|
|
|
|
struct clientparam logparam;
|
|
|
|
struct srvparam logsrv;
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
struct LOGGER;
|
|
|
|
|
|
|
|
void(*prelog)(struct clientparam * param) = NULL;
|
|
|
|
|
|
|
|
#ifdef WITHMAIN
|
|
|
|
#define HAVERADIUS 0
|
|
|
|
#define HAVESQL 0
|
|
|
|
#else
|
|
|
|
int raddobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s);
|
|
|
|
void logradius(const char * buf, int len, struct LOGGER *logger);
|
|
|
|
#define HAVERADIUS 1
|
|
|
|
|
|
|
|
#ifndef NOODBC
|
|
|
|
#undef HAVESQL
|
|
|
|
#define HAVESQL 1
|
|
|
|
static int sqlinit(const char * selector, int logtype, struct LOGGER *logger);
|
|
|
|
static void sqllog(const char * buf, int len, struct LOGGER *logger);
|
|
|
|
static void sqlrotate(struct LOGGER *logger);
|
|
|
|
static void sqlclose(struct LOGGER *logger);
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
#define HAVESYSLOG 0
|
|
|
|
#else
|
|
|
|
#define HAVESYSLOG 1
|
|
|
|
static int sysloginit(const char * selector, int logtype, struct LOGGER *logger);
|
|
|
|
static void logsyslog(const char * buf, int len, struct LOGGER *logger);
|
|
|
|
static void syslogrotate(struct LOGGER *logger);
|
|
|
|
static void syslogclose(struct LOGGER *logger);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static int stdloginit(const char * selector, int logtype, struct LOGGER *logger);
|
|
|
|
static void stdlog(const char * buf, int len, struct LOGGER *logger);
|
|
|
|
static void stdlogrotate(struct LOGGER *logger);
|
|
|
|
static void stdlogclose(struct LOGGER *logger);
|
|
|
|
|
2020-10-09 20:42:34 +08:00
|
|
|
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
struct LOGFUNC logfuncs = {
|
|
|
|
#if HAVESYSLOG > 0
|
|
|
|
{logfuncs+1+HAVESYSLOG, sysloginit, stddobuf, logsyslog, syslogrotate, syslogclose, "@"},
|
|
|
|
#endif
|
|
|
|
#if HAVERADIUS > 0
|
|
|
|
{logfuncs+1+HAVESYSLOG+HAVERADIUS, NULL, raddobuf, logradius, NULL, NULL, "radius"},
|
|
|
|
#endif
|
|
|
|
#if HAVESQL > 0
|
|
|
|
{logfuncs+1+HAVESYSLOG+HAVERADIUS+HAVESQL, sqlinit, sqldobuf, sqllog, sqlrotate, sqlclose, "&"},
|
|
|
|
#endif
|
|
|
|
{NULL, stdloginit, stddobuf, stdlog, stdlogrotate, stdlogclose, ""}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
struct LOGGER *loggers = NULL;
|
|
|
|
|
|
|
|
struct stdlogdata{
|
|
|
|
FILE *fp;
|
|
|
|
} errld= {stderr};
|
|
|
|
|
|
|
|
struct LOGGER {
|
|
|
|
char * selector;
|
|
|
|
void * data;
|
|
|
|
struct LOGFUNC *logfunc;
|
|
|
|
int rotate;
|
|
|
|
time_t rotated;
|
|
|
|
int registered;
|
|
|
|
} errlogger = {"errlogger", &errld, logfuncs+1+HAVESYSLOG+HAVERADIUS+HAVESQL, 0, 0, 1};
|
|
|
|
|
|
|
|
|
|
|
|
void initlog(void){
|
|
|
|
srvinit(&logsrv, &logparam);
|
|
|
|
pthread_mutex_init(&log_mutex, NULL);
|
|
|
|
}
|
|
|
|
|
2020-10-09 20:42:34 +08:00
|
|
|
void dolog(struct clientparam * param, const unsigned char *s){
|
|
|
|
static int init = 0;
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
/* TODO: dobuf */
|
|
|
|
/* TODO: spooling */
|
|
|
|
if(!param){
|
|
|
|
stdlog(s, strlen(s), &stdlogger);
|
2020-10-09 20:42:34 +08:00
|
|
|
}
|
2020-10-14 21:10:35 +08:00
|
|
|
else if(!param->nolog && param->srv->logtarget){
|
|
|
|
if(prelog)prelog(param);
|
|
|
|
param->srv->logfunc(param, s);
|
|
|
|
}
|
|
|
|
if(param->trafcountfunc)(*param->trafcountfunc)(param);
|
|
|
|
clearstat(param);
|
2020-10-09 20:42:34 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-08 00:03:59 +08:00
|
|
|
void clearstat(struct clientparam * param) {
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
struct timeb tb;
|
|
|
|
|
|
|
|
ftime(&tb);
|
|
|
|
param->time_start = (time_t)tb.time;
|
|
|
|
param->msec_start = (unsigned)tb.millitm;
|
|
|
|
|
|
|
|
#else
|
|
|
|
struct timeval tv;
|
|
|
|
struct timezone tz;
|
|
|
|
gettimeofday(&tv, &tz);
|
|
|
|
|
|
|
|
param->time_start = (time_t)tv.tv_sec;
|
|
|
|
param->msec_start = (tv.tv_usec / 1000);
|
|
|
|
#endif
|
|
|
|
param->statscli64 = param->statssrv64 = param->nreads = param->nwrites =
|
|
|
|
param->nconnects = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
char months[12][4] = {
|
|
|
|
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec, struct tm* tm, char * format){
|
|
|
|
int i, j;
|
|
|
|
int len;
|
|
|
|
time_t sec;
|
|
|
|
unsigned msec;
|
|
|
|
|
|
|
|
long timezone;
|
|
|
|
unsigned delay;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32
|
|
|
|
struct timeb tb;
|
|
|
|
|
|
|
|
ftime(&tb);
|
|
|
|
sec = (time_t)tb.time;
|
|
|
|
msec = (unsigned)tb.millitm;
|
|
|
|
timezone = tm->tm_isdst*60 - tb.timezone;
|
|
|
|
|
|
|
|
#else
|
|
|
|
struct timeval tv;
|
|
|
|
struct timezone tz;
|
|
|
|
gettimeofday(&tv, &tz);
|
|
|
|
|
|
|
|
sec = (time_t)tv.tv_sec;
|
|
|
|
msec = tv.tv_usec / 1000;
|
|
|
|
#ifdef _SOLARIS
|
|
|
|
timezone = -altzone / 60;
|
|
|
|
#else
|
|
|
|
timezone = tm->tm_gmtoff / 60;
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
delay = param->time_start?((unsigned) ((sec - param->time_start))*1000 + msec) - param->msec_start : 0;
|
|
|
|
*buf = 0;
|
|
|
|
for(i=0, j=0; format[j] && i < 4040; j++){
|
|
|
|
if(format[j] == '%' && format[j+1]){
|
|
|
|
j++;
|
|
|
|
switch(format[j]){
|
|
|
|
case '%':
|
|
|
|
buf[i++] = '%';
|
|
|
|
break;
|
|
|
|
case 'y':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_year%100);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 'Y':
|
|
|
|
sprintf((char *)buf+i, "%.4d", tm->tm_year+1900);
|
|
|
|
i+=4;
|
|
|
|
break;
|
|
|
|
case 'm':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_mon+1);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 'o':
|
|
|
|
sprintf((char *)buf+i, "%s", months[tm->tm_mon]);
|
|
|
|
i+=3;
|
|
|
|
break;
|
|
|
|
case 'd':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_mday);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 'H':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_hour);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 'M':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_min);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 'S':
|
|
|
|
sprintf((char *)buf+i, "%.2d", tm->tm_sec);
|
|
|
|
i+=2;
|
|
|
|
break;
|
|
|
|
case 't':
|
|
|
|
sprintf((char *)buf+i, "%.10u", (unsigned)sec);
|
|
|
|
i+=10;
|
|
|
|
break;
|
|
|
|
case 'b':
|
|
|
|
i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statscli64 * 1000./delay):0);
|
|
|
|
break;
|
|
|
|
case 'B':
|
|
|
|
i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statssrv64 * 1000./delay):0);
|
|
|
|
break;
|
|
|
|
case 'D':
|
|
|
|
i+=sprintf((char *)buf+i, "%u", delay);
|
|
|
|
break;
|
|
|
|
case '.':
|
|
|
|
sprintf((char *)buf+i, "%.3u", msec);
|
|
|
|
i+=3;
|
|
|
|
break;
|
|
|
|
case 'z':
|
|
|
|
sprintf((char *)buf+i, "%+.2ld%.2u", timezone / 60, (unsigned)(timezone%60));
|
|
|
|
i+=5;
|
|
|
|
break;
|
|
|
|
case 'U':
|
|
|
|
if(param->username && *param->username){
|
|
|
|
for(len = 0; i< 4000 && param->username[len]; len++){
|
|
|
|
buf[i] = param->username[len];
|
|
|
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
|
|
|
if(doublec && strchr((char *)doublec, buf[i])) {
|
|
|
|
buf[i+1] = buf[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
buf[i++] = '-';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'n':
|
|
|
|
len = param->hostname? (int)strlen((char *)param->hostname) : 0;
|
|
|
|
if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < 256; len++, i++){
|
|
|
|
buf[i] = param->hostname[len];
|
|
|
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
|
|
|
if(doublec && strchr((char *)doublec, buf[i])) {
|
|
|
|
buf[i+1] = buf[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
buf[i++] = '[';
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + i, 64);
|
|
|
|
buf[i++] = ']';
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 'N':
|
|
|
|
if(param->service < 15) {
|
|
|
|
len = (conf.stringtable)? (int)strlen((char *)conf.stringtable[SERVICES + param->service]) : 0;
|
|
|
|
if(len > 20) len = 20;
|
|
|
|
memcpy(buf+i, (len)?conf.stringtable[SERVICES + param->service]:(unsigned char*)"-", (len)?len:1);
|
|
|
|
i += (len)?len:1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'E':
|
|
|
|
sprintf((char *)buf+i, "%.05d", param->res);
|
|
|
|
i += 5;
|
|
|
|
break;
|
|
|
|
case 'T':
|
|
|
|
if(s){
|
|
|
|
for(len = 0; i<4000 && s[len]; len++){
|
|
|
|
buf[i] = s[len];
|
|
|
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
|
|
|
if(doublec && strchr((char *)doublec, buf[i])) {
|
|
|
|
buf[i+1] = buf[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 'e':
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->sinsl), SAADDR(¶m->sinsl), (char *)buf + i, 64);
|
|
|
|
break;
|
|
|
|
case 'i':
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->sincl), SAADDR(¶m->sincl), (char *)buf + i, 64);
|
|
|
|
break;
|
|
|
|
case 'C':
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->sincr), SAADDR(¶m->sincr), (char *)buf + i, 64);
|
|
|
|
break;
|
|
|
|
case 'R':
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->sinsr), SAADDR(¶m->sinsr), (char *)buf + i, 64);
|
|
|
|
break;
|
|
|
|
case 'Q':
|
|
|
|
i += myinet_ntop(*SAFAMILY(¶m->req), SAADDR(¶m->req), (char *)buf + i, 64);
|
|
|
|
break;
|
|
|
|
case 'p':
|
|
|
|
sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(¶m->srv->intsa)));
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'c':
|
|
|
|
sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(¶m->sincr)));
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'r':
|
|
|
|
sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(¶m->sinsr)));
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'q':
|
|
|
|
sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(¶m->req)));
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'L':
|
|
|
|
sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->cycles);
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'I':
|
|
|
|
sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statssrv64);
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'O':
|
|
|
|
sprintf((char *)buf+i, "%"PRINTF_INT64_MODIFIER"u", param->statscli64);
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case 'h':
|
|
|
|
sprintf((char *)buf+i, "%d", param->redirected);
|
|
|
|
i += (int)strlen((char *)buf+i);
|
|
|
|
break;
|
|
|
|
case '1':
|
|
|
|
case '2':
|
|
|
|
case '3':
|
|
|
|
case '4':
|
|
|
|
case '5':
|
|
|
|
case '6':
|
|
|
|
case '7':
|
|
|
|
case '8':
|
|
|
|
case '9':
|
|
|
|
{
|
|
|
|
int k, pmin=0, pmax=0;
|
|
|
|
for (k = j; isnumber(format[k]); k++);
|
|
|
|
if(format[k] == '-' && isnumber(format[k+1])){
|
|
|
|
pmin = atoi(format + j) - 1;
|
|
|
|
k++;
|
|
|
|
pmax = atoi(format + k) -1;
|
|
|
|
for (; isnumber(format[k]); k++);
|
|
|
|
j = k;
|
|
|
|
}
|
|
|
|
if(!s || format[k]!='T') break;
|
|
|
|
for(k = 0, len = 0; s[len] && i < 4000; len++){
|
|
|
|
if(isspace(s[len])){
|
|
|
|
k++;
|
|
|
|
while(isspace(s[len+1]))len++;
|
|
|
|
if(k == pmin) continue;
|
|
|
|
}
|
|
|
|
if(k>=pmin && k<=pmax) {
|
|
|
|
buf[i] = s[len];
|
|
|
|
if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
|
|
|
|
if(doublec && strchr((char *)doublec, buf[i])) {
|
|
|
|
buf[i+1] = buf[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
buf[i++] = format[j];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else buf[i++] = format[j];
|
|
|
|
}
|
|
|
|
buf[i] = 0;
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
int dobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s, const unsigned char * doublec){
|
|
|
|
struct tm* tm;
|
|
|
|
int i;
|
|
|
|
char * format;
|
|
|
|
time_t t;
|
|
|
|
|
|
|
|
time(&t);
|
|
|
|
if(!param) return 0;
|
|
|
|
format = param->srv->logformat?(char *)param->srv->logformat : DEFLOGFORMAT;
|
|
|
|
tm = (*format == 'G' || *format == 'g')?
|
|
|
|
gmtime(&t) : localtime(&t);
|
|
|
|
i = dobuf2(param, buf, s, doublec, tm, format + 1);
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
|
|
|
|
static int stdloginit(const char * selector, int logtype, struct LOGGER *logger){
|
|
|
|
char tmpuf[1024];
|
|
|
|
struct stdlogdata *lp;
|
|
|
|
lp = myalloc(sizeof(struct stdlogdata));
|
|
|
|
if(!lp) return 1;
|
|
|
|
logger->data = lp;
|
|
|
|
if(!selector || !*selector){
|
|
|
|
logger-rotate = NONE;
|
|
|
|
lp->fp = stdout;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
logger->rotate = logtype;
|
|
|
|
lp->fp = fopen((char *)dologname (tmpbuf, conf.logname, NULL, logtype, time(NULL)), "a");
|
|
|
|
if(!lp->fp){
|
|
|
|
myfree(lp);
|
|
|
|
return(2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int stddobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s){
|
|
|
|
return dobuf(param, buf, s, NULL);
|
2020-10-08 00:03:59 +08:00
|
|
|
}
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
void stdlog(struct clientparam * param, const unsigned char *s, struct LOGGER *logger) {
|
|
|
|
FILE *log = (struct stdlogdata *)logger->data;
|
2020-10-08 00:03:59 +08:00
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
fprintf(log, "%s\n", buf);
|
|
|
|
if(log == stdout || log == stderr)fflush(log);
|
2020-10-08 00:03:59 +08:00
|
|
|
}
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
static void stdlogrotate(struct LOGGER *logger){
|
|
|
|
char tmpuf[1024];
|
|
|
|
struct stdlogdata *lp = (struct stdlogdata)logger->data;
|
|
|
|
if(lp->fp) lp->fp = freopen((char *)dologname (tmpbuf, logger->selector, NULL, logger->rotate, conf.time), "a", lp->fp);
|
|
|
|
else lp->fp = fopen((char *)dologname (tmpbuf, logger->selector, NULL, logger->rotate, conf.time), "a");
|
|
|
|
conf.logtime = conf.time;
|
|
|
|
if(logger->rotate) {
|
|
|
|
int t;
|
|
|
|
t = 1;
|
|
|
|
switch(logger->rotate){
|
|
|
|
case ANNUALLY:
|
|
|
|
t = t * 12;
|
|
|
|
case MONTHLY:
|
|
|
|
t = t * 4;
|
|
|
|
case WEEKLY:
|
|
|
|
t = t * 7;
|
|
|
|
case DAILY:
|
|
|
|
t = t * 24;
|
|
|
|
case HOURLY:
|
|
|
|
t = t * 60;
|
|
|
|
case MINUTELY:
|
|
|
|
t = t * 60;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
dologname (tmpbuf, logger->selector, (conf.archiver)?conf.archiver[1]:NULL, logger->rotate, (conf.logtime - t * conf.rotate));
|
|
|
|
remove ((char *) tmpbuf);
|
|
|
|
if(conf.archiver) {
|
|
|
|
int i;
|
|
|
|
*tmpbuf = 0;
|
|
|
|
for(i = 2; i < conf.archiverc && strlen((char *)tmpbuf) < 512; i++){
|
|
|
|
strcat((char *)tmpbuf, " ");
|
|
|
|
if(!strcmp((char *)conf.archiver[i], "%A")){
|
|
|
|
strcat((char *)tmpbuf, "\"");
|
|
|
|
dologname (tmpbuf + strlen((char *)tmpbuf), logger->selector, conf.archiver[1], logger->rotate, (conf.logtime - t));
|
|
|
|
strcat((char *)tmpbuf, "\"");
|
|
|
|
}
|
|
|
|
else if(!strcmp((char *)conf.archiver[i], "%F")){
|
|
|
|
strcat((char *)tmpbuf, "\"");
|
|
|
|
dologname (tmpbuf+strlen((char *)tmpbuf), logger->selector, NULL, logger->rotate, (conf.logtime-t));
|
|
|
|
strcat((char *)tmpbuf, "\"");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
strcat((char *)tmpbuf, (char *)conf.archiver[i]);
|
|
|
|
}
|
|
|
|
system((char *)tmpbuf+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void stdlogclose(struct LOGGER *logger){
|
|
|
|
fclose(((struct stdlogdata *)logger->data)->fp);
|
|
|
|
myfree(((struct stdlogdata *)logger->data)->fp);
|
2020-10-08 00:03:59 +08:00
|
|
|
}
|
2020-10-14 21:10:35 +08:00
|
|
|
|
|
|
|
#if HAVESYSLOG > 0
|
|
|
|
|
|
|
|
static int sysloginit(const char * selector, int logtype, struct LOGGER *logger){
|
|
|
|
openlog(selector+1, LOG_PID, LOG_DAEMON);
|
|
|
|
logger->rotate = logtype;
|
|
|
|
logger->data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void logsyslog(const char * buf, int len, struct LOGGER *logger) {
|
|
|
|
|
|
|
|
syslog((param->res >= 90 && param->res<=99)?LOG_NOTICE:(param->res?LOG_WARNING:LOG_INFO), "%s", buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void syslogrotate(struct LOGGER *logger){
|
|
|
|
closelog();
|
|
|
|
openlog(logger->selector+1, LOG_PID, LOG_DAEMON);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void syslogclose(struct LOGGER *logger){
|
|
|
|
closelog();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-10-08 00:03:59 +08:00
|
|
|
#endif
|
|
|
|
|
2020-10-14 21:10:35 +08:00
|
|
|
#if HAVESQL > 0
|
|
|
|
|
|
|
|
struct sqldata {
|
|
|
|
SQLHENV henv;
|
|
|
|
SQLHSTMT hstmt;
|
|
|
|
SQLHDBC hdbc;
|
|
|
|
int attempt;
|
|
|
|
time_t attempt_time;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int sqlinit(const char * selector, int logtype, struct LOGGER *logger);
|
|
|
|
static void sqllog(struct clientparam * param, const unsigned char *s, LOGGER *logger);
|
|
|
|
static void sqlrotate(struct LOGGER *logger);
|
|
|
|
|
|
|
|
|
|
|
|
int sqlinit2(struct sqldata * sd, char * source){
|
|
|
|
SQLRETURN retcode;
|
|
|
|
char * datasource;
|
|
|
|
char * username;
|
|
|
|
char * password;
|
|
|
|
char * string;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sd->henv);
|
|
|
|
if (!henv || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)){
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
retcode = SQLSetEnvAttr(sd->henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
|
|
|
|
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
|
|
|
|
ret = 2;
|
|
|
|
goto CLOSEENV:
|
|
|
|
}
|
|
|
|
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &sd->hdbc);
|
|
|
|
if (!sd->hdbc || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)) {
|
|
|
|
ret = 3;
|
|
|
|
goto CLOSEENV:
|
|
|
|
}
|
|
|
|
SQLSetConnectAttr(sd->hdbc, SQL_LOGIN_TIMEOUT, (void*)15, 0);
|
|
|
|
|
|
|
|
string = mystrdup(source);
|
|
|
|
if(!string) goto CLOSEHDBC;
|
|
|
|
datasource = strtok(string, ",");
|
|
|
|
username = strtok(NULL, ",");
|
|
|
|
password = strtok(NULL, ",");
|
|
|
|
|
|
|
|
|
|
|
|
/* Connect to data source */
|
|
|
|
retcode = SQLConnect(sd->hdbc, (SQLCHAR*) datasource, (SQLSMALLINT)strlen(datasource),
|
|
|
|
(SQLCHAR*) username, (SQLSMALLINT)((username)?strlen(username):0),
|
|
|
|
(SQLCHAR*) password, (SQLSMALLINT)((password)?strlen(password):0));
|
|
|
|
|
|
|
|
myfree(string);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
|
|
|
|
ret = 4;
|
|
|
|
goto CLOSEHDBC;
|
|
|
|
}
|
|
|
|
|
|
|
|
retcode = SQLAllocHandle(SQL_HANDLE_STMT, sd->hdbc, &sd->hstmt);
|
|
|
|
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
|
|
|
|
sd->hstmt = 0;
|
|
|
|
ret = 5;
|
|
|
|
goto CLOSEHDBC;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
CLOSEHDBC:
|
|
|
|
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
|
|
|
sd->hdbc = 0;
|
|
|
|
CLOSEENV:
|
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, henv);
|
|
|
|
sd->henv = 0;
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sqlinit(const char * selector, int logtype, struct LOGGER *logger){
|
|
|
|
struct sqldata *sd;
|
|
|
|
int res
|
|
|
|
|
|
|
|
logger->rotate = logtype;
|
|
|
|
sd = (struct sqldata *)myalloc(sizeof(struct sqldata));
|
|
|
|
memset(sd, 0, sizeof(struct sqldata));
|
|
|
|
loger->data = sd;
|
|
|
|
if(!(res = sqlinit2(sd, selector+1))) {
|
|
|
|
myfree(sd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int sqldobuf(struct clientparam * param, unsigned char * buf, const unsigned char *s){
|
|
|
|
return dobuf(param, buf, s, (unsigned char *)"\'");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void sqllog(const char * buf, int len, struct LOGGER *logger){
|
|
|
|
SQLRETURN ret;
|
|
|
|
struct sqldata *sd = (struct sqldata *)logger->data;
|
|
|
|
|
|
|
|
|
|
|
|
if(sd->attempt > 5){
|
|
|
|
if (conf.time - sd->attempt_time < 180){
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(sd->attempt){
|
|
|
|
sd->attempt++;
|
|
|
|
sqlrotate(logger);
|
|
|
|
|
|
|
|
if(!sd->hstmt){
|
|
|
|
sd->attempt_time=conf.time;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = SQLExecDirect(sd->hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
|
|
|
|
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
|
|
|
|
sqlrotate(logger);
|
|
|
|
if(sd->hstmt) {
|
|
|
|
ret = SQLExecDirect(hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
|
|
|
|
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
|
|
|
|
sd->attempt++;
|
|
|
|
sd->attempt_time=conf.time;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sd->attempt=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sqlrotate(struct LOGGER *logger){
|
|
|
|
struct sqldata * sd;
|
|
|
|
sqlclose(logger);
|
|
|
|
sd = (struct sqldata *)myalloc(sizeof(struct sqldata));
|
|
|
|
memset(sd, 0, sizeof(struct sqldata));
|
|
|
|
loger->data = sd;
|
|
|
|
sqlinit2(sd, logger->selector+1)
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sqlclose(struct LOGGER *logger){
|
|
|
|
struct sqldata *sd = (struct sqldata *)loger->data;
|
|
|
|
if(sd->hstmt) {
|
|
|
|
SQLFreeHandle(SQL_HANDLE_STMT, sd->hstmt);
|
|
|
|
sd->hstmt = NULL;
|
|
|
|
}
|
|
|
|
if(sd->hdbc){
|
|
|
|
SQLDisconnect(sd->hdbc);
|
|
|
|
SQLFreeHandle(SQL_HANDLE_DBC, sd->hdbc);
|
|
|
|
sd->hdbc = NULL;
|
|
|
|
}
|
|
|
|
if(sd->henv) {
|
|
|
|
SQLFreeHandle(SQL_HANDLE_ENV, sd->henv);
|
|
|
|
sd->henv = NULL;
|
|
|
|
}
|
|
|
|
myfree(sd);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|