#include "global.h"
#include "clog.h"
int Verbose;
extern char compiled[], compiledby[], compilehost[];
static void
Usage()
{
printf( "cLOG is tool for managment syslogd operation with circular logs\n"
"=== %s === %s@%s ===\n\n"
" Syntax: clog [options] <file.log>\n\n"
"\t-v\t\tVerbose, more -vv more verbosity\n"
"\t-i\t\tInit file.log, create and prepare for use\n"
"\t-s <size>\tUse with init for set needed file.log size\n"
"\t-m <perm>\tUse permissions with init for set file.log\n"
"\t-f\t\tRead and follow log file.log\n"
"\n", compiled, compiledby, compilehost);
}
static int
initlog(const char *csLog, size_t size, int mode)
{
int f, ret = -1, fill = size;
struct clogFooter cf = { 0 };
char buffer[BUFLEN] = { 0 };
memcpy(&cf.cf_magic, MAGIC, sizeof cf.cf_magic);
cf.cf_max = size - sizeof cf;
f = open(csLog, O_WRONLY | O_CREAT | O_TRUNC, mode);
if (f == -1) {
printf("Error:: in open log %s #%d - %s\n", csLog, errno, strerror(errno));
return -1;
} else
VERB(1) printf("Verbose:: Create log %s\n", csLog);
while (fill > BUFLEN)
if (write(f, buffer, BUFLEN) == -1) {
printf("Error:: in fill log %s #%d - %s\n", csLog, errno, strerror(errno));
goto end;
} else
fill -= BUFLEN;
if (fill > BUFLEN) {
printf("Error:: in fill log %s uninspected result!!!\n", csLog);
goto end;
} else if (fill && write(f, buffer, fill) == -1) {
printf("Error:: in last fill log %s #%d - %s\n", csLog, errno, strerror(errno));
goto end;
}
// return to write cfooter
if (lseek(f, -(off_t)(sizeof cf), SEEK_END) == -1) {
printf("Error:: can`t set position for write footer #%d - %s\n", errno, strerror(errno));
goto end;
}
if (write(f, &cf, sizeof cf) == -1) {
printf("Error:: in footer log %s #%d - %s\n", csLog, errno, strerror(errno));
goto end;
}
ret = 0;
VERB(1) printf("Verbose:: Init done.\n");
end:
close(f);
return ret;
}
static int
readlog(const char *csLog, char m)
{
int f, cx;
size_t end;
struct clogFooter *cf;
char *buffer = NULL;
uint32_t next, start = 0;
struct iovec iov[2];
struct pollfd pfd = { 0 };
f = open(csLog, O_RDONLY);
if (f == -1) {
printf("Error:: in open read %s #%d - %s\n", csLog, errno, strerror(errno));
return -1;
} else
VERB(1) printf("Verbose:: Opened log %s\n", csLog);
end = lseek(f, 0, SEEK_END);
if (end == -1) {
printf("Error:: in get size %s #%d - %s\n", csLog, errno, strerror(errno));
close(f);
return -1;
} else
lseek(f, 0, SEEK_SET);
VERB(2) printf("Verbose(2):: Get file size %lu\n", (u_long) end);
buffer = mmap(NULL, end, PROT_READ, MAP_SHARED, f, 0);
if (!buffer) {
printf("Error:: in map %s #%d - %s\n", csLog, errno, strerror(errno));
close(f);
return -1;
} else {
close(f);
cf = (struct clogFooter*) (buffer + end - sizeof(struct clogFooter));
VERB(3) printf("Verbose(3):: Map file to address %p and footer %p\n", buffer, cf);
}
if (cf->cf_wrap == 1)
start = cf->cf_next + 1;
VERB(3) printf("Verbose(3):: wrapped log? %d\n", cf->cf_wrap);
do {
cx = 0;
while (cf->cf_lock == 1)
sched_yield();
next = cf->cf_next;
if (start > next) {
iov[cx].iov_base = buffer + start;
iov[cx++].iov_len = cf->cf_max - start;
start = 0;
}
iov[cx].iov_base = buffer + start;
iov[cx++].iov_len = next - start;
start = next;
writev(1, iov, cx);
if (!(m & 2))
break;
if (poll(&pfd, 1, 50) == -1) {
printf("Error:: in poll %s #%d - %s\n", csLog, errno, strerror(errno));
munmap(buffer, end);
return -1;
}
} while (42);
munmap(buffer, end);
VERB(1) printf("Verbose:: Read done.\n");
return 0;
}
int
main(int argc, char **argv)
{
char ch, m = 0, szLog[MAXPATHLEN];
size_t siz = 0;
int mode = 0644;
while ((ch = getopt(argc, argv, "hm:vfis:")) != -1)
switch (ch) {
case 'm':
mode = strtol(optarg, NULL, 0);
break;
case 'v':
Verbose++;
break;
case 'i':
m |= 1;
break;
case 'f':
m |= 2;
break;
case 's':
siz = strtol(optarg, NULL, 0);
if (siz < 1) {
printf("Error:: size is invalid %lu!\n", (u_long) siz);
Usage();
return 1;
}
break;
case 'h':
default:
Usage();
return 1;
}
argc -= optind;
argv += optind;
if (m & 1 && !siz) {
printf("Error:: not specified size when use with init log!\n");
Usage();
return 1;
}
if (m == 3) {
printf("Error:: can`t in same time init and force!\n");
Usage();
return 1;
}
if (!argc) {
printf("Error:: not specified log file!\n");
Usage();
return 1;
} else
strlcpy(szLog, *argv, MAXPATHLEN);
if (m & 1 && initlog(szLog, siz, mode) == -1)
return 2;
if (readlog(szLog, m) == -1)
return 3;
return 0;
}
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>