log.c 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. /*
  2. 3APA3A simpliest proxy server
  3. (c) 2002-2020 by Vladimir Dubrovin <3proxy@3proxy.ru>
  4. please read License Agreement
  5. */
  6. #include "proxy.h"
  7. pthread_mutex_t log_mutex;
  8. #ifdef _WIN32
  9. HANDLE log_sem;
  10. #else
  11. sem_t log_sem;
  12. #endif
  13. #define MAXLOG 1024
  14. #define EVENTSIZE (4096 - sizeof(void *))
  15. #define LOGBUFSIZE (EVENTSIZE - sizeof(struct logevent))
  16. #define MAX_SEM_COUNT 256
  17. typedef enum {
  18. REGISTER,
  19. UNREGISTER,
  20. LOG,
  21. FLUSH,
  22. FREEPARAM
  23. } EVENTTYPE;
  24. static int loginit = 0;
  25. struct clientparam logparam;
  26. struct srvparam logsrv;
  27. struct LOGGER;
  28. struct logevent {
  29. struct logevent *next;
  30. struct LOGGER *log;
  31. EVENTTYPE event;
  32. int inbuf;
  33. struct clientparam *param;
  34. char * logstring;
  35. char buf[1];
  36. } *logtail=NULL, *loghead=NULL;
  37. static void delayflushlogs(void);
  38. static void delayunregisterlog (struct LOGGER * log);
  39. static void delayregisterlog (struct LOGGER * log);
  40. static void delaydolog(struct logevent *evt);
  41. static void delayfreeparam(struct clientparam *param);
  42. static void initlog2(void);
  43. void logpush(struct logevent *evt);
  44. #ifdef WITHMAIN
  45. #define HAVERADIUS 0
  46. #define HAVESQL 0
  47. #else
  48. #ifndef NORADIUS
  49. int raddobuf(struct clientparam * param, char * buf, int bufsize, const char *s);
  50. void logradius(const char * buf, int len, struct LOGGER *logger);
  51. #define HAVERADIUS 1
  52. #else
  53. #define HAVERADIUS 0
  54. #endif
  55. #ifndef NOODBC
  56. #define HAVESQL 1
  57. static int sqlinit(struct LOGGER *logger);
  58. static int sqldobuf(struct clientparam * param, char * buf, int bufsize, const char *s);
  59. static void sqllog(const char * buf, int len, struct LOGGER *logger);
  60. static void sqlrotate(struct LOGGER *logger);
  61. static void sqlclose(struct LOGGER *logger);
  62. #else
  63. #define HAVESQL 0
  64. #endif
  65. #endif
  66. #ifdef _WIN32
  67. #define HAVESYSLOG 0
  68. #else
  69. #define HAVESYSLOG 1
  70. static int sysloginit(struct LOGGER *logger);
  71. static void logsyslog(const char * buf, int len, struct LOGGER *logger);
  72. static void syslogrotate(struct LOGGER *logger);
  73. static void syslogclose(struct LOGGER *logger);
  74. #endif
  75. static int stdloginit(struct LOGGER *logger);
  76. static int stddobuf(struct clientparam * param, char * buf, int bufsize, const char *s);
  77. static void stdlog(const char * buf, int len, struct LOGGER *logger);
  78. static void stdlogrotate(struct LOGGER *logger);
  79. static void stdlogclose(struct LOGGER *logger);
  80. static void stdlogflush(struct LOGGER *logger);
  81. struct LOGFUNC stdlogfuncs[] = {
  82. #if HAVESYSLOG > 0
  83. {stdlogfuncs+1, sysloginit, stddobuf, logsyslog, syslogrotate, NULL, syslogclose, "@"},
  84. #endif
  85. #if HAVERADIUS > 0
  86. {stdlogfuncs+1+HAVESYSLOG, NULL, raddobuf, logradius, NULL, NULL, NULL, "radius"},
  87. #endif
  88. #if HAVESQL > 0
  89. {stdlogfuncs+1+HAVESYSLOG+HAVERADIUS, sqlinit, sqldobuf, sqllog, sqlrotate, NULL, sqlclose, "&"},
  90. #endif
  91. {NULL, stdloginit, stddobuf, stdlog, stdlogrotate, stdlogflush, stdlogclose, ""}
  92. };
  93. struct LOGFUNC *logfuncs = stdlogfuncs;
  94. struct stdlogdata{
  95. FILE *fp;
  96. } errld;
  97. struct LOGGER errlogger = {NULL, NULL, "stderr", &errld, stdlogfuncs+1+HAVESYSLOG+HAVERADIUS+HAVESQL, 0, 0, 1};
  98. struct LOGGER *loggers = &errlogger;
  99. static void delayflushlogs(void){
  100. struct LOGGER *log;
  101. for(log = loggers; log; log=log->next){
  102. if(log->logfunc && log->logfunc->flush)log->logfunc->flush(log);
  103. #ifndef WITHMAIN
  104. if(log->rotate && log->logfunc && log->logfunc->rotate && timechanged(log->rotated, conf.time, log->rotate)){
  105. log->logfunc->rotate(log);
  106. log->rotated = conf.time;
  107. }
  108. #endif
  109. }
  110. }
  111. void flushlogs(void){
  112. if(loginit){
  113. struct logevent * evt;
  114. evt = malloc(sizeof(struct logevent));
  115. evt->event = FLUSH;
  116. logpush(evt);
  117. }
  118. }
  119. void delayregisterlog(struct LOGGER *log){
  120. struct LOGFUNC *funcs;
  121. if(log->logfunc) return;
  122. for(funcs = logfuncs; funcs; funcs=funcs->next){
  123. if(!strncmp(log->selector, funcs->prefix, strlen(funcs->prefix))){
  124. if(funcs->init && funcs->init(log)) break;
  125. log->logfunc = funcs;
  126. log->rotated = conf.time;
  127. return;
  128. }
  129. }
  130. }
  131. struct LOGGER * registerlog(const char * logstring, int logtype){
  132. struct LOGGER *log;
  133. if(!logstring || !strcmp(logstring, "NUL") || !strcmp(logstring, "/dev/null")) return NULL;
  134. pthread_mutex_lock(&log_mutex);
  135. if(!loginit){
  136. initlog2();
  137. loginit = 1;
  138. }
  139. for(log = loggers; log; log=log->next){
  140. if(!strcmp(logstring, log->selector)){
  141. if(logtype >= 0) log->rotate = logtype;
  142. log->registered++;
  143. pthread_mutex_unlock(&log_mutex);
  144. return log;
  145. }
  146. }
  147. log = malloc(sizeof(struct LOGGER));
  148. if(!log) {
  149. pthread_mutex_unlock(&log_mutex);
  150. return NULL;
  151. }
  152. memset (log, 0, sizeof(struct LOGGER));
  153. log->selector = mystrdup(logstring);
  154. if(log->selector){
  155. struct logevent *evt;
  156. if(logtype)log->rotate = logtype;
  157. log->registered++;
  158. log->next = loggers;
  159. if (log->next)log->next->prev = log;
  160. loggers = log;
  161. pthread_mutex_unlock(&log_mutex);
  162. evt = malloc(sizeof(struct logevent));
  163. evt->event = REGISTER;
  164. evt->log = log;
  165. logpush(evt);
  166. return log;
  167. }
  168. pthread_mutex_unlock(&log_mutex);
  169. myfree(log);
  170. return NULL;
  171. }
  172. static void delayunregisterlog (struct LOGGER * log){
  173. if(log){
  174. pthread_mutex_lock(&log_mutex);
  175. log->registered--;
  176. if(!log->registered){
  177. if(log->prev)log->prev->next = log->next;
  178. else loggers = log->next;
  179. if(log->next)log->next->prev = log->prev;
  180. pthread_mutex_unlock(&log_mutex);
  181. if(log->logfunc){
  182. if(log->logfunc->flush) log->logfunc->flush(log);
  183. if(log->logfunc->close) log->logfunc->close(log);
  184. }
  185. myfree(log->selector);
  186. myfree(log);
  187. }
  188. else pthread_mutex_unlock(&log_mutex);
  189. }
  190. }
  191. void unregisterlog (struct LOGGER * log){
  192. struct logevent *evt;
  193. if(!log) return;
  194. evt = malloc(sizeof(struct logevent));
  195. evt->event = UNREGISTER;
  196. evt->log = log;
  197. logpush(evt);
  198. }
  199. #ifdef _WIN32
  200. DWORD WINAPI logthreadfunc(LPVOID p) {
  201. #else
  202. void * logthreadfunc (void *p) {
  203. #endif
  204. for(;;){
  205. struct logevent *evt;
  206. #ifdef _WIN32
  207. WaitForSingleObject(log_sem, INFINITE);
  208. #else
  209. sem_wait(&log_sem);
  210. #endif
  211. while(loghead){
  212. pthread_mutex_lock(&log_mutex);
  213. evt = loghead;
  214. loghead = evt->next;
  215. if(!loghead)logtail = NULL;
  216. pthread_mutex_unlock(&log_mutex);
  217. switch(evt->event){
  218. case REGISTER:
  219. delayregisterlog(evt->log);
  220. break;
  221. case UNREGISTER:
  222. delayunregisterlog(evt->log);
  223. break;
  224. case FLUSH:
  225. delayflushlogs();
  226. break;
  227. case LOG:
  228. delaydolog(evt);
  229. break;
  230. case FREEPARAM:
  231. delayfreeparam(evt->param);
  232. break;
  233. default:
  234. break;
  235. }
  236. myfree(evt);
  237. }
  238. }
  239. return 0;
  240. }
  241. void logpush(struct logevent *evt){
  242. pthread_mutex_lock(&log_mutex);
  243. if(!loginit){
  244. if(evt->event == FREEPARAM){
  245. delayfreeparam(evt->param);
  246. }
  247. myfree(evt);
  248. pthread_mutex_unlock(&log_mutex);
  249. return;
  250. }
  251. if(logtail) logtail->next = evt;
  252. logtail = evt;
  253. evt->next = NULL;
  254. if(!loghead)loghead = evt;
  255. pthread_mutex_unlock(&log_mutex);
  256. #ifdef _WIN32
  257. ReleaseSemaphore(log_sem, 1, NULL);
  258. #else
  259. sem_post(&log_sem);
  260. #endif
  261. }
  262. static void initlog2(void){
  263. pthread_t thread;
  264. #ifdef _WIN32
  265. HANDLE h;
  266. if(!(log_sem = CreateSemaphore(NULL, 0, MAX_SEM_COUNT, NULL))) exit(11);
  267. #ifndef _WINCE
  268. h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, 65536, (void *)logthreadfunc, NULL, 0, &thread);
  269. #else
  270. h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, 65536, (void *)logthreadfunc, NULL, 0, &thread);
  271. #endif
  272. if (h) {
  273. CloseHandle(h);
  274. }
  275. else {
  276. exit(10);
  277. }
  278. #else
  279. pthread_attr_t pa;
  280. pthread_attr_init(&pa);
  281. pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 1024*256);
  282. pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED);
  283. if(sem_init(&log_sem, 0, 0)) exit(11);
  284. if(pthread_create(&thread, &pa, logthreadfunc, NULL)) exit(10);
  285. #endif
  286. }
  287. void initlog(void){
  288. srvinit(&logsrv, &logparam);
  289. pthread_mutex_init(&log_mutex, NULL);
  290. errld.fp = stdout;
  291. }
  292. static void delaydolog(struct logevent *evt){
  293. if(!evt->log->logfunc || !evt->log->logfunc->log) return;
  294. if(evt->inbuf){
  295. evt->log->logfunc->log(evt->buf, evt->inbuf, evt->log);
  296. }
  297. else if(evt->param && evt->log->logfunc->dobuf){
  298. char buf[LOGBUFSIZE];
  299. evt->log->logfunc->log(buf, evt->log->logfunc->dobuf(evt->param, buf, LOGBUFSIZE, evt->logstring), evt->log);
  300. }
  301. }
  302. void dolog(struct clientparam * param, const char *s){
  303. static int init = 0;
  304. if(!param || !param->srv){
  305. stdlog(s, (int)strlen(s), &errlogger);
  306. return;
  307. }
  308. if(conf.prelog)conf.prelog(param);
  309. if(!param->nolog && param->srv->log) {
  310. struct logevent *evt;
  311. if(!param->srv->log->logfunc) {
  312. int slen =0, hlen=0, ulen=0;
  313. slen = s?(int)strlen(s)+1 : 0;
  314. hlen = param->hostname? (int)strlen(param->hostname)+1 : 0;
  315. ulen = param->username? (int)strlen(param->username)+1 : 0;
  316. if(!(evt = malloc(sizeof(struct logevent) + slen + ulen + hlen))) return;
  317. evt->inbuf = 0;
  318. evt->param=param;
  319. evt->logstring = NULL;
  320. if(slen){
  321. memcpy(evt->buf,s, slen);
  322. evt->logstring = evt->buf;
  323. }
  324. if(hlen){
  325. memcpy(evt->buf+slen,param->hostname, hlen);
  326. param->hostname = evt->buf + slen;
  327. }
  328. if(ulen){
  329. memcpy(evt->buf+slen+hlen,param->username, ulen);
  330. param->username = evt->buf + slen + hlen;
  331. }
  332. evt->event = LOG;
  333. evt->log = param->srv->log;
  334. logpush(evt);
  335. }
  336. else if (param->srv->log->logfunc->log){
  337. if(!(evt = malloc(param->srv->log->logfunc->dobuf?EVENTSIZE:sizeof(struct logevent)))) return;
  338. evt->inbuf = 0;
  339. evt->param = NULL;
  340. evt->logstring = NULL;
  341. if(param->srv->log->logfunc->dobuf){
  342. evt->inbuf = param->srv->log->logfunc->dobuf(param, evt->buf, LOGBUFSIZE, s);
  343. }
  344. evt->event = LOG;
  345. evt->log = param->srv->log;
  346. logpush(evt);
  347. }
  348. }
  349. if(param->trafcountfunc)(*param->trafcountfunc)(param);
  350. clearstat(param);
  351. }
  352. static void delayfreeparam(struct clientparam * param) {
  353. if(param->res == 2) return;
  354. if(param->ctrlsocksrv != INVALID_SOCKET && param->ctrlsocksrv != param->remsock) {
  355. so._shutdown(param->ctrlsocksrv, SHUT_RDWR);
  356. so._closesocket(param->ctrlsocksrv);
  357. }
  358. if(param->ctrlsock != INVALID_SOCKET && param->ctrlsock != param->clisock) {
  359. so._shutdown(param->ctrlsock, SHUT_RDWR);
  360. so._closesocket(param->ctrlsock);
  361. }
  362. if(param->remsock != INVALID_SOCKET) {
  363. so._shutdown(param->remsock, SHUT_RDWR);
  364. so._closesocket(param->remsock);
  365. }
  366. if(param->clisock != INVALID_SOCKET) {
  367. so._shutdown(param->clisock, SHUT_RDWR);
  368. so._closesocket(param->clisock);
  369. }
  370. myfree(param->clibuf);
  371. myfree(param->srvbuf);
  372. if(param->datfilterssrv) myfree(param->datfilterssrv);
  373. #ifndef STDMAIN
  374. if(param->reqfilters) myfree(param->reqfilters);
  375. if(param->hdrfilterscli) myfree(param->hdrfilterscli);
  376. if(param->hdrfilterssrv) myfree(param->hdrfilterssrv);
  377. if(param->predatfilters) myfree(param->predatfilters);
  378. if(param->datfilterscli) myfree(param->datfilterscli);
  379. if(param->filters){
  380. if(param->nfilters)while(param->nfilters--){
  381. if(param->filters[param->nfilters].filter->filter_clear)
  382. (*param->filters[param->nfilters].filter->filter_clear)(param->filters[param->nfilters].data);
  383. }
  384. myfree(param->filters);
  385. }
  386. if(conf.connlimiter && (param->res != 95 || param->remsock != INVALID_SOCKET)) stopconnlims(param);
  387. #endif
  388. if(param->srv){
  389. pthread_mutex_lock(&param->srv->counter_mutex);
  390. if(param->prev){
  391. param->prev->next = param->next;
  392. }
  393. else
  394. param->srv->child = param->next;
  395. if(param->next){
  396. param->next->prev = param->prev;
  397. }
  398. (param->srv->childcount)--;
  399. if(param->srv->service == S_ZOMBIE && !param->srv->child)srvpostfree(param->srv);
  400. pthread_mutex_unlock(&param->srv->counter_mutex);
  401. }
  402. if(param->hostname) myfree(param->hostname);
  403. if(param->username) myfree(param->username);
  404. if(param->password) myfree(param->password);
  405. if(param->extusername) myfree(param->extusername);
  406. if(param->extpassword) myfree(param->extpassword);
  407. myfree(param);
  408. }
  409. void freeparam(struct clientparam * param) {
  410. struct logevent *evt;
  411. evt = malloc(sizeof(struct logevent));
  412. evt->event = FREEPARAM;
  413. evt->param = param;
  414. logpush(evt);
  415. }
  416. void clearstat(struct clientparam * param) {
  417. #ifdef _WIN32
  418. struct timeb tb;
  419. ftime(&tb);
  420. param->time_start = (time_t)tb.time;
  421. param->msec_start = (unsigned)tb.millitm;
  422. #else
  423. struct timeval tv;
  424. struct timezone tz;
  425. gettimeofday(&tv, &tz);
  426. param->time_start = (time_t)tv.tv_sec;
  427. param->msec_start = (tv.tv_usec / 1000);
  428. #endif
  429. param->statscli64 = param->statssrv64 = param->nreads = param->nwrites =
  430. param->nconnects = 0;
  431. }
  432. char months[12][4] = {
  433. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  434. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  435. };
  436. char * dologname (char *buf, int bufsize, char *name, const char *ext, ROTATION lt, time_t t) {
  437. struct tm *ts;
  438. ts = localtime(&t);
  439. if(strchr((char *)name, '%')){
  440. dobuf2(&logparam, buf, bufsize - (ext?(int)strlen(ext):0), NULL, NULL, ts, (char *)name);
  441. }
  442. else switch(lt){
  443. case NONE:
  444. sprintf((char *)buf, "%s", name);
  445. break;
  446. case ANNUALLY:
  447. sprintf((char *)buf, "%s.%04d", name, ts->tm_year+1900);
  448. break;
  449. case MONTHLY:
  450. sprintf((char *)buf, "%s.%04d.%02d", name, ts->tm_year+1900, ts->tm_mon+1);
  451. break;
  452. case WEEKLY:
  453. t = t - (ts->tm_wday * (60*60*24));
  454. ts = localtime(&t);
  455. sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
  456. break;
  457. case DAILY:
  458. sprintf((char *)buf, "%s.%04d.%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday);
  459. break;
  460. case HOURLY:
  461. sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour);
  462. break;
  463. case MINUTELY:
  464. sprintf((char *)buf, "%s.%04d.%02d.%02d-%02d.%02d", name, ts->tm_year+1900, ts->tm_mon+1, ts->tm_mday, ts->tm_hour, ts->tm_min);
  465. break;
  466. default:
  467. break;
  468. }
  469. if(ext){
  470. strcat((char *)buf, ".");
  471. strcat((char *)buf, (char *)ext);
  472. }
  473. return buf;
  474. }
  475. int dobuf2(struct clientparam * param, char * buf, int bufsize, const char *s, const char * doublec, struct tm* tm, char * format){
  476. int i, j;
  477. int len;
  478. time_t sec;
  479. unsigned msec;
  480. long timezone;
  481. unsigned delay;
  482. #ifdef _WIN32
  483. struct timeb tb;
  484. ftime(&tb);
  485. sec = (time_t)tb.time;
  486. msec = (unsigned)tb.millitm;
  487. timezone = tm->tm_isdst*60 - tb.timezone;
  488. #else
  489. struct timeval tv;
  490. struct timezone tz;
  491. gettimeofday(&tv, &tz);
  492. sec = (time_t)tv.tv_sec;
  493. msec = tv.tv_usec / 1000;
  494. #ifdef _SOLARIS
  495. timezone = -altzone / 60;
  496. #else
  497. timezone = tm->tm_gmtoff / 60;
  498. #endif
  499. #endif
  500. delay = param->time_start?((unsigned) ((sec - param->time_start))*1000 + msec) - param->msec_start : 0;
  501. *buf = 0;
  502. for(i=0, j=0; format[j] && i < (bufsize-70); j++){
  503. if(format[j] == '%' && format[j+1]){
  504. j++;
  505. switch(format[j]){
  506. case '%':
  507. buf[i++] = '%';
  508. break;
  509. case 'y':
  510. sprintf((char *)buf+i, "%.2d", tm->tm_year%100);
  511. i+=2;
  512. break;
  513. case 'Y':
  514. sprintf((char *)buf+i, "%.4d", tm->tm_year+1900);
  515. i+=4;
  516. break;
  517. case 'm':
  518. sprintf((char *)buf+i, "%.2d", tm->tm_mon+1);
  519. i+=2;
  520. break;
  521. case 'o':
  522. sprintf((char *)buf+i, "%s", months[tm->tm_mon]);
  523. i+=3;
  524. break;
  525. case 'd':
  526. sprintf((char *)buf+i, "%.2d", tm->tm_mday);
  527. i+=2;
  528. break;
  529. case 'H':
  530. sprintf((char *)buf+i, "%.2d", tm->tm_hour);
  531. i+=2;
  532. break;
  533. case 'M':
  534. sprintf((char *)buf+i, "%.2d", tm->tm_min);
  535. i+=2;
  536. break;
  537. case 'S':
  538. sprintf((char *)buf+i, "%.2d", tm->tm_sec);
  539. i+=2;
  540. break;
  541. case 't':
  542. sprintf((char *)buf+i, "%.10u", (unsigned)sec);
  543. i+=10;
  544. break;
  545. case 'b':
  546. i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statscli64 * 1000./delay):0);
  547. break;
  548. case 'B':
  549. i+=sprintf((char *)buf+i, "%u", delay?(unsigned)(param->statssrv64 * 1000./delay):0);
  550. break;
  551. case 'D':
  552. i+=sprintf((char *)buf+i, "%u", delay);
  553. break;
  554. case '.':
  555. sprintf((char *)buf+i, "%.3u", msec);
  556. i+=3;
  557. break;
  558. case 'z':
  559. sprintf((char *)buf+i, "%+.2ld%.2u", timezone / 60, (unsigned)(timezone%60));
  560. i+=5;
  561. break;
  562. case 'U':
  563. if(param->username && *param->username){
  564. for(len = 0; i< (bufsize - 3) && param->username[len]; len++){
  565. buf[i] = param->username[len];
  566. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  567. if(doublec && strchr((char *)doublec, buf[i])) {
  568. buf[i+1] = buf[i];
  569. i++;
  570. }
  571. i++;
  572. }
  573. }
  574. else {
  575. buf[i++] = '-';
  576. }
  577. break;
  578. case 'n':
  579. len = param->hostname? (int)strlen((char *)param->hostname) : 0;
  580. if (len > 0 && !strchr((char *)param->hostname, ':')) for(len = 0; param->hostname[len] && i < (bufsize-3); len++, i++){
  581. buf[i] = param->hostname[len];
  582. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  583. if(doublec && strchr((char *)doublec, buf[i])) {
  584. buf[i+1] = buf[i];
  585. i++;
  586. }
  587. }
  588. else {
  589. buf[i++] = '[';
  590. i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
  591. buf[i++] = ']';
  592. }
  593. break;
  594. case 'N':
  595. if(param->service < 15) {
  596. len = (conf.stringtable)? (int)strlen((char *)conf.stringtable[SERVICES + param->service]) : 0;
  597. if(len > 20) len = 20;
  598. memcpy(buf+i, (len)?conf.stringtable[SERVICES + param->service]:(char*)"-", (len)?len:1);
  599. i += (len)?len:1;
  600. }
  601. break;
  602. case 'E':
  603. sprintf((char *)buf+i, "%.05d", param->res);
  604. i += 5;
  605. break;
  606. case 'T':
  607. if(s){
  608. for(len = 0; i < (bufsize-3) && s[len]; len++){
  609. buf[i] = s[len];
  610. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  611. if(doublec && strchr((char *)doublec, buf[i])) {
  612. buf[i+1] = buf[i];
  613. i++;
  614. }
  615. i++;
  616. }
  617. }
  618. break;
  619. case 'e':
  620. i += myinet_ntop(*SAFAMILY(&param->sinsl), SAADDR(&param->sinsl), (char *)buf + i, 64);
  621. break;
  622. case 'i':
  623. i += myinet_ntop(*SAFAMILY(&param->sincl), SAADDR(&param->sincl), (char *)buf + i, 64);
  624. break;
  625. case 'C':
  626. i += myinet_ntop(*SAFAMILY(&param->sincr), SAADDR(&param->sincr), (char *)buf + i, 64);
  627. break;
  628. case 'R':
  629. i += myinet_ntop(*SAFAMILY(&param->sinsr), SAADDR(&param->sinsr), (char *)buf + i, 64);
  630. break;
  631. case 'Q':
  632. i += myinet_ntop(*SAFAMILY(&param->req), SAADDR(&param->req), (char *)buf + i, 64);
  633. break;
  634. case 'p':
  635. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->srv->intsa)));
  636. i += (int)strlen((char *)buf+i);
  637. break;
  638. case 'c':
  639. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sincr)));
  640. i += (int)strlen((char *)buf+i);
  641. break;
  642. case 'r':
  643. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->sinsr)));
  644. i += (int)strlen((char *)buf+i);
  645. break;
  646. case 'q':
  647. sprintf((char *)buf+i, "%hu", ntohs(*SAPORT(&param->req)));
  648. i += (int)strlen((char *)buf+i);
  649. break;
  650. case 'L':
  651. sprintf((char *)buf+i, "%"PRIu64, param->cycles);
  652. i += (int)strlen((char *)buf+i);
  653. break;
  654. case 'I':
  655. sprintf((char *)buf+i, "%"PRIu64, param->statssrv64);
  656. i += (int)strlen((char *)buf+i);
  657. break;
  658. case 'O':
  659. sprintf((char *)buf+i, "%"PRIu64, param->statscli64);
  660. i += (int)strlen((char *)buf+i);
  661. break;
  662. case 'h':
  663. sprintf((char *)buf+i, "%d", param->redirected);
  664. i += (int)strlen((char *)buf+i);
  665. break;
  666. case '1':
  667. case '2':
  668. case '3':
  669. case '4':
  670. case '5':
  671. case '6':
  672. case '7':
  673. case '8':
  674. case '9':
  675. {
  676. int k, pmin=0, pmax=0;
  677. for (k = j; isnumber(format[k]); k++);
  678. if(format[k] == '-' && isnumber(format[k+1])){
  679. pmin = atoi(format + j) - 1;
  680. k++;
  681. pmax = atoi(format + k) -1;
  682. for (; isnumber(format[k]); k++);
  683. j = k;
  684. }
  685. if(!s || format[k]!='T') break;
  686. for(k = 0, len = 0; s[len]; len++){
  687. if(isspace(s[len])){
  688. k++;
  689. while(isspace(s[len+1]))len++;
  690. if(k == pmin) continue;
  691. }
  692. if(k>=pmin && k<=pmax && i < (bufsize-3)) {
  693. buf[i] = s[len];
  694. if(param->srv->nonprintable && (buf[i] < 0x20 || strchr((char *)param->srv->nonprintable, buf[i]))) buf[i] = param->srv->replace;
  695. if(doublec && strchr((char *)doublec, buf[i])) {
  696. buf[i+1] = buf[i];
  697. i++;
  698. }
  699. i++;
  700. }
  701. }
  702. break;
  703. }
  704. default:
  705. buf[i++] = format[j];
  706. }
  707. }
  708. else buf[i++] = format[j];
  709. }
  710. buf[i] = 0;
  711. return i;
  712. }
  713. int dobuf(struct clientparam * param, char * buf, int bufsize, const char *s, const char * doublec){
  714. struct tm* tm;
  715. int i;
  716. char * format;
  717. time_t t;
  718. time(&t);
  719. if(!param) return 0;
  720. format = param->srv->logformat?(char *)param->srv->logformat : DEFLOGFORMAT;
  721. tm = (*format == 'G' || *format == 'g')?
  722. gmtime(&t) : localtime(&t);
  723. i = dobuf2(param, buf, bufsize, s, doublec, tm, format + 1);
  724. return i;
  725. }
  726. static int stdloginit(struct LOGGER *logger){
  727. char tmpbuf[1024];
  728. struct stdlogdata *lp;
  729. lp = myalloc(sizeof(struct stdlogdata));
  730. if(!lp) return 1;
  731. logger->data = lp;
  732. if(!*logger->selector || !strcmp(logger->selector, "stdout")){
  733. logger->rotate = NONE;
  734. lp->fp = stdout;
  735. }
  736. else if(!strcmp(logger->selector,"stderr")){
  737. logger->rotate = NONE;
  738. lp->fp = stderr;
  739. }
  740. else {
  741. lp->fp = fopen((char *)dologname (tmpbuf, sizeof(tmpbuf) - 1, logger->selector, NULL, logger->rotate, time(NULL)), "a");
  742. if(!lp->fp){
  743. myfree(lp);
  744. return(2);
  745. }
  746. }
  747. return 0;
  748. }
  749. static int stddobuf(struct clientparam * param, char * buf, int bufsize, const char *s){
  750. return dobuf(param, buf, bufsize, s, NULL);
  751. }
  752. static void stdlog(const char * buf, int len, struct LOGGER *logger) {
  753. FILE *log = ((struct stdlogdata *)logger->data)->fp;
  754. fprintf(log, "%s\n", buf);
  755. #ifdef WITHMAIN
  756. fflush(log);
  757. #endif
  758. }
  759. static void stdlogrotate(struct LOGGER *logger){
  760. #ifndef WITHMAIN
  761. char tmpbuf[1024];
  762. struct stdlogdata *lp = (struct stdlogdata *)logger->data;
  763. if(lp->fp) lp->fp = freopen((char *)dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, NULL, logger->rotate, conf.time), "a", lp->fp);
  764. else lp->fp = fopen((char *)dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, NULL, logger->rotate, conf.time), "a");
  765. logger->rotated = conf.time;
  766. if(logger->rotate) {
  767. int t;
  768. t = 1;
  769. switch(logger->rotate){
  770. case ANNUALLY:
  771. t = t * 12;
  772. case MONTHLY:
  773. t = t * 4;
  774. case WEEKLY:
  775. t = t * 7;
  776. case DAILY:
  777. t = t * 24;
  778. case HOURLY:
  779. t = t * 60;
  780. case MINUTELY:
  781. t = t * 60;
  782. default:
  783. break;
  784. }
  785. /*
  786. FIXME: move archiver to thread
  787. */
  788. dologname (tmpbuf, sizeof(tmpbuf) -1, logger->selector, (conf.archiver)?conf.archiver[1]:NULL, logger->rotate, (logger->rotated - t * conf.rotate));
  789. remove ((char *) tmpbuf);
  790. if(conf.archiver) {
  791. int i;
  792. *tmpbuf = 0;
  793. for(i = 2; i < conf.archiverc && strlen((char *)tmpbuf) < 512; i++){
  794. strcat((char *)tmpbuf, " ");
  795. if(!strcmp((char *)conf.archiver[i], "%A")){
  796. strcat((char *)tmpbuf, "\"");
  797. dologname (tmpbuf + strlen((char *)tmpbuf), (int)(sizeof(tmpbuf) - (strlen((char *)tmpbuf) + 1)), logger->selector, conf.archiver[1], logger->rotate, (logger->rotated - t));
  798. strcat((char *)tmpbuf, "\"");
  799. }
  800. else if(!strcmp((char *)conf.archiver[i], "%F")){
  801. strcat((char *)tmpbuf, "\"");
  802. dologname (tmpbuf+strlen((char *)tmpbuf), (int)(sizeof(tmpbuf) - (strlen((char *)tmpbuf) + 1)), logger->selector, NULL, logger->rotate, (logger->rotated-t));
  803. strcat((char *)tmpbuf, "\"");
  804. }
  805. else
  806. strcat((char *)tmpbuf, (char *)conf.archiver[i]);
  807. }
  808. (void)system((char *)tmpbuf+1);
  809. }
  810. }
  811. #endif
  812. }
  813. static void stdlogflush(struct LOGGER *logger){
  814. fflush(((struct stdlogdata *)logger->data)->fp);
  815. }
  816. static void stdlogclose(struct LOGGER *logger){
  817. if(((struct stdlogdata *)logger->data)->fp != stdout && ((struct stdlogdata *)logger->data)->fp != stderr)
  818. fclose(((struct stdlogdata *)logger->data)->fp);
  819. myfree(logger->data);
  820. }
  821. #if HAVESYSLOG > 0
  822. static int sysloginit(struct LOGGER *logger){
  823. openlog(logger->selector, LOG_PID, LOG_DAEMON);
  824. return 0;
  825. }
  826. static void logsyslog(const char * buf, int len, struct LOGGER *logger) {
  827. syslog(LOG_INFO, "%s", buf);
  828. }
  829. static void syslogrotate(struct LOGGER *logger){
  830. #ifndef WITHMAIN
  831. closelog();
  832. openlog(logger->selector+1, LOG_PID, LOG_DAEMON);
  833. #endif
  834. }
  835. static void syslogclose(struct LOGGER *logger){
  836. closelog();
  837. }
  838. #endif
  839. #if HAVESQL > 0
  840. struct sqldata {
  841. SQLHENV henv;
  842. SQLHSTMT hstmt;
  843. SQLHDBC hdbc;
  844. int attempt;
  845. time_t attempt_time;
  846. };
  847. static int sqlinit2(struct sqldata * sd, char * source){
  848. SQLRETURN retcode;
  849. char * datasource;
  850. char * username;
  851. char * password;
  852. char * string;
  853. int ret = 0;
  854. retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &sd->henv);
  855. if (!sd->henv || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)){
  856. return 1;
  857. }
  858. retcode = SQLSetEnvAttr(sd->henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
  859. if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
  860. ret = 2;
  861. goto CLOSEENV;
  862. }
  863. retcode = SQLAllocHandle(SQL_HANDLE_DBC, sd->henv, &sd->hdbc);
  864. if (!sd->hdbc || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)) {
  865. ret = 3;
  866. goto CLOSEENV;
  867. }
  868. SQLSetConnectAttr(sd->hdbc, SQL_LOGIN_TIMEOUT, (void*)15, 0);
  869. string = mystrdup(source);
  870. if(!string) goto CLOSEHDBC;
  871. datasource = strtok(string, ",");
  872. username = strtok(NULL, ",");
  873. password = strtok(NULL, ",");
  874. /* Connect to data source */
  875. retcode = SQLConnect(sd->hdbc, (SQLCHAR*) datasource, (SQLSMALLINT)strlen(datasource),
  876. (SQLCHAR*) username, (SQLSMALLINT)((username)?strlen(username):0),
  877. (SQLCHAR*) password, (SQLSMALLINT)((password)?strlen(password):0));
  878. myfree(string);
  879. if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
  880. ret = 4;
  881. goto CLOSEHDBC;
  882. }
  883. retcode = SQLAllocHandle(SQL_HANDLE_STMT, sd->hdbc, &sd->hstmt);
  884. if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
  885. sd->hstmt = 0;
  886. ret = 5;
  887. goto CLOSEHDBC;
  888. }
  889. return 0;
  890. CLOSEHDBC:
  891. SQLFreeHandle(SQL_HANDLE_DBC, sd->hdbc);
  892. sd->hdbc = 0;
  893. CLOSEENV:
  894. SQLFreeHandle(SQL_HANDLE_ENV, sd->henv);
  895. sd->henv = 0;
  896. return ret;
  897. }
  898. static int sqlinit(struct LOGGER *logger){
  899. struct sqldata *sd;
  900. int res;
  901. sd = (struct sqldata *)myalloc(sizeof(struct sqldata));
  902. memset(sd, 0, sizeof(struct sqldata));
  903. logger->data = sd;
  904. if((res = sqlinit2(sd, logger->selector))) {
  905. myfree(sd);
  906. return res;
  907. }
  908. return 0;
  909. }
  910. static int sqldobuf(struct clientparam * param, char * buf, int bufsize, const char *s){
  911. return dobuf(param, buf, bufsize, s, "\'");
  912. }
  913. static void sqllog(const char * buf, int len, struct LOGGER *logger){
  914. SQLRETURN ret;
  915. struct sqldata *sd = (struct sqldata *)logger->data;
  916. if(sd->attempt > 5){
  917. if (conf.time - sd->attempt_time < 180){
  918. return;
  919. }
  920. }
  921. if(sd->attempt){
  922. sd->attempt++;
  923. sqlrotate(logger);
  924. if(!sd->hstmt){
  925. sd->attempt_time=conf.time;
  926. return;
  927. }
  928. }
  929. ret = SQLExecDirect(sd->hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
  930. if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
  931. sqlrotate(logger);
  932. if(sd->hstmt) {
  933. ret = SQLExecDirect(sd->hstmt, (SQLCHAR *)buf, (SQLINTEGER)len);
  934. if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
  935. sd->attempt++;
  936. sd->attempt_time=conf.time;
  937. return;
  938. }
  939. }
  940. }
  941. sd->attempt=0;
  942. }
  943. static void sqlrotate(struct LOGGER *logger){
  944. struct sqldata * sd;
  945. sqlclose(logger);
  946. sd = (struct sqldata *)myalloc(sizeof(struct sqldata));
  947. memset(sd, 0, sizeof(struct sqldata));
  948. logger->data = sd;
  949. sqlinit2(sd, logger->selector+1);
  950. }
  951. static void sqlclose(struct LOGGER *logger){
  952. struct sqldata *sd = (struct sqldata *)logger->data;
  953. if(sd->hstmt) {
  954. SQLFreeHandle(SQL_HANDLE_STMT, sd->hstmt);
  955. sd->hstmt = NULL;
  956. }
  957. if(sd->hdbc){
  958. SQLDisconnect(sd->hdbc);
  959. SQLFreeHandle(SQL_HANDLE_DBC, sd->hdbc);
  960. sd->hdbc = NULL;
  961. }
  962. if(sd->henv) {
  963. SQLFreeHandle(SQL_HANDLE_ENV, sd->henv);
  964. sd->henv = NULL;
  965. }
  966. myfree(sd);
  967. }
  968. #endif