xref: /dflybsd-src/usr.sbin/clog/clog.c (revision fe08e20ddf9efaf51ce4fbe089d786a1989e1262)
1534b2416SMatthew Dillon /*-
2534b2416SMatthew Dillon  * Copyright (c) 2001
3534b2416SMatthew Dillon  *     Jeff Wheelhouse (jdw@wwwi.com)
4534b2416SMatthew Dillon  *
5534b2416SMatthew Dillon  * This code was originally developed by Jeff Wheelhouse (jdw@wwwi.com).
6534b2416SMatthew Dillon  *
7534b2416SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
8534b2416SMatthew Dillon  * modification, are permitted provided that the following conditions
9534b2416SMatthew Dillon  * are met:
10534b2416SMatthew Dillon  * 1. Redistribution of source code must retail the above copyright
11534b2416SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
12534b2416SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
13534b2416SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
14534b2416SMatthew Dillon  *    documentation and/or other materials provided with the distribution.
15534b2416SMatthew Dillon  *
16534b2416SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY JEFF WHEELHOUSE ``AS IS'' AND ANY EXPRESS OR
17534b2416SMatthew Dillon  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18534b2416SMatthew Dillon  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
19534b2416SMatthew Dillon  * NO EVENT SHALL JEFF WHEELHOUSE BE LIABLE FOR ANY DIRECT, INDIRECT,
20534b2416SMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT
21534b2416SMatthew Dillon  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22534b2416SMatthew Dillon  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23534b2416SMatthew Dillon  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24534b2416SMatthew Dillon  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25534b2416SMatthew Dillon  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26534b2416SMatthew Dillon  *
27534b2416SMatthew Dillon  * $Id: clog.c,v 1.3 2001/10/02 18:51:26 jdw Exp $
28534b2416SMatthew Dillon  */
29534b2416SMatthew Dillon 
30534b2416SMatthew Dillon 
31534b2416SMatthew Dillon #include <assert.h>
32534b2416SMatthew Dillon #include <errno.h>
33534b2416SMatthew Dillon #include <fcntl.h>
34534b2416SMatthew Dillon #include <poll.h>
35534b2416SMatthew Dillon #include <signal.h>
36534b2416SMatthew Dillon #include <stdio.h>
37534b2416SMatthew Dillon #include <stdlib.h>
38534b2416SMatthew Dillon #include <string.h>
39534b2416SMatthew Dillon #include <unistd.h>
40534b2416SMatthew Dillon 
41534b2416SMatthew Dillon #include <sys/mman.h>
42c4dd4100SJoe Talbott #include <sys/sched.h>
43534b2416SMatthew Dillon #include <sys/stat.h>
44534b2416SMatthew Dillon #include <sys/uio.h>
45534b2416SMatthew Dillon 
46534b2416SMatthew Dillon 
47534b2416SMatthew Dillon #include "clog.h"
48534b2416SMatthew Dillon 
49534b2416SMatthew Dillon 
50534b2416SMatthew Dillon /*
51534b2416SMatthew Dillon  *  The BUFFER_SIZE value is just used to allocate a buffer full of NULLs
52534b2416SMatthew Dillon  *  so that a new logfile can be extended to its full size.
53534b2416SMatthew Dillon  *
54534b2416SMatthew Dillon  *  Compiling with -pedantic complains when the buffer array is declared
55534b2416SMatthew Dillon  *  if I declare this as a const instead of a #define.
56534b2416SMatthew Dillon  */
57534b2416SMatthew Dillon #define BUFFER_SIZE 16384
58534b2416SMatthew Dillon 
59*fe08e20dSSascha Wildner static void init_log(const char *lname, size_t size) __dead2;
60*fe08e20dSSascha Wildner static void read_log(const char *lname, int optf) __dead2;
61*fe08e20dSSascha Wildner static void usage(void) __dead2;
62534b2416SMatthew Dillon 
63bf3beda6SSascha Wildner static const char *pname;
64534b2416SMatthew Dillon 
65a4c90f86SSascha Wildner int
main(int argc,char ** argv)66a4c90f86SSascha Wildner main(int argc, char **argv)
67a4c90f86SSascha Wildner {
68534b2416SMatthew Dillon 	int ch;
69534b2416SMatthew Dillon 	int init = 0;
70534b2416SMatthew Dillon 	int size = 0;
71534b2416SMatthew Dillon 	int optf = 0;
72534b2416SMatthew Dillon 
73534b2416SMatthew Dillon 	pname = argv[0];
74534b2416SMatthew Dillon 
75534b2416SMatthew Dillon 	while ((ch = getopt(argc, argv, "fis:")) != -1)
76534b2416SMatthew Dillon 		switch(ch) {
77534b2416SMatthew Dillon 		case 'i':
78534b2416SMatthew Dillon 			init = 1;
79534b2416SMatthew Dillon 			break;
80534b2416SMatthew Dillon 		case 's':
81534b2416SMatthew Dillon 			size = atol(optarg);
82534b2416SMatthew Dillon 			if (size==0) usage();
83534b2416SMatthew Dillon 			break;
84534b2416SMatthew Dillon 		case 'f':
85534b2416SMatthew Dillon 			optf = 1;
86534b2416SMatthew Dillon 		}
87534b2416SMatthew Dillon 
88534b2416SMatthew Dillon 	if ((size>0)&&(init==0)) {
89534b2416SMatthew Dillon 		fprintf(stderr,"%s: WARNING: -s argument ignored without -i.\n",pname);
90534b2416SMatthew Dillon 		size = 0;
91534b2416SMatthew Dillon 	}
92534b2416SMatthew Dillon 	if (argv[optind]==NULL) {
93534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: log_file argument must be specified.\n",pname);
94534b2416SMatthew Dillon 		usage();
95534b2416SMatthew Dillon 	}
96534b2416SMatthew Dillon 	if ((init==1)&&(size==0)) {
97534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: -i argument requires -s.\n",pname);
98534b2416SMatthew Dillon 		usage();
99534b2416SMatthew Dillon 	}
100534b2416SMatthew Dillon 	if ((init==1)&&(optf==1)) {
101534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: flags -f and -i are incompatible.\n",pname);
102534b2416SMatthew Dillon 		usage();
103534b2416SMatthew Dillon 	}
104534b2416SMatthew Dillon 
105534b2416SMatthew Dillon 	if (init==1) init_log(argv[optind],size);
106534b2416SMatthew Dillon 	/* if (optf==1) follow_log(artv[optind]); */
107534b2416SMatthew Dillon 	read_log(argv[optind],optf);
108534b2416SMatthew Dillon 
109534b2416SMatthew Dillon 	return 0;
110534b2416SMatthew Dillon }
111534b2416SMatthew Dillon 
112534b2416SMatthew Dillon 
113bf3beda6SSascha Wildner static void
usage(void)114a4c90f86SSascha Wildner usage(void)
115a4c90f86SSascha Wildner {
116534b2416SMatthew Dillon   fprintf(stderr,"usage: %s [-i -s log_size] [ -f ] log_file\n",pname);
117534b2416SMatthew Dillon   exit(1);
118534b2416SMatthew Dillon }
119534b2416SMatthew Dillon 
120534b2416SMatthew Dillon 
121bf3beda6SSascha Wildner static void
read_log(const char * lname,int optf)122a4c90f86SSascha Wildner read_log(const char *lname, int optf)
123a4c90f86SSascha Wildner {
124534b2416SMatthew Dillon 	int fd;
125534b2416SMatthew Dillon 	struct stat sb;
126534b2416SMatthew Dillon 	struct clog_footer *pcf;
127534b2416SMatthew Dillon 	char *pbuffer;
128534b2416SMatthew Dillon 	struct iovec iov[2];
129534b2416SMatthew Dillon 	int iovcnt = 0;
130534b2416SMatthew Dillon 	uint32_t start = 0;
131534b2416SMatthew Dillon 	uint32_t next;
132534b2416SMatthew Dillon 	struct pollfd pfd;
133534b2416SMatthew Dillon 
134534b2416SMatthew Dillon 	pfd.fd = -1;
135534b2416SMatthew Dillon 
136534b2416SMatthew Dillon 	fd = open(lname,O_RDONLY);
137534b2416SMatthew Dillon 	if (fd==-1) {
138534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno));
139534b2416SMatthew Dillon 		exit(11);
140534b2416SMatthew Dillon 	}
141534b2416SMatthew Dillon 
142534b2416SMatthew Dillon 	if (fstat(fd,&sb)==-1) {
143534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not stat %s (%s)\n",pname,lname,strerror(errno));
144534b2416SMatthew Dillon 		exit(13);
145534b2416SMatthew Dillon 	}
146534b2416SMatthew Dillon 	pbuffer = mmap(NULL,sb.st_size,PROT_READ,MAP_SHARED,fd,0);
147534b2416SMatthew Dillon 	if (pbuffer==NULL) {
148534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not mmap %s body (%s)\n",pname,lname,strerror(errno));
149534b2416SMatthew Dillon 		exit(14);
150534b2416SMatthew Dillon 	}
151534b2416SMatthew Dillon 	pcf = (struct clog_footer*)(pbuffer + sb.st_size - sizeof(struct clog_footer));
152534b2416SMatthew Dillon 
153534b2416SMatthew Dillon 	if (pcf->cf_wrap==1) start = pcf->cf_next + 1;
154534b2416SMatthew Dillon 	while(1) {
155534b2416SMatthew Dillon 		while(pcf->cf_lock==1) sched_yield();
156534b2416SMatthew Dillon 		next = pcf->cf_next;
157534b2416SMatthew Dillon 		iovcnt = 0;
158534b2416SMatthew Dillon 		if (start>next) {
159534b2416SMatthew Dillon 			iov[iovcnt].iov_base = pbuffer + start;
160534b2416SMatthew Dillon 			iov[iovcnt++].iov_len = pcf->cf_max - start;
161534b2416SMatthew Dillon 			start = 0;
162534b2416SMatthew Dillon 		}
163534b2416SMatthew Dillon 		iov[iovcnt].iov_base = pbuffer + start;
164534b2416SMatthew Dillon 		iov[iovcnt++].iov_len = next - start;
165534b2416SMatthew Dillon 		if (writev(1,iov,iovcnt)==-1) {
166534b2416SMatthew Dillon 			fprintf(stderr,"%s: ERROR: could not write output (%s)\n",pname,strerror(errno));
167534b2416SMatthew Dillon 			exit(15);
168534b2416SMatthew Dillon 		}
169534b2416SMatthew Dillon 		start = next;
170534b2416SMatthew Dillon 		if (optf==0) break;
171534b2416SMatthew Dillon 		if (poll(&pfd,1,50)==-1) {
172534b2416SMatthew Dillon 			fprintf(stderr,"%s: ERROR: could not poll (%s)\n",pname,strerror(errno));
173534b2416SMatthew Dillon 			exit(16);
174534b2416SMatthew Dillon 		}
175534b2416SMatthew Dillon 	}
176534b2416SMatthew Dillon 
17771126e33SSascha Wildner 	munmap(pbuffer,sb.st_size);
17871126e33SSascha Wildner 	close(fd);
179534b2416SMatthew Dillon 
180534b2416SMatthew Dillon 	exit(0);
181534b2416SMatthew Dillon }
182534b2416SMatthew Dillon 
183534b2416SMatthew Dillon 
184bf3beda6SSascha Wildner static void
init_log(const char * lname,size_t size)185a4c90f86SSascha Wildner init_log(const char *lname, size_t size)
186a4c90f86SSascha Wildner {
187534b2416SMatthew Dillon 	int fd;
188534b2416SMatthew Dillon 	size_t fill = size;
189534b2416SMatthew Dillon 	char buffer[BUFFER_SIZE];
190534b2416SMatthew Dillon 	struct clog_footer cf;
191534b2416SMatthew Dillon 
192534b2416SMatthew Dillon 	memcpy(&cf.cf_magic,MAGIC_CONST,4);
193534b2416SMatthew Dillon 	cf.cf_max = size - sizeof(struct clog_footer);
194534b2416SMatthew Dillon 
19571126e33SSascha Wildner 	memset(buffer,0,BUFFER_SIZE);
196534b2416SMatthew Dillon 
197534b2416SMatthew Dillon 	fd = open(lname,O_RDWR|O_CREAT,0666);
198534b2416SMatthew Dillon 	if (fd==-1) {
199534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno));
200534b2416SMatthew Dillon 		exit(2);
201534b2416SMatthew Dillon 	}
202534b2416SMatthew Dillon 	if (ftruncate(fd,(off_t)0)==-1) {
203534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not truncate %s (%s)\n",pname,lname,strerror(errno));
204534b2416SMatthew Dillon 		exit(3);
205534b2416SMatthew Dillon 	}
206534b2416SMatthew Dillon 
207534b2416SMatthew Dillon 	while(fill>BUFFER_SIZE) {
208534b2416SMatthew Dillon 		if (write(fd,buffer,BUFFER_SIZE)==-1){
209534b2416SMatthew Dillon 			fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno));
210534b2416SMatthew Dillon 			exit(4);
211534b2416SMatthew Dillon 		}
212534b2416SMatthew Dillon 		fill -= BUFFER_SIZE;
213534b2416SMatthew Dillon 	}
214534b2416SMatthew Dillon 	assert(fill<=BUFFER_SIZE);
215534b2416SMatthew Dillon 	if (fill>0) {
216534b2416SMatthew Dillon 		if (write(fd,buffer,fill)==-1) {
217534b2416SMatthew Dillon 			fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno));
218534b2416SMatthew Dillon 			exit(5);
219534b2416SMatthew Dillon 		}
220534b2416SMatthew Dillon 	}
221534b2416SMatthew Dillon 	if (lseek(fd,-(off_t)(sizeof(struct clog_footer)),SEEK_END)==-1) {
222534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not seek in %s (%s)\n",pname,lname,strerror(errno));
223534b2416SMatthew Dillon 		exit(6);
224534b2416SMatthew Dillon 	}
225534b2416SMatthew Dillon 	if (write(fd,&cf,sizeof(cf))==-1) {
226534b2416SMatthew Dillon 		fprintf(stderr,"%s: ERROR: could not write magic in %s (%s)\n",pname,lname,strerror(errno));
227534b2416SMatthew Dillon 		exit(7);
228534b2416SMatthew Dillon 	}
22971126e33SSascha Wildner 	close(fd);
230534b2416SMatthew Dillon 	exit(0);
231534b2416SMatthew Dillon }
232