3 * Jeff Wheelhouse (jdw@wwwi.com)
5 * This code was originally developed by Jeff Wheelhouse (jdw@wwwi.com).
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistribution of source code must retail the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY JEFF WHEELHOUSE ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
19 * NO EVENT SHALL JEFF WHEELHOUSE BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING BUT NOT
21 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
22 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
23 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * $Id: clog.c,v 1.3 2001/10/02 18:51:26 jdw Exp $
28 * $DragonFly: src/usr.sbin/clog/clog.c,v 1.2 2004/12/18 22:48:03 swildner Exp $
52 * The BUFFER_SIZE value is just used to allocate a buffer full of NULLs
53 * so that a new logfile can be extended to its full size.
55 * Compiling with -pedantic complains when the buffer array is declared
56 * if I declare this as a const instead of a #define.
58 #define BUFFER_SIZE 16384
60 void init_log __P((const char *lname, size_t size));
61 void read_log __P((const char *lname, int optf));
62 void usage __P((void));
66 int main(int argc, char **argv) {
74 while ((ch = getopt(argc, argv, "fis:")) != -1)
87 if ((size>0)&&(init==0)) {
88 fprintf(stderr,"%s: WARNING: -s argument ignored without -i.\n",pname);
91 if (argv[optind]==NULL) {
92 fprintf(stderr,"%s: ERROR: log_file argument must be specified.\n",pname);
95 if ((init==1)&&(size==0)) {
96 fprintf(stderr,"%s: ERROR: -i argument requires -s.\n",pname);
99 if ((init==1)&&(optf==1)) {
100 fprintf(stderr,"%s: ERROR: flags -f and -i are incompatible.\n",pname);
104 if (init==1) init_log(argv[optind],size);
105 /* if (optf==1) follow_log(artv[optind]); */
106 read_log(argv[optind],optf);
113 fprintf(stderr,"usage: %s [-i -s log_size] [ -f ] log_file\n",pname);
118 void read_log(const char *lname, int optf) {
121 struct clog_footer *pcf;
131 fd = open(lname,O_RDONLY);
133 fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno));
137 if (fstat(fd,&sb)==-1) {
138 fprintf(stderr,"%s: ERROR: could not stat %s (%s)\n",pname,lname,strerror(errno));
141 pbuffer = mmap(NULL,sb.st_size,PROT_READ,MAP_SHARED,fd,0);
143 fprintf(stderr,"%s: ERROR: could not mmap %s body (%s)\n",pname,lname,strerror(errno));
146 pcf = (struct clog_footer*)(pbuffer + sb.st_size - sizeof(struct clog_footer));
148 if (pcf->cf_wrap==1) start = pcf->cf_next + 1;
150 while(pcf->cf_lock==1) sched_yield();
154 iov[iovcnt].iov_base = pbuffer + start;
155 iov[iovcnt++].iov_len = pcf->cf_max - start;
158 iov[iovcnt].iov_base = pbuffer + start;
159 iov[iovcnt++].iov_len = next - start;
160 if (writev(1,iov,iovcnt)==-1) {
161 fprintf(stderr,"%s: ERROR: could not write output (%s)\n",pname,strerror(errno));
166 if (poll(&pfd,1,50)==-1) {
167 fprintf(stderr,"%s: ERROR: could not poll (%s)\n",pname,strerror(errno));
172 munmap(pbuffer,sb.st_size);
179 void init_log(const char *lname, size_t size) {
182 char buffer[BUFFER_SIZE];
183 struct clog_footer cf;
185 memcpy(&cf.cf_magic,MAGIC_CONST,4);
186 cf.cf_max = size - sizeof(struct clog_footer);
188 memset(buffer,0,BUFFER_SIZE);
190 fd = open(lname,O_RDWR|O_CREAT,0666);
192 fprintf(stderr,"%s: ERROR: could not open %s (%s)\n",pname,lname,strerror(errno));
195 if (ftruncate(fd,(off_t)0)==-1) {
196 fprintf(stderr,"%s: ERROR: could not truncate %s (%s)\n",pname,lname,strerror(errno));
200 while(fill>BUFFER_SIZE) {
201 if (write(fd,buffer,BUFFER_SIZE)==-1){
202 fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno));
207 assert(fill<=BUFFER_SIZE);
209 if (write(fd,buffer,fill)==-1) {
210 fprintf(stderr,"%s: ERROR: could not write %s (%s)\n",pname,lname,strerror(errno));
214 if (lseek(fd,-(off_t)(sizeof(struct clog_footer)),SEEK_END)==-1) {
215 fprintf(stderr,"%s: ERROR: could not seek in %s (%s)\n",pname,lname,strerror(errno));
218 if (write(fd,&cf,sizeof(cf))==-1) {
219 fprintf(stderr,"%s: ERROR: could not write magic in %s (%s)\n",pname,lname,strerror(errno));