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.4 2007/06/26 23:30:05 josepht Exp $
43 #include <sys/sched.h>
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(const char *lname
, size_t size
);
61 void read_log(const char *lname
, int optf
);
67 main(int argc
, char **argv
)
76 while ((ch
= getopt(argc
, argv
, "fis:")) != -1)
89 if ((size
>0)&&(init
==0)) {
90 fprintf(stderr
,"%s: WARNING: -s argument ignored without -i.\n",pname
);
93 if (argv
[optind
]==NULL
) {
94 fprintf(stderr
,"%s: ERROR: log_file argument must be specified.\n",pname
);
97 if ((init
==1)&&(size
==0)) {
98 fprintf(stderr
,"%s: ERROR: -i argument requires -s.\n",pname
);
101 if ((init
==1)&&(optf
==1)) {
102 fprintf(stderr
,"%s: ERROR: flags -f and -i are incompatible.\n",pname
);
106 if (init
==1) init_log(argv
[optind
],size
);
107 /* if (optf==1) follow_log(artv[optind]); */
108 read_log(argv
[optind
],optf
);
117 fprintf(stderr
,"usage: %s [-i -s log_size] [ -f ] log_file\n",pname
);
123 read_log(const char *lname
, int optf
)
127 struct clog_footer
*pcf
;
137 fd
= open(lname
,O_RDONLY
);
139 fprintf(stderr
,"%s: ERROR: could not open %s (%s)\n",pname
,lname
,strerror(errno
));
143 if (fstat(fd
,&sb
)==-1) {
144 fprintf(stderr
,"%s: ERROR: could not stat %s (%s)\n",pname
,lname
,strerror(errno
));
147 pbuffer
= mmap(NULL
,sb
.st_size
,PROT_READ
,MAP_SHARED
,fd
,0);
149 fprintf(stderr
,"%s: ERROR: could not mmap %s body (%s)\n",pname
,lname
,strerror(errno
));
152 pcf
= (struct clog_footer
*)(pbuffer
+ sb
.st_size
- sizeof(struct clog_footer
));
154 if (pcf
->cf_wrap
==1) start
= pcf
->cf_next
+ 1;
156 while(pcf
->cf_lock
==1) sched_yield();
160 iov
[iovcnt
].iov_base
= pbuffer
+ start
;
161 iov
[iovcnt
++].iov_len
= pcf
->cf_max
- start
;
164 iov
[iovcnt
].iov_base
= pbuffer
+ start
;
165 iov
[iovcnt
++].iov_len
= next
- start
;
166 if (writev(1,iov
,iovcnt
)==-1) {
167 fprintf(stderr
,"%s: ERROR: could not write output (%s)\n",pname
,strerror(errno
));
172 if (poll(&pfd
,1,50)==-1) {
173 fprintf(stderr
,"%s: ERROR: could not poll (%s)\n",pname
,strerror(errno
));
178 munmap(pbuffer
,sb
.st_size
);
186 init_log(const char *lname
, size_t size
)
190 char buffer
[BUFFER_SIZE
];
191 struct clog_footer cf
;
193 memcpy(&cf
.cf_magic
,MAGIC_CONST
,4);
194 cf
.cf_max
= size
- sizeof(struct clog_footer
);
196 memset(buffer
,0,BUFFER_SIZE
);
198 fd
= open(lname
,O_RDWR
|O_CREAT
,0666);
200 fprintf(stderr
,"%s: ERROR: could not open %s (%s)\n",pname
,lname
,strerror(errno
));
203 if (ftruncate(fd
,(off_t
)0)==-1) {
204 fprintf(stderr
,"%s: ERROR: could not truncate %s (%s)\n",pname
,lname
,strerror(errno
));
208 while(fill
>BUFFER_SIZE
) {
209 if (write(fd
,buffer
,BUFFER_SIZE
)==-1){
210 fprintf(stderr
,"%s: ERROR: could not write %s (%s)\n",pname
,lname
,strerror(errno
));
215 assert(fill
<=BUFFER_SIZE
);
217 if (write(fd
,buffer
,fill
)==-1) {
218 fprintf(stderr
,"%s: ERROR: could not write %s (%s)\n",pname
,lname
,strerror(errno
));
222 if (lseek(fd
,-(off_t
)(sizeof(struct clog_footer
)),SEEK_END
)==-1) {
223 fprintf(stderr
,"%s: ERROR: could not seek in %s (%s)\n",pname
,lname
,strerror(errno
));
226 if (write(fd
,&cf
,sizeof(cf
))==-1) {
227 fprintf(stderr
,"%s: ERROR: could not write magic in %s (%s)\n",pname
,lname
,strerror(errno
));