diff -rc /usr/src/usr.sbin/syslogd/syslog.conf.5 syslogd/syslog.conf.5
*** /usr/src/usr.sbin/syslogd/syslog.conf.5	Tue Apr  3 11:25:59 2001
--- syslogd/syslog.conf.5	Mon Oct  1 22:56:53 2001
***************
*** 302,307 ****
--- 302,313 ----
  An asterisk.
  Selected messages are written to all logged-in users.
  .It
+ A percent sign
+ .Pq Dq \&% ,
+ followed by a pathname (beginning with a leading slash).  Selected messages
+ are written to a circular log file.  See clog(8) for a discussion of
+ circular log files.
+ .It
  A vertical bar
  .Pq Dq \&| ,
  followed by a command to pipe the selected
diff -rc /usr/src/usr.sbin/syslogd/syslogd.c syslogd/syslogd.c
*** /usr/src/usr.sbin/syslogd/syslogd.c	Sun Feb 18 10:22:59 2001
--- syslogd/syslogd.c	Mon Oct  1 22:47:58 2001
***************
*** 69,74 ****
--- 69,75 ----
   *   by Peter da Silva.
   * -u and -v by Harlan Stenn.
   * Priority comparison code by Harlan Stenn.
+  * Ring buffer code by Jeff Wheelhouse.
   */
  
  #define	MAXLINE		1024		/* maximum line length */
***************
*** 89,94 ****
--- 90,96 ----
  #include <sys/time.h>
  #include <sys/resource.h>
  #include <sys/syslimits.h>
+ #include <sys/mman.h>
  #include <paths.h>
  
  #include <netinet/in.h>
***************
*** 108,113 ****
--- 110,116 ----
  #include <unistd.h>
  #include <utmp.h>
  #include "pathnames.h"
+ #include "../clog/clog.h"
  
  #define SYSLOG_NAMES
  #include <sys/syslog.h>
***************
*** 121,126 ****
--- 124,130 ----
  const char	*ConfFile = _PATH_LOGCONF;
  const char	*PidFile = _PATH_LOGPID;
  const char	ctty[] = _PATH_CONSOLE;
+ const char  ring_magic[] = "CLOG";
  
  #define	dprintf		if (Debug) printf
  
***************
*** 171,176 ****
--- 175,185 ----
  			char	f_pname[MAXPATHLEN];
  			pid_t	f_pid;
  		} f_pipe;
+ 		struct {
+ 		  char		f_rname[MAXPATHLEN];
+ 			struct clog_footer *f_footer;
+ 			size_t	f_size;
+ 		} f_ring;
  	} f_un;
  	char	f_prevline[MAXSVLINE];		/* last message logged */
  	char	f_lasttime[16];			/* time of last occurrence */
***************
*** 246,255 ****
  #define F_USERS		5		/* list of users */
  #define F_WALL		6		/* everyone logged on */
  #define F_PIPE		7		/* pipe to program */
  
! char	*TypeNames[8] = {
  	"UNUSED",	"FILE",		"TTY",		"CONSOLE",
! 	"FORW",		"USERS",	"WALL",		"PIPE"
  };
  
  struct	filed *Files;
--- 255,266 ----
  #define F_USERS		5		/* list of users */
  #define F_WALL		6		/* everyone logged on */
  #define F_PIPE		7		/* pipe to program */
+ #define F_RING		8		/* ring buffer (circular log) */
  
! char	*TypeNames[9] = {
  	"UNUSED",	"FILE",		"TTY",		"CONSOLE",
! 	"FORW",		"USERS",	"WALL",		"PIPE",
! 	"RING"
  };
  
  struct	filed *Files;
***************
*** 299,304 ****
--- 310,317 ----
  void	printline __P((char *, char *));
  void	printsys __P((char *));
  int	p_open __P((char *, pid_t *));
+ ssize_t	rbwrite __P((struct filed *, char *, size_t));
+ ssize_t	rbwritev __P((struct filed *, struct iovec *, int));
  void	readklog __P((void));
  void	reapchild __P((int));
  char   *ttymsg __P((struct iovec *, int, char *, int));
***************
*** 1038,1043 ****
--- 1051,1071 ----
  			(void)fsync(f->f_file);
  		break;
  
+ 	case F_RING:
+ 		dprintf(" %s\n", f->f_un.f_ring.f_rname);
+ 		v->iov_base = "\n";
+ 		v->iov_len = 1;
+ 		if (rbwritev(f, iov, 7)==-1) {
+ 			int e = errno;
+ 			(void)munmap(f->f_un.f_ring.f_footer,sizeof(struct clog_footer));
+ 			(void)close(f->f_file);
+ 			f->f_type = F_UNUSED;
+ 			errno = e;
+ 			logerror(f->f_un.f_fname);
+ 		}
+ 
+ 		break;
+ 
  	case F_PIPE:
  		dprintf(" %s\n", f->f_un.f_pipe.f_pname);
  		v->iov_base = "\n";
