/* This file is in the public domain. */ #include #include #include #include #include #include #include #include extern const char *__progname; #include "bpp.h" #include "errf.h" #include "panic.h" #include "config.h" #include "stdio-util.h" FILE *errf; static FILE *errf0; static char errf_ring[65536]; static int errf_head = 0; static int errf_n = 0; static void errf_ring_save(const char *buf, int len) { if (len < 0) len = strlen(buf); if (len > sizeof(errf_ring)) { buf += len - sizeof(errf_ring); len = sizeof(errf_ring); } if (errf_head+len > sizeof(errf_ring)) { int n; n = sizeof(errf_ring) - errf_head; bcopy(buf,&errf_ring[errf_head],n); bcopy(buf+n,&errf_ring[0],len-n); errf_head = len - n; } else { bcopy(buf,&errf_ring[errf_head],len); errf_head += len; } errf_n += len; if (errf_n > sizeof(errf_ring)) errf_n = sizeof(errf_ring); } static int errf_w(void *cookie __attribute__((__unused__)), const char *buf, int len0) { int len; int wrote; struct pollfd pfd; len = len0; while (len > 0) { errf_ring_save("[try ",-1); { char buf[64]; sprintf(&buf[0],"%d",len); errf_ring_save(&buf[0],-1); } errf_ring_save("]",-1); wrote = write(2,buf,len); if (wrote < 0) { switch (errno) { case EINTR: errf_ring_save("[EINTR]",-1); continue; break; case EWOULDBLOCK: errf_ring_save("[EWOULDBLOCK]",-1); pfd.fd = 2; pfd.events = POLLOUT | POLLWRNORM; poll(&pfd,1,100); continue; break; default: fcntl(2,F_SETFL,fcntl(2,F_GETFL,0)&~O_NONBLOCK); fprintf(stderr,"%s: stderr write error: %s\r\n",__progname,strerror(errno)); exit(1); break; } } errf_ring_save("[wrote ",-1); { char buf[64]; sprintf(&buf[0],"%d",wrote); errf_ring_save(&buf[0],-1); } errf_ring_save(":",-1); errf_ring_save(buf,wrote); errf_ring_save("]",-1); buf += wrote; len -= wrote; } return(len0); } void errf_setup(void) { errf = fwopen(0,&errf_w); setvbuf(errf,0,_IONBF,0); errf0 = errf; } void logmsg(int pri, const char *fmt, ...) { va_list ap; char *s; FILE *f; f = fopen_alloc(&s,0); va_start(ap,fmt); if (pri & LM_PEER) fprintf(f,"%s: ",bpp_peer_text()); vfprintf(f,fmt,ap); va_end(ap); putc('\0',f); fclose(f); if (config_bool("use-syslog")) { static int done = 0; int logpri; if (! done) { openlog(__progname,LOG_PID,LOG_AUTH); done = 1; } switch (pri & LM_SEV) { case LM_ERR: logpri = LOG_ERR; break; case LM_WARN: logpri = LOG_WARNING; break; case LM_NOTE: logpri = LOG_NOTICE; break; case LM_INFO: logpri = LOG_INFO; break; default: panic("bad pri"); break; } if (pri & LM_AUTH) logpri |= LOG_AUTHPRIV; else logpri |= LOG_AUTH; syslog(pri,"%s",s); } else { fprintf(errf,"%s: %s\r\n",__progname,s); } free(s); } typedef struct lmpriv LMPRIV; struct lmpriv { int pri; char *s; int l; } ; static int lm_w(void *pv, const char *data, int len) { LMPRIV *p; p = pv; p->s = realloc(p->s,p->l+len); bcopy(data,p->s+p->l,len); p->l += len; return(len); } static int lm_c(void *pv) { LMPRIV *p; lm_w(pv,"",1); p = pv; logmsg(p->pri,"%s",p->s); free(p->s); free(p); return(0); } FILE *logmsg_fopen(int pri) { FILE *f; LMPRIV *p; p = malloc(sizeof(LMPRIV)); if (p == 0) return(0); p->pri = pri; p->s = 0; p->l = 0; f = funopen(p,0,&lm_w,0,&lm_c); if (! f) free(p); return(f); }