rats

RAdix iniT Suite
git clone https://git.daat.foo/repos/rats.git
Log | Files | Refs | README | LICENSE

slog.c (2290B)


      1 /* slog: simple logging daemon */
      2 
      3 #ifndef _GNU_SOURCE
      4 #define _GNU_SOURCE /* needed for PATH_MAX, to, and from */
      5 #endif
      6 
      7 #include "arg.h"
      8 #include "util.h"
      9 
     10 #include <errno.h>
     11 #include <fcntl.h>
     12 #include <limits.h>
     13 #include <stdio.h>
     14 #include <stdlib.h>
     15 #include <string.h>
     16 #include <sys/stat.h>
     17 #include <unistd.h>
     18 
     19 static void
     20 usage(void)
     21 {
     22 	eprintf("usage: %s [-d dir] [-s bytes] [-n count]\n", argv0);
     23 }
     24 
     25 static void
     26 mkdir_p(const char *path)
     27 {
     28 	char tmp[PATH_MAX];
     29 	char *p;
     30 	size_t len;
     31 
     32 	strlcpy(tmp, path, sizeof(tmp));
     33 	len = strlen(tmp);
     34 	if (len > 0 && tmp[len - 1] == '/')
     35 		tmp[len - 1] = '\0';
     36 
     37 	for (p = tmp + 1; *p; p++) {
     38 		if (*p == '/') {
     39 			*p = '\0';
     40 			if (mkdir(tmp, 0755) < 0 && errno != EEXIST)
     41 				eprintf("mkdir %s:", tmp);
     42 			*p = '/';
     43 		}
     44 	}
     45 	if (mkdir(tmp, 0755) < 0 && errno != EEXIST)
     46 		eprintf("mkdir %s:", tmp);
     47 }
     48 
     49 int
     50 main(int argc, char *argv[])
     51 {
     52 	char *dir;
     53 	char cur[PATH_MAX], from[PATH_MAX], to[PATH_MAX];
     54 	long maxsize, maxfiles;
     55 	int fd, i, n;
     56 	size_t total;
     57 	char buf[4096];
     58 
     59 	dir = ".";
     60 	maxsize = 1048576;
     61 	maxfiles = 10;
     62 
     63 	ARGBEGIN {
     64 	case 'd': dir = EARGF(usage()); break;
     65 	case 's': maxsize = estrtonum(EARGF(usage()), 1, LONG_MAX); break;
     66 	case 'n': maxfiles = estrtonum(EARGF(usage()), 1, 1000); break;
     67 	default:  usage();
     68 	} ARGEND
     69 
     70 	if (argc)
     71 		usage();
     72 
     73 	mkdir_p(dir);
     74 
     75 	snprintf(cur, sizeof(cur), "%s/current", dir);
     76 	fd = open(cur, O_WRONLY | O_CREAT | O_APPEND, 0644);
     77 	if (fd < 0)
     78 		eprintf("open %s:", cur);
     79 
     80 	total = 0;
     81 	while ((n = read(STDIN_FILENO, buf, sizeof(buf))) > 0) {
     82 		if (writeall(fd, buf, n) < 0)
     83 			eprintf("write %s:", cur);
     84 		total += n;
     85 		if (total < (size_t)maxsize)
     86 			continue;
     87 
     88 		/* rotate: delete oldest, shift others, current -> 0 */
     89 		close(fd);
     90 		snprintf(to, sizeof(to), "%s/%ld", dir, maxfiles - 1);
     91 		unlink(to);
     92 		for (i = maxfiles - 2; i >= 0; i--) {
     93 			snprintf(from, sizeof(from), "%s/%d", dir, i);
     94 			snprintf(to, sizeof(to), "%s/%d", dir, i + 1);
     95 			if (rename(from, to) < 0 && errno != ENOENT)
     96 				weprintf("rename %s -> %s:", from, to);
     97 		}
     98 		snprintf(to, sizeof(to), "%s/0", dir);
     99 		if (rename(cur, to) < 0)
    100 			weprintf("rename %s -> %s:", cur, to);
    101 
    102 		fd = open(cur, O_WRONLY | O_CREAT | O_APPEND, 0644);
    103 		if (fd < 0)
    104 			eprintf("open %s:", cur);
    105 		total = 0;
    106 	}
    107 
    108 	close(fd);
    109 	return 0;
    110 }