***************
*** 1366,1371 ****
--- 1394,1403 ----
  					    f->f_un.f_pipe.f_pname);
  			f->f_un.f_pipe.f_pid = 0;
  			break;
+ 		case F_RING:
+ 			(void)munmap(f->f_un.f_ring.f_footer,sizeof(struct clog_footer));
+ 			(void)close(f->f_file);
+ 			break;
  		}
  		next = f->f_next;
  		if (f->f_program) free(f->f_program);
***************
*** 1475,1480 ****
--- 1507,1516 ----
  				printf("%s", f->f_un.f_forw.f_hname);
  				break;
  
+ 			case F_RING:
+ 				printf("%s", f->f_un.f_ring.f_rname);
+ 				break;
+ 
  			case F_PIPE:
  				printf("%s", f->f_un.f_pipe.f_pname);
  				break;
***************
*** 1508,1513 ****
--- 1544,1550 ----
  	int error, i, pri;
  	char *bp, *p, *q;
  	char buf[MAXLINE], ebuf[100];
+ 	struct stat sb;
  
  	dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host);
  
***************
*** 1660,1665 ****
--- 1697,1734 ----
  		}
  		break;
  
+   case '%':
+     if ((f->f_file = open(p+1, O_RDWR, 0 )) < 0) {
+ 			f->f_type = F_UNUSED;
+ 			logerror(p+1);
+ 			break;
+ 		}
+ 		if (fstat(f->f_file,&sb)<0) {
+ 			(void)close(f->f_file);
+ 			f->f_type = F_UNUSED;
+ 			logerror(p+1);
+ 			break;
+ 		}
+ 		f->f_un.f_ring.f_footer = mmap(NULL,sizeof(struct clog_footer),PROT_READ|PROT_WRITE,MAP_SHARED,f->f_file,sb.st_size-sizeof(struct clog_footer));
+ 		if (f->f_un.f_ring.f_footer==NULL) {
+ 			(void)close(f->f_file);
+ 			f->f_type = F_UNUSED;
+ 			logerror(p+1);
+ 			break;
+ 		}
+ 		if (memcmp(&(f->f_un.f_ring.f_footer->cf_magic),MAGIC_CONST,4)!=0) {
+ 			(void)munmap(f->f_un.f_ring.f_footer,sizeof(struct clog_footer));
+ 			(void)close(f->f_file);
+ 			f->f_type = F_UNUSED;
+ 			errno = ENODEV;
+ 			logerror(p+1);
+ 			break;
+ 		}
+ 		f->f_un.f_ring.f_size = sb.st_size;
+ 		(void)strcpy(f->f_un.f_ring.f_rname, p + 1);
+ 		f->f_type = F_RING;
+ 		break;
+ 
  	case '|':
  		f->f_un.f_pipe.f_pid = 0;
  		(void)strcpy(f->f_un.f_pipe.f_pname, p + 1);
***************
*** 2291,2293 ****
--- 2360,2409 ----
  
  	return(socks);
  }
+ 
+ 
+ ssize_t rbwritev(struct filed *f, struct iovec *iov, int iovcnt) {
+ 	int i;
+ 	ssize_t out = 0;
+ 	ssize_t err;
+ 
+ 	for(i=0;i<iovcnt;i++) {
+ 		err = rbwrite(f,iov[i].iov_base,iov[i].iov_len);
+ 		if (err==-1) return -1;
+ 		out += err;
+ 	}
+ 	return out;
+ }
+ 
+ 
+ ssize_t rbwrite(struct filed *f, char *buf, size_t nbytes) {
+ 	size_t maxwrite = f->f_un.f_ring.f_footer->cf_max - f->f_un.f_ring.f_footer->cf_next;
+ 	ssize_t err;
+ 	ssize_t out = 0;
+ 
+ 	f->f_un.f_ring.f_footer->cf_lock = 1;
+ 	while (nbytes>0) {
+ 		maxwrite = f->f_un.f_ring.f_footer->cf_max - f->f_un.f_ring.f_footer->cf_next;
+ 		if (maxwrite>nbytes) maxwrite = nbytes;
+ 		err = pwrite(f->f_file,buf,maxwrite,f->f_un.f_ring.f_footer->cf_next);
+ 		if (err==-1) {
+ 			f->f_un.f_ring.f_footer->cf_lock = 0;
+ 			return -1;
+ 		}
+ 		nbytes -= err;
+ 		out += err;
+ 		buf += err;
+ 		f->f_un.f_ring.f_footer->cf_next += err;
+ 		if (f->f_un.f_ring.f_footer->cf_next==f->f_un.f_ring.f_footer->cf_max) {
+ 			f->f_un.f_ring.f_footer->cf_next = 0;
+ 			f->f_un.f_ring.f_footer->cf_wrap = 1;
+ 		}
+ 		
+ 	}
+ 			
+ 	f->f_un.f_ring.f_footer->cf_lock = 0;
+ 	return out;
+ }
+ 
+ 
+ 
