From 534b2416b5e907c371f2d46b501b777076141136 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 30 Oct 2004 20:26:48 +0000 Subject: [PATCH] Bring in Jeff Wheelhouse's CLOG / circular log file support for syslogd, With some formatting changes. Side note: CLOG's use of mmap within syslogd is very dangerous and could lead to syslogd seg-faulting out, especially since the control structure appears to reside at the end of the physical log file. Users of circular log files must take care. Requested-by: The MOB! --- usr.sbin/Makefile | 3 +- usr.sbin/clog/Makefile | 10 ++ usr.sbin/clog/clog.8 | 99 +++++++++++++++ usr.sbin/clog/clog.c | 226 +++++++++++++++++++++++++++++++++ usr.sbin/clog/clog.h | 54 ++++++++ usr.sbin/syslogd/syslog.conf.5 | 8 +- usr.sbin/syslogd/syslogd.c | 136 +++++++++++++++++++- 7 files changed, 531 insertions(+), 5 deletions(-) create mode 100644 usr.sbin/clog/Makefile create mode 100644 usr.sbin/clog/clog.8 create mode 100644 usr.sbin/clog/clog.c create mode 100644 usr.sbin/clog/clog.h diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index f1a0ab0a5c..f83d8cebed 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,6 +1,6 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 # $FreeBSD: src/usr.sbin/Makefile,v 1.183.2.14 2003/04/16 11:01:51 ru Exp $ -# $DragonFly: src/usr.sbin/Makefile,v 1.14 2004/09/23 06:38:29 simokawa Exp $ +# $DragonFly: src/usr.sbin/Makefile,v 1.15 2004/10/30 20:26:44 dillon Exp $ # XXX MISSING: mkproto SUBDIR= IPXrouted \ @@ -21,6 +21,7 @@ SUBDIR= IPXrouted \ chown \ chroot \ ckdist \ + clog \ config \ cron \ crunch \ diff --git a/usr.sbin/clog/Makefile b/usr.sbin/clog/Makefile new file mode 100644 index 0000000000..415b569ef9 --- /dev/null +++ b/usr.sbin/clog/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 +# $Id: Makefile,v 1.2 2001/10/02 06:03:21 jdw Exp $ +# $DragonFly: src/usr.sbin/clog/Makefile,v 1.1 2004/10/30 20:26:46 dillon Exp $ + +PROG= clog +SRCS= clog.c +MAN8= clog.8 +COPTS+= -Wall + +.include diff --git a/usr.sbin/clog/clog.8 b/usr.sbin/clog/clog.8 new file mode 100644 index 0000000000..9d23d72f28 --- /dev/null +++ b/usr.sbin/clog/clog.8 @@ -0,0 +1,99 @@ +.\" Copyright (c) 2001 +.\" Jeffrey D. Wheelhouse. All rights reserved. +.\" +.\" This code was originally developed by Jeff Wheelhouse (jdw@wwwi.com). +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY JEFF WHEELHOUSE ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN +.\" NO EVENT SHALL JEFF WHEELHOUSE BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT +.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, +.\" OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: clog.8,v 1.2 2001/10/02 04:41:21 jdw Exp $ +.\" $DragonFly: src/usr.sbin/clog/clog.8,v 1.1 2004/10/30 20:26:46 dillon Exp $ +.\" +.Dd October 1, 2001 +.Dt CLOG 8 +.Os BSD 4 +.Sh NAME +.Nm clog +.Nd "display or initialize a circular system log" +.Sh SYNOPSIS +.Nm +.Op Fl f +.Op Fl i Fl s Ar size +.Ar logfile +.Sh DESCRIPTION +.Nm Clog +displays or initializes a circular log file. +.Pp +The options are as follows: +.Bl -tag -width indent +.It Fl f +Display the contents of the circular logfile +.Ar logfile , +then go into a loop waiting for +new material to arrive. This is essentially the same as using the +.Fl f +option of the +.Xr tail 1 +command on a standard syslog file. +.It Fl i +Initialize +.Ar logfile +rather than reading it. This option requires the +.Fl s +option. If +.Ar logfile +already exists, it will be truncated and recreated by this command. +.It Fl s +This option specifies the size in bytes of the circular logfile that should +be created. This option requires the +.Fl i +option. +.El +.Sh ABOUT CIRCULAR LOGFILES +The +.Nm +command supports circular logfiles for +.Xr syslogd 8 . +A circular logfile differs from a standard syslog file in that is has a fixed +size. It does not grow, and does not need to be rotated. When +.Xr syslogd 8 +reaches the end of a circular logfile, it simply begins again at the beginning, +overwriting the oldest data. The circular logfile also contains information +allowing +.Nm +to establish what parts of the file are valid, and in what order they should +be displayed. +.Pp +Circular logfiles are primarily useful for their ability to control the amount +of storage devoted to logfiles. This may be valuable when storage space is +at a premium or when the consequences of running out of storage space are +unacceptable. Circular logfiles can safely be used on a memory disk (see +.Xr md 4 ). +.Pp +Circular logfiles are also useful to catch messages that are generated rapidly +but soon lose relevance, such as messages logged at debug priority. + +.Sh SEE ALSO +.Xr syslogd 8 , +.Xr syslog.conf 5 +.Sh HISTORY +The +.Nm +command was written for FreeBSD 4.3 but is not yet part of a BSD distribution. diff --git a/usr.sbin/clog/clog.c b/usr.sbin/clog/clog.c new file mode 100644 index 0000000000..87fb6c10b0 --- /dev/null +++ b/usr.sbin/clog/clog.c @@ -0,0 +1,226 @@ +/*- + * Copyright (c) 2001 + * Jeff Wheelhouse (jdw@wwwi.com) + * + * This code was originally developed by Jeff Wheelhouse (jdw@wwwi.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistribution of source code must retail the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JEFF WHEELHOUSE ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL JEFF WHEELHOUSE BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: clog.c,v 1.3 2001/10/02 18:51:26 jdw Exp $ + * $DragonFly: src/usr.sbin/clog/clog.c,v 1.1 2004/10/30 20:26:46 dillon Exp $ + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#include "clog.h" + + +/* + * The BUFFER_SIZE value is just used to allocate a buffer full of NULLs + * so that a new logfile can be extended to its full size. + * + * Compiling with -pedantic complains when the buffer array is declared + * if I declare this as a const instead of a #define. + */ +#define BUFFER_SIZE 16384 + +void init_log __P((const char *lname, size_t size)); +void read_log __P((const char *lname, int optf)); +void usage __P((void)); + +const char *pname; + +int main(int argc, char **argv) { + int ch; + int init = 0; + int size = 0; + int optf = 0; + + pname = argv[0]; + + while ((ch = getopt(argc, argv, "fis:")) != -1) + switch(ch) { + case 'i': + init = 1; + break; + case 's': + size = atol(optarg); + if (size==0) usage(); + break; + case 'f': + optf = 1; + } + + if ((size>0)&&(init==0)) { + fprintf(stderr,"%s: WARNING: -s argument ignored without -i.\n",pname); + size = 0; + } + if (argv[optind]==NULL) { + fprintf(stderr,"%s: ERROR: log_file argument must be specified.\n",pname); + usage(); + } + if ((init==1)&&(size==0)) { + fprintf(stderr,"%s: ERROR: -i argument requires -s.\n",pname); + usage(); + } + if ((init==1)&&(optf==1)) { + fprintf(stderr,"%s: ERROR: flags -f and -i are incompatible.\n",pname); + usage(); + } + + if (init==1) init_log(argv[optind],size); + /* if (optf==1) follow_log(artv[optind]); */ + read_log(argv[optind],optf); + + return 0; +} + + +void usage() { + fprintf(stderr,"usage: %s [-i -s log_size] [ -f ] log_file\n",pname); + exit(1); +} + + +void read_log(const char *lname, int optf) { + int fd; + struct stat sb; + struct clog_footer *pcf; + char *pbuffer; + struct iovec iov[2]; + int iovcnt = 0; + uint32_t start = 0; + uint32_t next; + struct pollfd pfd; + + pfd.fd = -1; + + fd = open(lname,O_RDONLY); + if (fd==-1) { + fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno)); + exit(11); + } + + if (fstat(fd,&sb)==-1) { + fprintf(stderr,"%s: ERROR: could not stat %s (%s)\n",pname,lname,strerror(errno)); + exit(13); + } + pbuffer = mmap(NULL,sb.st_size,PROT_READ,MAP_SHARED,fd,0); + if (pbuffer==NULL) { + fprintf(stderr,"%s: ERROR: could not mmap %s body (%s)\n",pname,lname,strerror(errno)); + exit(14); + } + pcf = (struct clog_footer*)(pbuffer + sb.st_size - sizeof(struct clog_footer)); + + if (pcf->cf_wrap==1) start = pcf->cf_next + 1; + while(1) { + while(pcf->cf_lock==1) sched_yield(); + next = pcf->cf_next; + iovcnt = 0; + if (start>next) { + iov[iovcnt].iov_base = pbuffer + start; + iov[iovcnt++].iov_len = pcf->cf_max - start; + start = 0; + } + iov[iovcnt].iov_base = pbuffer + start; + iov[iovcnt++].iov_len = next - start; + if (writev(1,iov,iovcnt)==-1) { + fprintf(stderr,"%s: ERROR: could not write output (%s)\n",pname,strerror(errno)); + exit(15); + } + start = next; + if (optf==0) break; + if (poll(&pfd,1,50)==-1) { + fprintf(stderr,"%s: ERROR: could not poll (%s)\n",pname,strerror(errno)); + exit(16); + } + } + + (void)munmap(pbuffer,sb.st_size); + (void)close(fd); + + exit(0); +} + + +void init_log(const char *lname, size_t size) { + int fd; + size_t fill = size; + char buffer[BUFFER_SIZE]; + struct clog_footer cf; + + memcpy(&cf.cf_magic,MAGIC_CONST,4); + cf.cf_max = size - sizeof(struct clog_footer); + + (void)memset(buffer,0,BUFFER_SIZE); + + fd = open(lname,O_RDWR|O_CREAT,0666); + if (fd==-1) { + fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno)); + exit(2); + } + if (ftruncate(fd,(off_t)0)==-1) { + fprintf(stderr,"%s: ERROR: could not truncate %s (%s)\n",pname,lname,strerror(errno)); + exit(3); + } + + while(fill>BUFFER_SIZE) { + if (write(fd,buffer,BUFFER_SIZE)==-1){ + fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno)); + exit(4); + } + fill -= BUFFER_SIZE; + } + assert(fill<=BUFFER_SIZE); + if (fill>0) { + if (write(fd,buffer,fill)==-1) { + fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno)); + exit(5); + } + } + if (lseek(fd,-(off_t)(sizeof(struct clog_footer)),SEEK_END)==-1) { + fprintf(stderr,"%s: ERROR: could not seek in %s (%s)\n",pname,lname,strerror(errno)); + exit(6); + } + if (write(fd,&cf,sizeof(cf))==-1) { + fprintf(stderr,"%s: ERROR: could not write magic in %s (%s)\n",pname,lname,strerror(errno)); + exit(7); + } + (void)close(fd); + exit(0); +} + + diff --git a/usr.sbin/clog/clog.h b/usr.sbin/clog/clog.h new file mode 100644 index 0000000000..14189c317f --- /dev/null +++ b/usr.sbin/clog/clog.h @@ -0,0 +1,54 @@ +/*- + * Copyright (c) 2001 + * Jeff Wheelhouse (jdw@wwwi.com) + * + * This code was originally developed by Jeff Wheelhouse (jdw@wwwi.com). + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistribution of source code must retail the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY JEFF WHEELHOUSE ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN + * NO EVENT SHALL JEFF WHEELHOUSE BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, + * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $Id: clog.h,v 1.2 2001/10/02 04:43:52 jdw Exp $ + * $DragonFly: src/usr.sbin/clog/clog.h,v 1.1 2004/10/30 20:26:46 dillon Exp $ + */ + + +#ifndef _CLOG_H_ +#define _CLOG_H_ + +/* + * This magic constant is used to identify a valid circular log file. + * syslogd will ignore any circular log file that doesn't have this constant. + */ + +const char MAGIC_CONST[4] = "CLOG"; + + +struct clog_footer { + uint32_t cf_magic; + uint32_t cf_wrap; + uint32_t cf_next; + uint32_t cf_max; + uint32_t cf_lock; +}; + + +#endif /* _CLOG_H_ */ + + diff --git a/usr.sbin/syslogd/syslog.conf.5 b/usr.sbin/syslogd/syslog.conf.5 index 4bba15484e..cf12b31458 100644 --- a/usr.sbin/syslogd/syslog.conf.5 +++ b/usr.sbin/syslogd/syslog.conf.5 @@ -31,7 +31,7 @@ .\" .\" @(#)syslog.conf.5 8.1 (Berkeley) 6/9/93 .\" $FreeBSD: src/usr.sbin/syslogd/syslog.conf.5,v 1.35 2004/07/03 18:35:53 ru Exp $ -.\" $DragonFly: src/usr.sbin/syslogd/syslog.conf.5,v 1.3 2004/08/09 20:11:19 dillon Exp $ +.\" $DragonFly: src/usr.sbin/syslogd/syslog.conf.5,v 1.4 2004/10/30 20:26:48 dillon Exp $ .\" .Dd June 9, 1993 .Dt SYSLOG.CONF 5 @@ -350,6 +350,12 @@ if they are logged in. 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 --git a/usr.sbin/syslogd/syslogd.c b/usr.sbin/syslogd/syslogd.c index c5de032f69..50b242faf2 100644 --- a/usr.sbin/syslogd/syslogd.c +++ b/usr.sbin/syslogd/syslogd.c @@ -33,7 +33,7 @@ * @(#) Copyright (c) 1983, 1988, 1993, 1994 The Regents of the University of California. All rights reserved. * @(#)syslogd.c 8.3 (Berkeley) 4/4/94 * $FreeBSD: src/usr.sbin/syslogd/syslogd.c,v 1.130 2004/07/04 19:52:48 cperciva Exp $ - * $DragonFly: src/usr.sbin/syslogd/syslogd.c,v 1.3 2004/08/09 20:11:19 dillon Exp $ + * $DragonFly: src/usr.sbin/syslogd/syslogd.c,v 1.4 2004/10/30 20:26:48 dillon Exp $ */ /* @@ -60,6 +60,7 @@ * 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 */ @@ -80,6 +81,7 @@ #include #include #include +#include #include #include @@ -103,6 +105,7 @@ #include "pathnames.h" #include "ttymsg.h" +#include "../clog/clog.h" #define SYSLOG_NAMES #include @@ -116,6 +119,7 @@ static const int withscopeid; 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 @@ -168,6 +172,11 @@ struct filed { 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,10 +255,12 @@ int repeatinterval[] = { 30, 120, 600 }; /* # of secs before flush */ #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) */ -const char *TypeNames[8] = { +const char *TypeNames[] = { "UNUSED", "FILE", "TTY", "CONSOLE", - "FORW", "USERS", "WALL", "PIPE" + "FORW", "USERS", "WALL", "PIPE", + "RING" }; static struct filed *Files; /* Log files that we write to */ @@ -309,6 +320,8 @@ static int skip_message(const char *, const char *, int); static void printline(const char *, char *); static void printsys(char *); static int p_open(const char *, pid_t *); +ssize_t rbwrite(struct filed *, char *, size_t); +ssize_t rbwritev(struct filed *, struct iovec *, int); static void readklog(void); static void reapchild(int); static void usage(void); @@ -1169,6 +1182,21 @@ fprintlog(struct filed *f, int flags, const char *msg) } 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; + munmap(f->f_un.f_ring.f_footer, + sizeof(struct clog_footer)); + 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 = lf; @@ -1482,6 +1510,11 @@ init(int signo) } f->f_un.f_pipe.f_pid = 0; break; + case F_RING: + munmap(f->f_un.f_ring.f_footer, + sizeof(struct clog_footer)); + close(f->f_file); + break; } next = f->f_next; if (f->f_program) free(f->f_program); @@ -1604,6 +1637,10 @@ init(int signo) 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; @@ -1654,6 +1691,7 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host) const char *p, *q; char *bp; char buf[MAXLINE], ebuf[100]; + struct stat sb; dprintf("cfline(\"%s\", f, \"%s\", \"%s\")\n", line, prog, host); @@ -1842,6 +1880,42 @@ cfline(const char *line, struct filed *f, const char *prog, const char *host) } 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) { + 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) { + 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) { + munmap(f->f_un.f_ring.f_footer, + sizeof(struct clog_footer)); + 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; + 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)strlcpy(f->f_un.f_fname, p + 1, sizeof(f->f_un.f_fname)); @@ -2530,3 +2604,59 @@ socksetup(int af, const char *bindhostname) return (socks); } + +ssize_t +rbwritev(struct filed *f, struct iovec *iov, int iovcnt) +{ + int i; + ssize_t out = 0; + ssize_t error; + + for (i = 0; i < iovcnt; i++) { + error = rbwrite(f, iov[i].iov_base, iov[i].iov_len); + if (error == -1) + return (-1); + out += error; + } + return (out); +} + + +ssize_t +rbwrite(struct filed *f, char *buf, size_t nbytes) +{ + size_t maxwrite; + ssize_t error; + ssize_t out; + + maxwrite = f->f_un.f_ring.f_footer->cf_max - + f->f_un.f_ring.f_footer->cf_next; + 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; + error = pwrite(f->f_file, buf, maxwrite, + f->f_un.f_ring.f_footer->cf_next); + if (error == -1) { + f->f_un.f_ring.f_footer->cf_lock = 0; + return (-1); + } + nbytes -= error; + out += error; + buf += error; + f->f_un.f_ring.f_footer->cf_next += error; + 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); +} -- 2.41.0