log.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:8k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /* Copyright (c) 1995,1996,1997 NEC Corporation. All rights reserved. */
- /* */
- /* The redistribution, use and modification in source or binary forms of */
- /* this software is subject to the conditions set forth in the copyright */
- /* document ("Copyright") included with this distribution. */
- /*
- * $Id: log.c,v 1.71.4.5 1998/10/09 16:05:14 steve Exp $
- */
- #define __NOLOGUPDATEPROTO
- #include "socks5p.h"
- #include "log.h" /* Prototypes & defines. */
- #include "threads.h" /* MUTEX & THREAD_SELF */
- void *S5LogDefaultHandle = NULL;
- int S5LogShowThreadIDS = 0;
- #ifdef HAVE_STDARG_H
- #include <stdarg.h>
- #define VA_START(a, b) va_start((a), (b))
- #define va_alist ...
- #define va_dcl
- #else
- #include <varargs.h>
- #define VA_START(a, b) va_start((a))
- #endif
- #ifdef HAVE_NL_TYPES_H
- #include <nl_types.h>
- #endif
- #ifdef HAVE_SYSLOG_H
- #include <syslog.h>
- #ifndef LOG_DAEMON
- #define LOG_DAEMON LOG_USER
- #endif
- #endif
- typedef struct {
- #ifdef HAVE_NL_TYPES_H
- nl_catd catalog;
- #define NL_START(x, y) (x)->catalog = catopen((y), 0)
- #define NL_UPDATE(x, e, f) if ((x)->catalog != (nl_catd)-1) (f) = catgets((x)->catalog, 0, (e), (f))
- #define NL_CLOSE(x) if ((x)->catalog != (nl_catd)-1) catclose((x)->catalog); (x)->catalog = (nl_catd)-1
- #elif defined(HAVE_DGETTEXT)
- char domain[MAXNAMELEN];
- #define NL_START(x, y) strncpy((x)->domain, name, MAX(MAXNAMELEN, strlen(name))); (x)->domain[MAX(MAXNAMELEN, strlen(name))] = ' '
- #define NL_UPDATE(x, e, f) (f) = dgettext((x)->domain, (f))
- #define NL_CLOSE(x)
- #else
- #define NL_START(x, y)
- #define NL_UPDATE(x, e, f)
- #define NL_CLOSE(x)
- #endif
- int level;
- int how;
- } S5LogHandle;
- static void replacePercentM(const char *inbuffer, char *outbuffer, int olen) {
- register const char *t2;
- register char *t1, ch;
- if (!outbuffer || !inbuffer) return;
- olen--;
- for (t1 = outbuffer; (ch = *inbuffer) && t1-outbuffer < olen ; ++inbuffer)
- if (inbuffer[0] == '%' && inbuffer[1] == 'm')
- for (++inbuffer, t2 = strerror(GETERRNO()); (t2 && t1-outbuffer < olen) && (*t1 = *t2++); t1++);
- else *t1++ = ch;
- *t1 = ' ';
- }
- void S5LogvUpdate(const void *handle, int level, int msgID, const char *oformat, va_list pvar) {
- #define FMT_BUFLEN 2*1024 + 2*10
- char fmt_cpy[FMT_BUFLEN], format[FMT_BUFLEN];
- S5LogHandle *h = (S5LogHandle *)handle;
- int serrno = GETERRNO();
- #ifndef HAVE_VSNPRINTF
- static FILE *tmpFile = NULL;
- #endif
- *fmt_cpy = ' ';
- /* If S5LogHandle has not been initialized, do it before we start; */
- /* Saves the mess of making sure it gets called ahead of time. */
- if (h == NULL) {
- S5LogStart(&S5LogDefaultHandle, -1, -1, "libsocks5");
- h = (S5LogHandle *)S5LogDefaultHandle;
- }
- /* If the handle is invalid, don't log. */
- /* If the maximum log level is too low for this message, don't log. */
- /* If something that we call forces us to log a message, don't log. */
- if (!h || !(h->how) || h->level == -1 || level > h->level) return;
- /* Change the format if the message is in the catalog... */
- NL_UPDATE(h, msgID, oformat);
- if (!oformat) return;
- /* Print the pid & maybe the thread id in format here. Skip forward if */
- /* you don't want it later (e.g. if syslogging). */
- sprintf(format, "%05d:", (int)getpid());
- if (S5LogShowThreadIDS) sprintf(format+strlen(format), "%06d:", (int)THREAD_SELF());
- strcat(format, " ");
- replacePercentM(oformat, format + strlen(format), sizeof(format) - strlen(format));
- #ifdef HAVE_VSNPRINTF
- if (vsnprintf(fmt_cpy, FMT_BUFLEN-1, format, pvar) < 0) {
- fmt_cpy[FMT_BUFLEN-1] = ' ';
- }
- #else
- /* Original idea for VSPRINTF verification courtesy of Sten Gunterbuer */
- /* (sten@ERGON.CH) a la BUGTRAQ. Another solution is to use pipes or a */
- /* temp file, but I'm not convinced it would be more efficient (2 laps */
- /* through the formatting versus 1 and a bunch of byte copies through */
- /* the kernel). */
- /* */
- /* Thanks to Zach Brown (zab@zabbo.net) for finding the problem... */
- if (tmpFile == NULL && (tmpFile = tmpfile()) == NULL) {
- sprintf(fmt_cpy, "ERROR: Unable to verify string for vsprintf");
- if ((h->level - 1) > S5_LOG_INFO) h->level = S5_LOG_INFO;
- else h->level--;
- level = S5_LOG_ERROR;
- } else if (vfprintf(tmpFile, format, pvar) > FMT_BUFLEN-1) {
- sprintf(fmt_cpy, "ERROR: String verification failed when trying to log message with format: %s", format);
- if ((h->level - 1) > S5_LOG_INFO) h->level = S5_LOG_INFO;
- else h->level--;
- level = S5_LOG_ERROR;
- } else {
- rewind(tmpFile);
- vsprintf(fmt_cpy, format, pvar);
- }
- #endif
- /* Log to the Local log facility, e.g. Stderr on Unix and maybe a window */
- /* or something on NT. Neither system can deal with a NULL format so */
- /* check that here too. */
- if (h->how & S5_LOG_LOCAL && format) {
- fprintf(stderr, "%sn", fmt_cpy);
- fflush(stderr);
- }
- /* Log to the system logging facility -- e.g. Syslog on Unix & the */
- /* EventLog on Windows NT. */
- if (h->how & S5_LOG_SYSTEM) {
- #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
- int slfac, offset = 6;
- if (level == S5_LOG_ERROR) slfac = LOG_ERR;
- else if (level == S5_LOG_INFO) slfac = LOG_NOTICE;
- else if (level > S5_LOG_INFO && level < S5_LOG_DEBUG(5)) slfac = LOG_WARNING;
- else if (level > S5_LOG_DEBUG(0) && level < S5_LOG_DEBUG(10)) slfac = LOG_NOTICE;
- else if (level > S5_LOG_DEBUG(5) && level < S5_LOG_DEBUG(15)) slfac = LOG_INFO;
- else if (level >= S5_LOG_DEBUG(15)) slfac = LOG_DEBUG;
- /* skip "%05d:", and maybe another " " */
- if (!S5LogShowThreadIDS) offset++;
- syslog(slfac, fmt_cpy + offset);
- #else
- #endif
- }
- SETERRNO(serrno); /* restore errno, just in case...? */
- return;
- }
- void S5LogUpdate(const void *handle, int level, int msgID, const char *format, va_alist) va_dcl {
- va_list pvar;
- #ifdef HAVE_STDARG_H
- va_start(pvar, format);
- #else
- VA_START(pvar, format);
- #endif
- S5LogvUpdate(handle, level, msgID, format, pvar);
- va_end(pvar);
- }
- void S5LogStart(void **vhp, int how, int level, const char *name) {
- S5LogHandle **hp = (S5LogHandle **)vhp;
- char buf[1024], *tmp;
- /*
- char tbuf[1024];
- time_t now = time(NULL);
- */
- sprintf(buf, "%s", name);
- if (!(*hp) && ((*hp) = (S5LogHandle *)malloc(sizeof(S5LogHandle))) == NULL) {
- /* no where to store things, so just skip it. */
- return;
- } else {
- if (how == -1) {
- (*hp)->how = 0;
- if (getenv("SOCKS5_LOG_SYSLOG")) (*hp)->how |= S5_LOG_SYSTEM;
- if (getenv("SOCKS5_LOG_STDERR")) (*hp)->how |= S5_LOG_LOCAL;
- } else (*hp)->how = how;
- if (level == -1) {
- if ((tmp = getenv("SOCKS5_DEBUG"))) {
- if (isdigit((int)*tmp)) (*hp)->level = S5_LOG_DEBUG(atoi(tmp));
- else (*hp)->level = S5_LOG_DEBUG(25);
- } else (*hp)->level = -1;
- } else (*hp)->level = level;
- NL_START(*hp, buf);
- }
- #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
- /* Only the first person to call this gets to open the log, that way the */
- /* monitor doesn't clobber the server's socks5 name in the logs. */
- if ((*hp)->how & S5_LOG_SYSTEM){
- static int logopened = 0;
- if (!logopened) {
- logopened = 1;
- openlog(name, LOG_PID, SYSLOG_FAC);
- }
- }
- #endif
- /* Following code is commented out so that we can remove DontLoop... */
- /*
- if (restart && (*hp)->how != 0) {
- MUTEX_LOCK(lt_mutex);
- strftime(tbuf, sizeof(tbuf), "%c", REAL(localtime)(&now));
- S5LogUpdate((*hp), S5_LOG_DEBUG(0), 0, "%s Logging (re)started at %s", name, tbuf);
- MUTEX_UNLOCK(lt_mutex);
- }
- */
- }
- void S5LogEnd(void *vh) {
- S5LogHandle *h = (S5LogHandle *)vh;
- if (!h) return;
- NL_CLOSE(h);
- #if defined(HAVE_SYSLOG_H) && defined(SYSLOG_FAC)
- closelog();
- #endif
- free(h);
- }