log.c
上传用户:pycemail
上传日期:2007-01-04
资源大小:329k
文件大小:18k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /*
  2.  * ProFTPD - FTP server daemon
  3.  * Copyright (c) 1997, 1998 Public Flood Software
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307, USA.
  18.  */
  19. /*
  20.  * ProFTPD logging support
  21.  * $Id: log.c,v 1.12 1999/10/01 07:57:32 macgyver Exp $
  22.  */
  23. /* History Log:
  24.  *
  25.  * 4/24/97 0.99.0pl1
  26.  *   Added log_debug() and log_setdebuglevel() in order to facilitate
  27.  *   altering the amount of debugging info printed or syslogged.
  28.  *   Also added a command line argument (-d,--debug) to alter the
  29.  *   debug level at runtime.  See main.c.
  30.  */
  31. /* AIX requires this to be the first thing in the file. */
  32. #if defined(_AIX) && !defined(__GNUC__)
  33. #pragma alloca
  34. #endif
  35. #include "conf.h"
  36. #include <signal.h>
  37. static int syslog_open = FALSE;
  38. static int syslog_discard = FALSE;
  39. static int logstderr = TRUE;
  40. static int debug_level = DEBUG0; /* Default is no debug logging */
  41. static int facility = LOG_DAEMON;
  42. static int set_facility = -1;
  43. static char *syslog_fn = NULL;
  44. static char *syslog_hostname;
  45. static int syslog_fd = -1;
  46. static int runfd = -1;
  47. static char scoreboard_path[MAX_PATH_LEN] = RUN_DIR;
  48. static char *runfn = NULL;
  49. static char *runcwd = NULL;
  50. static char *address = NULL;
  51. static size_t runsize = 0;
  52. static int xferfd = -1;
  53. char *fmt_time(time_t t)
  54. {
  55.   static char buf[30];
  56.   static char *mons[] =
  57.   { "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec" };
  58.   static char *days[] =
  59.   { "Sun","Mon","Tue","Wed","Thu","Fri","Sat" };
  60.   struct tm *tr;
  61.   if((tr = localtime(&t)) != NULL) {
  62.     snprintf(buf,sizeof(buf),"%s %s %2d %02d:%02d:%02d %d",
  63.             days[tr->tm_wday],
  64.             mons[tr->tm_mon],
  65.             tr->tm_mday,
  66.             tr->tm_hour,
  67.             tr->tm_min,
  68.             tr->tm_sec,
  69.             tr->tm_year + 1900);
  70.   } else
  71.     buf[0] = '';
  72.   
  73.   return buf;
  74. }
  75. void log_close_xfer()
  76. {
  77.   if(xferfd != -1)
  78.     close(xferfd);
  79.   xferfd = -1;
  80. }
  81. int log_open_xfer(const char *fn)
  82. {
  83.   if(!fn) {
  84.     if(xferfd != -1)
  85.       log_close_xfer();
  86.     return 0;
  87.   }
  88.   if(xferfd == -1)
  89.     xferfd = open(fn,O_WRONLY|O_APPEND|O_CREAT,0644);
  90.   return xferfd;
  91. }
  92. int log_xfer(int xfertime,char *remhost,unsigned long fsize,
  93.              char *fname,char xfertype,char direction,
  94.              char access,char *user)
  95. {
  96.   char buf[1024], fbuf[1024];
  97.   int i;
  98.   if(xferfd == -1)
  99.     return 0;
  100.   for(i = 0; (i + 1 < sizeof(fbuf)) && fname[i] != ''; i++) {
  101.     fbuf[i] = (isspace(fname[i]) || iscntrl(fname[i])) ? '_' : fname[i];
  102.   }
  103.   
  104.   fbuf[i] = '';
  105.   
  106.   snprintf(buf,sizeof(buf),"%s %d %s %lu %s %c _ %c %c %s ftp 0 *n",
  107.    fmt_time(time(NULL)),xfertime,remhost,fsize,
  108.    fbuf,xfertype,direction,access,user);
  109.   return(write(xferfd,buf,strlen(buf)));
  110. }
  111. void log_rm_run()
  112. {
  113.   if(runfd > -1)
  114.     close(runfd);
  115.   if(runfn)
  116.     unlink(runfn);
  117.   runfd = -1;
  118. }
  119. int log_close_run()
  120. {
  121.   if(runfd == -1)
  122.     return 0;
  123.   close(runfd);
  124.   runfd = -1;
  125.   return 0;
  126. }
  127. const char *log_run_getpath(void)
  128. {
  129.   return scoreboard_path;
  130. }
  131. void log_run_setpath(const char *path)
  132. {
  133.   sstrncpy(scoreboard_path,path,sizeof(scoreboard_path));
  134.   if(scoreboard_path[strlen(scoreboard_path)-1] == '/')
  135.     scoreboard_path[strlen(scoreboard_path)-1] = '';
  136. }
  137. int log_run_checkpath(void)
  138. {
  139.   struct stat sbuf;
  140.   if(stat(scoreboard_path,&sbuf) < 0)
  141.     return -1;
  142.   if(!S_ISDIR(sbuf.st_mode)) {
  143.     errno = ENOTDIR;
  144.     return -1;
  145.   }
  146.   return 0;
  147. }
  148. int log_open_run(pid_t mpid, int trunc, int allow_update)
  149. {
  150.   char fname[MAXPATHLEN];
  151.   logrun_header_t hdr;
  152.   int i;
  153.   if(runfd > -1)
  154.     return 0;
  155.   if(!mpid)
  156.     snprintf(fname, sizeof(fname), "%s/proftpd-inetd",scoreboard_path);
  157.   else
  158.     snprintf(fname, sizeof(fname), "%s/proftpd-%d",scoreboard_path,(int)mpid);
  159.   runfn = pstrdup(permanent_pool,fname);
  160.   if((runfd = open(runfn,O_RDWR|O_CREAT|(trunc ? O_TRUNC : 0),
  161.                    0644)) == -1)
  162.     return -1;
  163.   /* Attempt to read header */
  164.   i = read(runfd, &hdr, sizeof(hdr));
  165.   if(i <= 0) {
  166.     char buf[sizeof(logrun_t)];
  167.     runsize = sizeof(logrun_t);
  168.     
  169.     hdr.r_magic = LOGRUN_MAGIC;
  170.     hdr.r_version = INTERNAL_VERSION;
  171.     hdr.r_size = sizeof(logrun_t);
  172.     bzero(buf,sizeof(logrun_t));
  173.     bcopy(&hdr,buf,sizeof(hdr));
  174.     write(runfd,buf,runsize);
  175.     fsync(runfd);
  176.     return runfd;
  177.   }
  178.   if(i < sizeof(hdr)) {
  179.     /* File is corrupt, etc, silently rm it */
  180.     if(allow_update) {
  181.       log_rm_run();
  182.       return log_open_run(mpid,trunc,allow_update);
  183.     }
  184.     return -1;
  185.   }
  186.   if(hdr.r_magic != LOGRUN_MAGIC) {
  187.     /* Old version or corrupt */
  188.     log_pri(LOG_NOTICE,"run-time scoreboard file '%s' is corrupted or old version.",fname);
  189.     if(allow_update) {
  190.       log_rm_run();
  191.       return log_open_run(mpid,trunc,allow_update);
  192.     }
  193.     return -1;
  194.   }
  195.   if(hdr.r_version < INTERNAL_VERSION) {
  196.     log_pri(LOG_NOTICE,"run-time scoreboard file '%s' is old version.",fname);
  197.     if(allow_update) {
  198.       log_rm_run();
  199.       return log_open_run(mpid,trunc,allow_update);
  200.     }
  201.     return -1;
  202.   }
  203.   if(hdr.r_version > INTERNAL_VERSION) {
  204.     log_pri(LOG_NOTICE,"run-time scoreboard file '%s' appears to be from a newer version of proftpd (%s).",
  205.             fname,VERSION);
  206.     log_close_run();
  207.     return -1;
  208.   }
  209.   runsize = (size_t)hdr.r_size;
  210.   return runfd;
  211. }
  212. static int _pid_exists(pid_t pid)
  213. {
  214. #ifdef LINUX
  215.   char procfn[20];
  216.   struct stat sbuf;
  217. #endif
  218.   int res;
  219.   res = kill(pid,SIGCONT);
  220. #ifdef LINUX
  221.   snprintf(procfn, sizeof(procfn), "/proc/%d",pid);    
  222.   if( (res == -1 && errno == EPERM) || !res ||
  223.     stat(procfn,&sbuf) != -1)
  224. #else
  225.   if( (res == -1 && errno == EPERM) || !res )
  226. #endif
  227.     return 1;
  228.   return 0;
  229. }
  230. static size_t _read_hdr(int fd)
  231. {
  232.   logrun_header_t hdr;
  233.   if(read(fd,&hdr,sizeof(hdr)) != sizeof(hdr))
  234.     return 0;
  235.   if(hdr.r_magic != LOGRUN_MAGIC)
  236.     /* Old version or corrupt */
  237.     return 0;
  238.   if(hdr.r_version != INTERNAL_VERSION)
  239.     return 0;
  240.   lseek(fd, hdr.r_size, SEEK_SET);
  241.   return (size_t)hdr.r_size;
  242. }
  243. static int _read_run(int fd, size_t size, logrun_t *ent)
  244. {
  245.   unsigned char *buf;
  246.   logrun_t *tmp;
  247.   buf = (unsigned char*)alloca(size);
  248.   while(read(fd,buf,size) == size) {
  249.     tmp = (logrun_t*)buf;
  250.     if(tmp->pid) {
  251.       /* Try to determine if the process still exists */
  252.       bcopy(tmp,ent,sizeof(logrun_t));
  253.       return _pid_exists(ent->pid);
  254.     }
  255.   }
  256.   return -1;
  257. }
  258. logrun_t *log_read_run(pid_t *mpid)
  259. {
  260.   static DIR *dir = NULL;
  261.   static struct dirent *dent = NULL;
  262.   static int fd = -1;
  263.   static logrun_t ent;
  264.   static size_t size = 0;
  265.   char *cp, buf[MAXPATHLEN];
  266.   errno = 0;
  267.   if(!dir) {
  268.     dir = opendir(scoreboard_path);
  269.     if(!dir)
  270.       return NULL;
  271.   }
  272.   while(fd != -1) {
  273.     switch(_read_run(fd,size,&ent)) {
  274.     case 1:
  275.       errno = 0;
  276.       return &ent;
  277.     case -1:
  278.       close(fd); fd = -1; break;
  279.     }
  280.   }
  281.   while((dent = readdir(dir)) != NULL)
  282.     if(strncmp(dent->d_name,"proftpd",7) == 0) {
  283.       cp = rindex(dent->d_name,'-');
  284.       if(cp) {
  285.         cp++;
  286.         if(mpid)
  287.           *mpid = (pid_t)atoi(cp);
  288.         snprintf(buf, sizeof(buf), "%s/%s",scoreboard_path,dent->d_name);
  289.         fd = open(buf,O_RDONLY,0644);
  290.         if(fd != -1) {
  291.           size = _read_hdr(fd);
  292.           if(!size) {
  293.             close(fd);
  294.             fd = -1;
  295.           }
  296.           while(fd != -1) {
  297.             switch(_read_run(fd,size,&ent)) {
  298.             case 1: errno = 0; return &ent;
  299.             case -1: close(fd); fd = -1; errno = 0;
  300.             }
  301.           }
  302.         } else
  303.           return NULL;
  304.       }
  305.     }
  306.   closedir(dir);
  307.   dir = NULL;
  308.   return NULL;
  309. }
  310. void log_run_address(const char *remote_name, const p_in_addr_t *remote_ipaddr)
  311. {
  312.   char buf[1024];
  313.   snprintf(buf,sizeof(buf),"%s [%s]",remote_name,inet_ntoa(*remote_ipaddr));
  314.   buf[1023] = '';
  315.   address = pstrdup(permanent_pool,buf);
  316. }
  317. void log_run_cwd(const char *cwd)
  318. {
  319.   if(!runcwd)
  320.     runcwd = pcalloc(permanent_pool,MAX_PATH_LEN);
  321.   
  322.   sstrncpy(runcwd,cwd,MAX_PATH_LEN);
  323. }
  324. /* log_add_run() logs the current process and connection information to
  325.  * the scoreboard_path/proftpd-[master_daemon_pid] file.  If an existing record
  326.  * for the current pid is found, it is overwritten.  Passing user ==
  327.  * NULL clears the entry.
  328.  */
  329. int log_add_run(pid_t mpid, time_t *idle_since, char *user,char *class,
  330.                 p_in_addr_t *server_ip, unsigned short server_port, 
  331.                 unsigned long tx_size, unsigned long tx_done, char *op, ...)
  332. {
  333.   logrun_t ent,fent;
  334.   int res = 0,c,first = -1;
  335.   va_list msg;
  336.   char buf[1500] = "";
  337. #ifndef HAVE_FLOCK
  338.   struct flock arg;
  339. #endif
  340.   c = runsize;
  341.   if(op) {
  342.     va_start(msg,op);
  343.     vsnprintf(buf,sizeof(buf),op,msg);
  344.     va_end(msg);
  345.     buf[sizeof(buf)-1] = '';
  346.   }
  347.   if(runfd == -1)
  348.     log_open_run(mpid,FALSE,FALSE);
  349.   if(runfd == -1)
  350.     return -1;
  351.   bzero(&ent,sizeof(ent));
  352.   ent.pid = getpid();
  353.   ent.uid = geteuid();
  354.   ent.gid = getegid();
  355. #ifdef HAVE_FLOCK
  356.   flock(runfd,LOCK_EX);
  357. #else
  358.   arg.l_type = F_WRLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
  359.   fcntl(runfd, F_SETLKW, &arg);
  360. #endif
  361.   if(lseek(runfd,runsize,SEEK_SET) != -1) {
  362.     while(read(runfd,(char*)&fent,sizeof(fent)) == sizeof(fent) &&
  363.           fent.pid != ent.pid) {
  364.       if((!fent.pid || !_pid_exists(fent.pid)) && first == -1)
  365.         first = c;
  366.       c += sizeof(fent);
  367.     }
  368.     if(fent.pid == ent.pid) {
  369.       bcopy(&fent,&ent,sizeof(ent));
  370.       first = -1;
  371.       lseek(runfd,c,SEEK_SET);
  372.     } else
  373.       lseek(runfd,runsize,SEEK_END);
  374.   }
  375.   if(idle_since)
  376.     ent.idle_since = *idle_since;
  377.   else
  378.     ent.idle_since = 0;
  379.   if(user) {
  380.     bzero(ent.user,sizeof(ent.user));
  381.     sstrncpy(ent.user,user,sizeof(ent.user));
  382.   }
  383.   if(class) {
  384.     bzero(ent.class,sizeof(ent.class));
  385.     sstrncpy(ent.class,class,sizeof(ent.class));
  386.   }
  387.   if(buf[0]) {
  388.     bzero(ent.op,sizeof(ent.op));
  389.     sstrncpy(ent.op,buf,sizeof(ent.op));
  390.   }
  391.   if(server_ip)
  392.     bcopy(server_ip,&ent.server_ip,sizeof(ent.server_ip));
  393.   if(server_port)
  394.     ent.server_port = server_port;
  395.   if(tx_size) {
  396.     ent.transfer_size = tx_size;
  397.     ent.transfer_complete = tx_done;
  398.   } else {
  399.     ent.transfer_size = 0;
  400.     ent.transfer_complete = 0;
  401.   }
  402.   if(runcwd) {
  403.     sstrncpy(ent.cwd,runcwd,sizeof(ent.cwd));
  404.     ent.cwd[sizeof(ent.cwd)-1] = '';
  405.   } else
  406.     bzero(ent.cwd,sizeof(ent.cwd));
  407.   if(address) {
  408.     sstrncpy(ent.address,address,sizeof(ent.address));
  409.     ent.address[sizeof(ent.address)-1] = '';
  410.   } else
  411.     bzero(ent.address,sizeof(ent.address));
  412.   if(!user) {
  413.     if(fent.pid == ent.pid) {
  414.       bzero(&ent,sizeof(ent));
  415.       res = write(runfd,(char*)&ent,sizeof(ent));
  416.     }
  417.   } else {
  418.     if(first != -1)
  419.       lseek(runfd,first,SEEK_SET);
  420.     res = write(runfd,(char*)&ent,sizeof(ent));
  421.   }
  422.   /* 11/16/97 - fsync() causes the kernel to flush related file buffers to
  423.    * disk, not necessary here.
  424.    */
  425.   /* fsync(runfd); */
  426. #ifdef HAVE_FLOCK
  427.   flock(runfd,LOCK_UN);
  428. #else
  429.   arg.l_type = F_UNLCK; arg.l_whence = arg.l_start = arg.l_len = 0;
  430.   fcntl(runfd, F_SETLKW, &arg);
  431. #endif
  432.   return res;
  433. }
  434. /* This next function logs an entry to wtmp, it MUST be called as
  435.  * root BEFORE a chroot occurs.
  436.  * Note: This has some portability ifdefs in it.  They *should* work,
  437.  * but I haven't been able to test them.
  438.  */
  439. int log_wtmp(char *line, char *name, char *host, p_in_addr_t *ip)
  440. {
  441.   struct stat buf;
  442.   struct utmp ut;
  443.   int res = 0;
  444.   static int fd = -1;
  445. #if defined(SVR4) || defined(__SVR4)
  446. #if !(defined(LINUX) || defined(__hpux) || defined (_AIX))
  447.   /* This "auxilliary" utmp doesn't exist under linux. */
  448.   struct utmpx utx;
  449.   static int fdx = -1;
  450.   if(fdx < 0 && (fdx = open(WTMPX_FILE, O_WRONLY | O_APPEND, 0)) < 0) {
  451.     log_pri(LOG_WARNING,"wtmpx %s: %s",WTMPX_FILE,strerror(errno));
  452.     return -1;
  453.   }
  454.   if(fstat(fdx,&buf) == 0) {
  455.     memset(&utx,0,sizeof(utx));
  456.     sstrncpy(utx.ut_user,name,sizeof(utx.ut_user));
  457.     sstrncpy(utx.ut_id,"ftp",sizeof(utx.ut_user));
  458.     sstrncpy(utx.ut_line,line,sizeof(utx.ut_line));
  459.     sstrncpy(utx.ut_host,host,sizeof(utx.ut_host));
  460.     utx.ut_syslen = strlen(utx.ut_host)+1;
  461.     utx.ut_pid = getpid();
  462.     time(&utx.ut_tv.tv_sec);
  463.     if(*name)
  464.       utx.ut_type = USER_PROCESS;
  465.     else
  466.       utx.ut_type = DEAD_PROCESS;
  467.     utx.ut_exit.e_termination = 0;
  468.     utx.ut_exit.e_exit = 0;
  469.     if(write(fdx,(char*)&utx,sizeof(utx)) != sizeof(utx))
  470.       ftruncate(fdx, buf.st_size);
  471.   } else {
  472.     log_debug(DEBUG0,"%s fstat(): %s",WTMPX_FILE,strerror(errno));
  473.     res = -1;
  474.   }
  475. #endif
  476. #endif /* SVR4 */
  477.   if(fd < 0 && (fd = open(WTMP_FILE,O_WRONLY|O_APPEND,0)) < 0) {
  478.     log_pri(LOG_WARNING,"wtmp %s: %s",WTMP_FILE,strerror(errno));
  479.     return -1;
  480.   }
  481.  
  482.   if(fstat(fd,&buf) == 0) {
  483.     memset(&ut,0,sizeof(ut));
  484. #ifdef HAVE_UTMAXTYPE
  485. #ifdef LINUX
  486.     if(ip)
  487.       memcpy(&ut.ut_addr,ip,sizeof(ut.ut_addr));
  488. #else
  489.     sstrncpy(ut.ut_id,"ftp",sizeof(ut.ut_id));
  490.     ut.ut_exit.e_termination = 0;
  491.     ut.ut_exit.e_exit = 0;
  492. #endif
  493.     sstrncpy(ut.ut_line,line,sizeof(ut.ut_line));
  494.     if(name && *name)
  495.       sstrncpy(ut.ut_user,name,sizeof(ut.ut_user));
  496.     ut.ut_pid = getpid();
  497.     if(name && *name)
  498.       ut.ut_type = USER_PROCESS;
  499.     else
  500.       ut.ut_type = DEAD_PROCESS;
  501. #else  /* !HAVE_UTMAXTYPE */
  502.     sstrncpy(ut.ut_line,line,sizeof(ut.ut_line));
  503.     if(name && *name)
  504.       sstrncpy(ut.ut_name,name,sizeof(ut.ut_name));
  505. #endif /* HAVE_UTMAXTYPE */
  506. #ifdef HAVE_UT_UT_HOST
  507.     if(host && *host)
  508.       sstrncpy(ut.ut_host,host,sizeof(ut.ut_host));
  509. #endif /* HAVE_UT_UT_HOST */
  510.     time(&ut.ut_time);
  511.     if(write(fd,(char*)&ut,sizeof(ut)) != sizeof(ut))
  512.       ftruncate(fd,buf.st_size);
  513.   } else {
  514.     log_debug(DEBUG0,"%s fstat(): %s",WTMP_FILE,strerror(errno));
  515.     res = -1;
  516.   }
  517.   return res;
  518. }
  519. int log_opensyslog(const char *fn)
  520. {
  521.   char *ptr;
  522.   struct stat statbuf;
  523.   
  524.   if(set_facility != -1)
  525.     facility = set_facility;
  526.   if(fn)
  527.     syslog_fn = pstrdup(permanent_pool,fn);
  528.   if(!syslog_fn) {
  529.     openlog("proftpd",LOG_NDELAY|LOG_PID,facility);
  530.     syslog_open = TRUE;
  531.     syslog_fd = -1;
  532.   } else {
  533.     if((ptr = rindex(syslog_fn, '/')) == NULL) {
  534.       log_debug(DEBUG0, "%s rindex failed", syslog_fn);
  535.       syslog_fn = NULL;
  536.       return -1;
  537.     }
  538.     
  539.     *ptr = '';
  540.     if(stat(syslog_fn, &statbuf) == -1) {
  541.       log_debug(DEBUG0, "%s stat: %s", syslog_fn, strerror(errno));
  542.       syslog_fn = NULL;
  543.       return -1;
  544.     }
  545.     if(!S_ISDIR(statbuf.st_mode)) {
  546.       log_debug(DEBUG0, "%s is not a directory", syslog_fn);
  547.       syslog_fn = NULL;
  548.       return -1;
  549.     }
  550.     
  551.     if(statbuf.st_mode & S_IWOTH) {
  552.       log_debug(DEBUG0, "%s is a world writeable directory", syslog_fn);
  553.       syslog_fn = NULL;
  554.       return -2;
  555.     }
  556.     
  557.     *ptr = '/';
  558.     syslog_fd = open(syslog_fn,O_CREAT|O_APPEND|O_WRONLY,0640);
  559.     if(syslog_fd == -1) {
  560.       syslog_fn = NULL;
  561.       return -1;
  562.     }
  563.     syslog_open = TRUE;
  564.   }
  565.   return 0;
  566. }
  567. void log_closesyslog()
  568. {
  569.   if(syslog_fd != -1)
  570.     close(syslog_fd);
  571.   else
  572.     closelog();
  573.   syslog_fd = -1;
  574.   syslog_open = FALSE;
  575. }
  576. void log_setfacility(int f)
  577. {
  578.   set_facility = f;
  579. }
  580. void log_discard()
  581. {
  582.   syslog_discard = TRUE;
  583. }
  584. void log(int priority, int f, char *s)
  585. {
  586.   if(logstderr) {
  587.     fprintf(stderr,"%sn",s);
  588.     return;
  589.   }
  590.   if(syslog_discard)
  591.     return;
  592.   if(syslog_fd != -1) {
  593.     char buf[1024];
  594.     time_t tt = time(NULL);
  595.     struct tm *t;
  596.     t = localtime(&tt);
  597.     strftime(buf,sizeof(buf),"%b %d %H:%M:%S ",t);
  598.     buf[sizeof(buf) - 1] = '';
  599.     snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
  600.              "%s proftpd[%u]: %s",syslog_hostname,
  601.              (unsigned int)getpid(),s);
  602.     buf[sizeof(buf)-1] = '';
  603.     write(syslog_fd,buf,strlen(buf));
  604.     write(syslog_fd,"n",1);
  605.     return;
  606.   }
  607.   if(set_facility != -1)
  608.     f = set_facility;
  609.   if(f != facility || !syslog_open)
  610.     openlog("proftpd", LOG_NDELAY | LOG_PID, f);
  611.   syslog(priority, "%sn", s);
  612.   if(!syslog_open)
  613.     closelog();
  614.   else if(f != facility)
  615.     openlog("proftpd", LOG_NDELAY | LOG_PID, facility);
  616. }
  617. void log_pri(int priority,char *fmt,...)
  618. {
  619.   char buf[1024];
  620.   va_list msg;
  621.   va_start(msg,fmt);
  622.   vsnprintf(buf, sizeof(buf), fmt, msg);
  623.   va_end(msg);
  624.   buf[1023] = '';
  625.   log(priority,facility,buf);
  626. }
  627. /* Like log_pri(), but sends the log entry in the LOG_AUTHPRIV
  628.  * facility (presumable it doesn't need to be seen by everyone
  629.  */
  630. void log_auth(int priority, char *fmt, ...)
  631. {
  632.   char buf[1024];
  633.   va_list msg;
  634.   va_start(msg,fmt);
  635.   vsnprintf(buf, sizeof(buf), fmt, msg);
  636.   va_end(msg);
  637.   buf[1023] = '';
  638.   log(priority, LOG_AUTHPRIV, buf);
  639. }
  640. /* Disable logging to stderr, should be done right before forking
  641.  * or disassociation from controlling tty.  After disabling stderr
  642.  * logging, all messages go to syslog.
  643.  */
  644. void log_stderr(int bool)
  645. {
  646.   logstderr = bool;
  647. }
  648. /* Set the debug logging level, see log.h for constants.  Higher
  649.  * numbers mean print more, DEBUG0 (0) == print no debugging log
  650.  * (default)
  651.  */
  652. int log_setdebuglevel(int level)
  653. {
  654.   int old_level = debug_level;
  655.   debug_level = level;
  656.   return old_level;
  657. }
  658. void log_debug(int level,char *str,...)
  659. {
  660.   char buf[1024];
  661.   va_list msg;
  662.   if(debug_level < level)
  663.     return;
  664.   va_start(msg,str);
  665.   vsnprintf(buf, sizeof(buf), str, msg);
  666.   va_end(msg);
  667.   buf[1023] = '';
  668.   log(LOG_DEBUG, facility, buf);
  669. }
  670. void init_log()
  671. {
  672.   char buf[256];
  673.   if(gethostname(buf, sizeof(buf)) == -1)
  674.     sstrncpy(buf, "localhost", sizeof(buf));
  675.   
  676.   syslog_hostname = inet_validate(pstrdup(permanent_pool, buf));
  677. }