From: Michal Vaner Date: Wed, 10 Sep 2008 09:14:39 +0000 (+0200) Subject: Move ucw utils to subdirectory X-Git-Tag: holmes-import~314^2~1 X-Git-Url: http://mj.ucw.cz/gitweb/?a=commitdiff_plain;h=e52137cfe720e1d2ce9bcaa2ef76e174f5d1478d;p=libucw.git Move ucw utils to subdirectory --- diff --git a/ucw/Makefile b/ucw/Makefile index 0f2dc39e..36ab965c 100644 --- a/ucw/Makefile +++ b/ucw/Makefile @@ -4,9 +4,7 @@ DIRS+=ucw LIBUCW=$(o)/ucw/libucw.pc ifdef CONFIG_UCW_UTILS -UCW_UTILS=basecode b224 rotate-log urltool daemon-helper hex - -PROGS+=$(addprefix $(o)/ucw/,$(UCW_UTILS)) +include $(s)/ucw/utils/Makefile endif LIBUCW_MODS= \ @@ -93,7 +91,6 @@ $(o)/ucw/lizard-test: $(o)/ucw/lizard-test.o $(LIBUCW) $(o)/ucw/kmp-test: $(o)/ucw/kmp-test.o $(LIBUCW) $(LIBCHARSET) $(o)/ucw/ipaccess-test: $(o)/ucw/ipaccess-test.o $(LIBUCW) $(o)/ucw/trie-test: $(o)/ucw/trie-test.o $(LIBUCW) -$(o)/ucw/basecode: $(o)/ucw/basecode.o $(LIBUCW) TESTS+=$(addprefix $(o)/ucw/,regex.test unicode.test hash-test.test mempool.test stkstring.test \ slists.test kmp-test.test bbuf.test getopt.test ff-unicode.test eltpool.test \ @@ -144,13 +141,3 @@ endif ifdef CONFIG_UCW_SHELL_UTILS include $(s)/ucw/shell/Makefile endif - -ifdef CONFIG_UCW_UTILS -$(o)/ucw/b224: $(o)/ucw/b224.o $(LIBUCW) -$(o)/ucw/daemon-helper: $(o)/ucw/daemon-helper.o $(LIBUCW) -$(o)/ucw/urltool: $(o)/ucw/urltool.o $(LIBUCW) -$(o)/ucw/hex: $(o)/ucw/hex.o $(LIBUCW) - -TESTS+=$(o)/ucw/basecode.test -$(o)/ucw/basecode.test: $(o)/ucw/basecode -endif diff --git a/ucw/b224.c b/ucw/b224.c deleted file mode 100644 index 501bd143..00000000 --- a/ucw/b224.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * A Program For Manipulation With Base224 Encoded Files - * - * (c) 2002 Martin Mares - */ - -#include "ucw/lib.h" -#include "ucw/fastbuf.h" -#include "ucw/base224.h" - -#include - -int main(int argc, char **argv) -{ - struct fastbuf *in = bfdopen_shared(0, 4096); - struct fastbuf *out = bfdopen_shared(1, 4096); - byte ib[BASE224_IN_CHUNK*10], ob[BASE224_OUT_CHUNK*10], *b; - uns il, ol; - - if (argc != 2 || argv[1][0] != '-') - goto usage; - - switch (argv[1][1]) - { - case 'e': /* Plain encoding */ - while (il = bread(in, ib, sizeof(ib))) - { - ol = base224_encode(ob, ib, il); - bwrite(out, ob, ol); - } - break; - case 'E': /* Line block encoding */ - while (il = bread(in, ib, BASE224_IN_CHUNK*6)) - { - ol = base224_encode(ob, ib, il); - bputc(out, 'N'); - bwrite(out, ob, ol); - bputc(out, '\n'); - } - break; - case 'd': /* Plain decoding */ - while (ol = bread(in, ob, sizeof(ob))) - { - il = base224_decode(ib, ob, ol); - bwrite(out, ib, il); - } - break; - case 'D': /* Line block decoding */ - while (b = bgets(in, ob, sizeof(ob))) - { - if (!ob[0]) - die("Invalid line syntax"); - il = base224_decode(ib, ob+1, b-ob-1); - bwrite(out, ib, il); - } - break; - default: - usage: - fputs("Usage: b224 (-e|-E|-d|-D)\n", stderr); - return 1; - } - - bclose(in); - bclose(out); - return 0; -} diff --git a/ucw/basecode.c b/ucw/basecode.c deleted file mode 100644 index 892e883a..00000000 --- a/ucw/basecode.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * UCW Library -- Line utility for encoding and decoding base64 & base224 - * - * (c) 2008, Michal Vaner - * - * This software may be freely distributed and used according to the terms - * of the GNU Lesser General Public License. - */ - -#include -#include -#include - -#include "ucw/lib.h" -#include "ucw/base64.h" -#include "ucw/base224.h" -#include "ucw/fastbuf.h" -#include "ucw/getopt.h" - -static struct option opts[] = { - { "encode64", 0, 0, 'e' }, - { "decode64", 0, 0, 'd' }, - { "encode224", 0, 0, 'E' }, - { "decode224", 0, 0, 'D' }, - { "prefix", 1, 0, 'p' }, - { "blocks", 1, 0, 'b' }, - { 0, 0, 0, 0 } -}; - -static const struct { - uns (*function)(byte *, const byte *, uns); - uns in_block, out_block, num_blocks; - uns add_prefix; -} actions[] = { - { - base64_encode, - BASE64_IN_CHUNK, BASE64_OUT_CHUNK, 20, - 1 - }, - { - base64_decode, - BASE64_OUT_CHUNK, BASE64_IN_CHUNK, 20, - 0 - }, - { - base224_encode, - BASE224_IN_CHUNK, BASE64_OUT_CHUNK, 6, - 1 - }, - { - base224_decode, - BASE224_OUT_CHUNK, BASE224_IN_CHUNK, 6, - 0 - } -}; - -int main(int argc, char **argv) -{ - // Choose mode - int mode = -1; - char *prefix = NULL; - uns blocks = 0; - int opt; - while ((opt = getopt_long(argc, argv, "edEDp:b:", opts, NULL)) >= 0) - switch (opt) - { - case 'e': mode = 0; break; - case 'd': mode = 1; break; - case 'E': mode = 2; break; - case 'D': mode = 3; break; - case 'p': prefix = optarg; break; - case 'b': - { - char *end; - blocks = strtol(optarg, &end, 0); - if ((blocks > 0) && !*end) - break; - } - default: goto usage; - } - - if (mode == -1) - { - usage: - fprintf(stderr, "basecode mode [--prefix=prefix] [--blocks=number_of_blocks]\nMode is one of:\n\t--encode64 (-e)\n\t--decode64 (-d)\n\t--encode224 (-E)\n\t--decode224 (-D)\n"); - return 1; - } - if (!blocks) - blocks = actions[mode].num_blocks; - - // Prepare buffers - struct fastbuf *in = bfdopen_shared(0, 4096); - struct fastbuf *out = bfdopen_shared(1, 4096); - int has_offset = !actions[mode].add_prefix && prefix; - uns offset = has_offset ? strlen(prefix) : 0; - uns read_size = actions[mode].in_block * blocks + offset + has_offset; - uns write_size = actions[mode].out_block * blocks; - byte in_buff[read_size], out_buff[write_size]; - uns isize; - - // Recode it - while (isize = bread(in, in_buff, read_size)) - { - if (prefix) - { - if (actions[mode].add_prefix) - bputs(out, prefix); - else - if ((isize < offset) || (in_buff[isize-1] != '\n') - || (strncmp(prefix, in_buff, offset))) - die("Invalid line syntax"); - } - uns osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - has_offset); - bwrite(out, out_buff, osize); - if (actions[mode].add_prefix && prefix) - bputc(out, '\n'); - } - - bclose(in); - bclose(out); - return 0; -} diff --git a/ucw/daemon-helper.c b/ucw/daemon-helper.c deleted file mode 100644 index 6146aabb..00000000 --- a/ucw/daemon-helper.c +++ /dev/null @@ -1,185 +0,0 @@ -/* - * A Simple Wrapper for Starting and Stopping of Daemons - * - * (c) 2003 Martin Mares - * - * It would seem that we are reinventing the wheel and the - * start-stop-daemon command present in most Linux distributions - * is just what we need, but the usual "does the process already - * exist?" strategies fail in presence of multiple running daemons. - * - * Return codes: - * 101 already running - * 102 not running - */ - -#include "ucw/lib.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum action { - ACTION_NONE, - ACTION_START, - ACTION_STOP, - ACTION_FORCE_STOP, - ACTION_CHECK, - ACTION_RELOAD -}; - -static int action; - -static struct option options[] = { - { "pid-file", required_argument, NULL, 'p' }, - { "status-file", required_argument, NULL, 's' }, - { "start", no_argument, &action, ACTION_START }, - { "stop", no_argument, &action, ACTION_STOP }, - { "force-stop", no_argument, &action, ACTION_FORCE_STOP }, - { "check", no_argument, &action, ACTION_CHECK }, - { "reload", no_argument, &action, ACTION_RELOAD }, - { NULL, no_argument, NULL, 0 } -}; - -static void NONRET -usage(void) -{ - fputs("\n\ -Usage: daemon-helper --start -- \n\ - or: daemon-helper --stop \n\ - or: daemon-helper --force-stop \n\ - or: daemon-helper --reload \n\ - or: daemon-helper --check \n\ -\n\ -Options:\n\ ---pid-file Name of PID file for this daemon (mandatory)\n\ ---status-file Status file used by the daemon (deleted just before starting)\n\ -", stderr); - exit(1); -} - -int -main(int argc, char **argv) -{ - int c, fd; - char *pidfile = NULL; - char *statfile = NULL; - struct flock fl; - char buf[64]; - - while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) - switch (c) - { - case 0: - break; - case 'p': - pidfile = optarg; - break; - case 's': - statfile = optarg; - break; - default: - usage(); - } - if (!pidfile) - usage(); - - bzero(&fl, sizeof(fl)); - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - - switch (action) - { - case ACTION_START: - if (optind >= argc) - usage(); - fd = open(pidfile, O_RDWR | O_CREAT, 0666); - if (fd < 0) - die("Unable to create %s: %m", pidfile); - if ((c = fcntl(fd, F_SETLK, &fl)) < 0) - { - if (errno == EAGAIN || errno == EACCES) - return 101; - else - die("fcntl lock on %s failed: %m", pidfile); - } - c = sprintf(buf, "%d\n", getpid()); - if (write(fd, buf, c) != c) - die("write on %s failed: %m", pidfile); - if (ftruncate(fd, c) < 0) - die("truncate on %s failed: %m", pidfile); - if (statfile && unlink(statfile) < 0 && errno != ENOENT) - die("unlink(%s) failed: %m", statfile); - setsid(); - /* Disconnect from stdin and stdout, leave stderr to the daemon. */ - close(0); - open("/dev/null", O_RDWR, 0); - dup2(0, 1); - argv += optind; - argc -= optind; - char **a = alloca(sizeof(char *) * (argc+1)); - memcpy(a, argv, sizeof(char *) * argc); - a[argc] = NULL; - execv(a[0], a); - die("Cannot execute %s: %m", a[0]); - case ACTION_STOP: - case ACTION_FORCE_STOP: - case ACTION_CHECK: - case ACTION_RELOAD: - if (optind < argc) - usage(); - fd = open(pidfile, O_RDWR); - if (fd < 0) - { - if (errno == ENOENT) - return 102; - else - die("Unable to open %s: %m", pidfile); - } - if ((c = fcntl(fd, F_SETLK, &fl)) >= 0) - { - nopid: - unlink(pidfile); - return 102; - } - if (errno != EAGAIN && errno != EACCES) - die("fcntl lock on %s failed: %m", pidfile); - if ((c = read(fd, buf, sizeof(buf))) < 0) - die("read on %s failed: %m", pidfile); - if (!c) - goto nopid; - if (c >= (int) sizeof(buf) || sscanf(buf, "%d", &c) != 1) - die("PID file syntax error"); - int sig = 0; - if (action == ACTION_CHECK || action == ACTION_RELOAD) - { - if (action == ACTION_RELOAD) - sig = SIGHUP; - if (kill(c, sig) < 0 && errno == ESRCH) - goto nopid; - return 0; - } - sig = (action == ACTION_STOP) ? SIGTERM : SIGQUIT; - if (kill(c, sig) < 0) - { - if (errno == ESRCH) - goto nopid; - die("Cannot kill process %d: %m", c); - } - if ((c = fcntl(fd, F_SETLKW, &fl)) < 0) - die("Cannot lock %s: %m", pidfile); - if (statfile) - unlink(statfile); - if (unlink(pidfile) < 0) - die("Cannot unlink %s: %m", pidfile); - return 0; - default: - usage(); - } -} diff --git a/ucw/hex.c b/ucw/hex.c deleted file mode 100644 index 4ddb96ab..00000000 --- a/ucw/hex.c +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Hexadecimal dumper (CP/M style format) - * - * Original version (c) Eric S. Raymond - * Heavily modified by Martin Mares - * - * Can be freely distributed and used under the terms of the GNU GPL. - */ - -#include "ucw/lib.h" -#include "ucw/lfs.h" - -#include -#include -#include -#include -#include -#include - -#define DEFWIDTH 16 /* Default # chars to show per line */ -#define MAXWIDTH 32 /* Maximum # of bytes per line */ - -typedef int bool; -#define TRUE 1 -#define FALSE 0 - -static long linesize = DEFWIDTH; /* # of bytes to print per line */ -static bool cflag = FALSE; /* show printables as ASCII if true */ -static bool gflag = FALSE; /* suppress mid-page gutter if true */ -static ucw_off_t start = 0; /* file offset to start dumping at */ -static ucw_off_t length = 0; /* if nz, how many chars to dump */ - -static void dumpfile(FILE *f) - /* dump a single, specified file -- stdin if filename is NULL */ -{ - int ch = '\0'; /* current character */ - char ascii[MAXWIDTH+3]; /* printable ascii data */ - int i = 0; /* counter: # bytes processed */ - int ai = 0; /* index into ascii[] */ - ucw_off_t offset = start; /* byte offset of line in file */ - int hpos = 0; /* horizontal position counter */ - ucw_off_t fstart = start; - ucw_off_t flength = length; - char *specials = "\b\f\n\r\t"; - char *escapes = "bfnrt"; - char *cp; - - if (fstart && ucw_seek(fileno(f), fstart, SEEK_SET) >= 0) - fstart = 0; - - do { - ch = getc(f); - - if (ch != EOF) - { - if (length && flength-- <= 0) - ch = EOF; - } - - if (ch != EOF) - { - if (i++ % linesize == 0) - { - (void) printf("%04Lx ", (long long) offset); - offset += linesize; - hpos = 5; - } - - /* output one space for the mid-page gutter */ - if (!gflag) - if ((i - 1) % (linesize / 2) == 0) - { - (void) putchar(' '); - hpos++; - ascii[ai++] = ' '; - } - - /* dump the indicated representation of a character */ - ascii[ai] = (isprint (ch) || ch == ' ') ? ch : '.'; - - if (cflag && (isprint(ch) || ch == ' ')) - (void) printf("%c ", ch); - else if (cflag && ch && (cp = strchr(specials, ch))) - (void) printf("\\%c ", escapes[cp - specials]); - else - (void) printf("%02x ", ch); - - /* update counters and things */ - ai++; - hpos += 3; - } - - /* At end-of-line or EOF, show ASCII version of data. */ - if (i && (ch == EOF || (i % linesize == 0))) - { - if (!cflag) - { - while (hpos < linesize * 3 + 7) - { - hpos++; - (void) putchar(' '); - } - - ascii[ai] = '\0'; - (void) printf("%s", ascii); - } - - if (ch != EOF || (i % linesize != 0)) - (void) putchar('\n'); - ai = 0; /* reset counters */ - } - } while - (ch != EOF); -} - -static ucw_off_t getoffs(char *cp) - /* fetch decimal or hex integer to be used as file start or offset */ -{ - ucw_off_t value = 0; - char *hexdigits = "0123456789abcdefABCDEF"; - -#if 0 - bool foundzero = FALSE; - int base = 0; - - for (; *cp; cp++) - if (*cp == '0') - foundzero = TRUE; - else if (isdigit(*cp)) - { - base = 10; - break; - } - else if (*cp = 'x' || *cp == 'X' || *cp == 'h' || *cp == 'H') - { - base = 16; - cp++; - break; - } - else - return(-1L); - - if (base == 0) - if (foundzero) - base = 10; - else - return(-1L); - - if (base == 10) - { - for (; *cp; cp++) - if (isdigit(*cp)) - value = value * 10 + (*cp - '0'); - else - return(-1L); - } - else -#endif - { - for (; *cp; cp++) - if (strchr(hexdigits, *cp)) - value = value*16 + (strchr(hexdigits, tolower(*cp))-hexdigits); - else - return -1; - } - - return(value); -} - -int main(int argc, char **argv) -{ - FILE *infile; /* file pointer input file */ - int dumpcount = 0; /* count of files dumped so far */ - char *cp; - int fd; - - for (argv++, argc--; argc > 0; argv++, argc--) - { - char s = **argv; - - if (s == '-' || s == '+') - { - int c = *++*argv; - - switch (c) - { - case 'c': cflag = (s == '-'); continue; - case 'g': gflag = (s == '-'); continue; - - case 's': - if ((*argv)[1]) - (*argv)++; - else - argc--, argv++; - if (s == '-' && argc >= 0) - { - if (cp = strchr(*argv, ',')) - *cp++ = '\0'; - if ((start = getoffs(*argv)) < 0) - { - (void) fputs("hex: start offset no good\n", stderr); - exit(1); - } - - if (cp) - if ((length = getoffs(cp)) < 0) - { - (void) fputs("hex: length no good\n", stderr); - exit(1); - } - } - else - start = length = 0L; - continue; - - case '\0': - infile = stdin; - break; - - case 'w': - if ((*argv)[1]) - (*argv)++; - else - argc--, argv++; - if ((linesize = getoffs(*argv)) == -1L || linesize > MAXWIDTH) - { - (void) fputs("hex: line width no good\n", stderr); - exit(1); - } - if (linesize % 2) - gflag = TRUE; - continue; - - default: - (void) fprintf(stderr, "hex: no such option as %s\n", *argv); - exit(1); - } - } - else - { - fd = ucw_open(*argv, O_RDONLY, 0); - if (fd < 0 || !(infile = fdopen(fd, "r"))) - { - (void) fprintf(stderr, "hex: cannot open %s: %m\n", *argv); - exit(1); - } - } - - if (dumpcount > 0 || argc > 1) - if (infile == stdin) - (void) printf("---- ----\n"); - else - (void) printf("---- %s ----\n", *argv); - dumpfile(infile); - dumpcount++; - if (infile != stdin) - (void) fclose(infile); - } - - if (dumpcount == 0) - dumpfile(stdin); - return(0); -} diff --git a/ucw/rotate-log.pl b/ucw/rotate-log.pl deleted file mode 100644 index e4c9b109..00000000 --- a/ucw/rotate-log.pl +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/perl - -# Rotate Sherlock logs -# (c) 2001--2002 Martin Mares - -use File::stat; - -@ARGV >= 3 or die "Usage: rotate-log "; - -$now = time; -$cps = shift @ARGV; -$del = shift @ARGV; - -$compress_thr = $now - 86400 * $cps; -$delete_thr = $now - 86400 * $del; -foreach $f (@ARGV) { - -f $f or next; - $st = stat $f or next; - if ($del > 0 && $st->mtime < $delete_thr) { - print "Deleting $f\n"; - unlink $f || die "Delete FAILED: $!"; - } elsif ($cps > 0 && $st->mtime < $compress_thr && $f !~ /\.(gz|bz2)$/) { - print "Compressing $f\n"; - `gzip -f $f`; - $? && die "Compression FAILED: $!"; - } -} diff --git a/ucw/urltool.c b/ucw/urltool.c deleted file mode 100644 index 5bcb33ca..00000000 --- a/ucw/urltool.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Sherlock Utilities -- URL Handling Tool - * - * (c) 2004 Martin Mares - */ - -#include "ucw/lib.h" -#include "ucw/getopt.h" -#include "ucw/url.h" -#include "ucw/fastbuf.h" - -#include -#include -#include - -static byte *base_url; -static struct url base; -static uns opt_split = 0, opt_normalize = 0, opt_forgive = 0; -static struct fastbuf *fout; -static uns err_count; - -static void -process_url(byte *url) -{ - byte buf1[MAX_URL_SIZE], buf2[MAX_URL_SIZE], buf3[MAX_URL_SIZE], buf4[MAX_URL_SIZE]; - int e; - struct url ur; - - if ((e = url_deescape(url, buf1)) || (e = url_split(buf1, &ur, buf2))) - goto error; - if ((base_url || opt_normalize) && (e = url_normalize(&ur, &base))) - goto error; - if (opt_normalize && (e = url_canonicalize(&ur))) - goto error; - if (opt_split) - { - if (ur.protocol) - bprintf(fout, "protocol=%s\n", ur.protocol); - if (ur.user) - bprintf(fout, "user=%s\n", ur.user); - if (ur.pass) - bprintf(fout, "pass=%s\n", ur.pass); - if (ur.host) - bprintf(fout, "host=%s\n", ur.host); - if (ur.port != ~0U) - bprintf(fout, "port=%d\n", ur.port); - if (ur.rest) - bprintf(fout, "rest=%s\n", ur.rest); - bputc(fout, '\n'); - } - else - { - if ((e = url_pack(&ur, buf3)) || (e = url_enescape(buf3, buf4))) - goto error; - bprintf(fout, "%s\n", buf4); - } - return; - - error: - msg(L_ERROR, "%s: %s", url, url_error(e)); - err_count++; -} - -static char *shortopts = CF_SHORT_OPTS "b:fns"; -static struct option longopts[] = -{ - CF_LONG_OPTS - { "base", 1, 0, 'b' }, - { "forgive", 0, 0, 'f' }, - { "normalize", 0, 0, 'n' }, - { "split", 0, 0, 's' }, - { NULL, 0, 0, 0 } -}; - -static char *help = "\ -Usage: urltool [] []\n\ -\n\ -Options:\n" -CF_USAGE "\ --b, --base \tInput URL's are relative to this base\n\ --f, --forgive\t\tReturn exit status 0 even if there were errors\n\ -\n\ -Operations:\n\ --s, --split\t\tSplit a given URL to components\n\ --n, --normalize\t\tNormalize given URL\n\ -"; - -static void NONRET -usage(byte *msg) -{ - if (msg) - { - fputs(msg, stderr); - fputc('\n', stderr); - } - fputs(help, stderr); - exit(1); -} - -int -main(int argc, char **argv) -{ - int opt, err; - byte *base_url = NULL; - byte basebuf1[MAX_URL_SIZE], basebuf2[MAX_URL_SIZE]; - - log_init(argv[0]); - while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0) - switch (opt) - { - case 'b': - base_url = optarg; - err = url_canon_split(base_url, basebuf1, basebuf2, &base); - if (err) - die("Invalid base URL: %s", url_error(err)); - break; - case 's': - opt_split = 1; - break; - case 'n': - opt_normalize = 1; - break; - case 'f': - opt_forgive = 1; - break; - default: - usage("Invalid option"); - } - - fout = bfdopen_shared(1, 4096); - if (optind >= argc) - { - struct fastbuf *fin = bfdopen_shared(0, 4096); - byte url[MAX_URL_SIZE]; - while (bgets(fin, url, sizeof(url))) - process_url(url); - bclose(fin); - } - else - while (optind < argc) - process_url(argv[optind++]); - bclose(fout); - - return (err_count && !opt_forgive); -} diff --git a/ucw/utils/Makefile b/ucw/utils/Makefile new file mode 100644 index 00000000..e7892722 --- /dev/null +++ b/ucw/utils/Makefile @@ -0,0 +1,17 @@ +# Makefile for the UCW utilities (c) 2008 Michal Vaner + +PROGS+=$(addprefix $(o)/ucw/utils/,b224 basecode daemon-helper rotate-log urltool) +DIRS+=ucw/utils + +ifdef CONFIG_DEBUG +PROGS+=$(o)/ucw/utils/hex +endif + +$(o)/ucw/utils/b224: $(o)/ucw/utils/b224.o $(LIBUCW) +$(o)/ucw/utils/basecode: $(o)/ucw/utils/basecode.o $(LIBUCW) +$(o)/ucw/utils/daemon-helper: $(o)/ucw/utils/daemon-helper.o $(LIBUCW) +$(o)/ucw/utils/hex: $(o)/ucw/utils/hex.o $(LIBUCW) +$(o)/ucw/utils/urltool: $(o)/ucw/utils/urltool.o $(LIBUCW) + +TESTS+=$(o)/ucw/utils/basecode.test +$(o)/ucw/utils/basecode.test: $(o)/ucw/utils/basecode diff --git a/ucw/utils/b224.c b/ucw/utils/b224.c new file mode 100644 index 00000000..501bd143 --- /dev/null +++ b/ucw/utils/b224.c @@ -0,0 +1,66 @@ +/* + * A Program For Manipulation With Base224 Encoded Files + * + * (c) 2002 Martin Mares + */ + +#include "ucw/lib.h" +#include "ucw/fastbuf.h" +#include "ucw/base224.h" + +#include + +int main(int argc, char **argv) +{ + struct fastbuf *in = bfdopen_shared(0, 4096); + struct fastbuf *out = bfdopen_shared(1, 4096); + byte ib[BASE224_IN_CHUNK*10], ob[BASE224_OUT_CHUNK*10], *b; + uns il, ol; + + if (argc != 2 || argv[1][0] != '-') + goto usage; + + switch (argv[1][1]) + { + case 'e': /* Plain encoding */ + while (il = bread(in, ib, sizeof(ib))) + { + ol = base224_encode(ob, ib, il); + bwrite(out, ob, ol); + } + break; + case 'E': /* Line block encoding */ + while (il = bread(in, ib, BASE224_IN_CHUNK*6)) + { + ol = base224_encode(ob, ib, il); + bputc(out, 'N'); + bwrite(out, ob, ol); + bputc(out, '\n'); + } + break; + case 'd': /* Plain decoding */ + while (ol = bread(in, ob, sizeof(ob))) + { + il = base224_decode(ib, ob, ol); + bwrite(out, ib, il); + } + break; + case 'D': /* Line block decoding */ + while (b = bgets(in, ob, sizeof(ob))) + { + if (!ob[0]) + die("Invalid line syntax"); + il = base224_decode(ib, ob+1, b-ob-1); + bwrite(out, ib, il); + } + break; + default: + usage: + fputs("Usage: b224 (-e|-E|-d|-D)\n", stderr); + return 1; + } + + bclose(in); + bclose(out); + return 0; +} diff --git a/ucw/utils/basecode.c b/ucw/utils/basecode.c new file mode 100644 index 00000000..892e883a --- /dev/null +++ b/ucw/utils/basecode.c @@ -0,0 +1,122 @@ +/* + * UCW Library -- Line utility for encoding and decoding base64 & base224 + * + * (c) 2008, Michal Vaner + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + */ + +#include +#include +#include + +#include "ucw/lib.h" +#include "ucw/base64.h" +#include "ucw/base224.h" +#include "ucw/fastbuf.h" +#include "ucw/getopt.h" + +static struct option opts[] = { + { "encode64", 0, 0, 'e' }, + { "decode64", 0, 0, 'd' }, + { "encode224", 0, 0, 'E' }, + { "decode224", 0, 0, 'D' }, + { "prefix", 1, 0, 'p' }, + { "blocks", 1, 0, 'b' }, + { 0, 0, 0, 0 } +}; + +static const struct { + uns (*function)(byte *, const byte *, uns); + uns in_block, out_block, num_blocks; + uns add_prefix; +} actions[] = { + { + base64_encode, + BASE64_IN_CHUNK, BASE64_OUT_CHUNK, 20, + 1 + }, + { + base64_decode, + BASE64_OUT_CHUNK, BASE64_IN_CHUNK, 20, + 0 + }, + { + base224_encode, + BASE224_IN_CHUNK, BASE64_OUT_CHUNK, 6, + 1 + }, + { + base224_decode, + BASE224_OUT_CHUNK, BASE224_IN_CHUNK, 6, + 0 + } +}; + +int main(int argc, char **argv) +{ + // Choose mode + int mode = -1; + char *prefix = NULL; + uns blocks = 0; + int opt; + while ((opt = getopt_long(argc, argv, "edEDp:b:", opts, NULL)) >= 0) + switch (opt) + { + case 'e': mode = 0; break; + case 'd': mode = 1; break; + case 'E': mode = 2; break; + case 'D': mode = 3; break; + case 'p': prefix = optarg; break; + case 'b': + { + char *end; + blocks = strtol(optarg, &end, 0); + if ((blocks > 0) && !*end) + break; + } + default: goto usage; + } + + if (mode == -1) + { + usage: + fprintf(stderr, "basecode mode [--prefix=prefix] [--blocks=number_of_blocks]\nMode is one of:\n\t--encode64 (-e)\n\t--decode64 (-d)\n\t--encode224 (-E)\n\t--decode224 (-D)\n"); + return 1; + } + if (!blocks) + blocks = actions[mode].num_blocks; + + // Prepare buffers + struct fastbuf *in = bfdopen_shared(0, 4096); + struct fastbuf *out = bfdopen_shared(1, 4096); + int has_offset = !actions[mode].add_prefix && prefix; + uns offset = has_offset ? strlen(prefix) : 0; + uns read_size = actions[mode].in_block * blocks + offset + has_offset; + uns write_size = actions[mode].out_block * blocks; + byte in_buff[read_size], out_buff[write_size]; + uns isize; + + // Recode it + while (isize = bread(in, in_buff, read_size)) + { + if (prefix) + { + if (actions[mode].add_prefix) + bputs(out, prefix); + else + if ((isize < offset) || (in_buff[isize-1] != '\n') + || (strncmp(prefix, in_buff, offset))) + die("Invalid line syntax"); + } + uns osize = actions[mode].function(out_buff, in_buff + offset, isize - offset - has_offset); + bwrite(out, out_buff, osize); + if (actions[mode].add_prefix && prefix) + bputc(out, '\n'); + } + + bclose(in); + bclose(out); + return 0; +} diff --git a/ucw/utils/daemon-helper.c b/ucw/utils/daemon-helper.c new file mode 100644 index 00000000..6146aabb --- /dev/null +++ b/ucw/utils/daemon-helper.c @@ -0,0 +1,185 @@ +/* + * A Simple Wrapper for Starting and Stopping of Daemons + * + * (c) 2003 Martin Mares + * + * It would seem that we are reinventing the wheel and the + * start-stop-daemon command present in most Linux distributions + * is just what we need, but the usual "does the process already + * exist?" strategies fail in presence of multiple running daemons. + * + * Return codes: + * 101 already running + * 102 not running + */ + +#include "ucw/lib.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +enum action { + ACTION_NONE, + ACTION_START, + ACTION_STOP, + ACTION_FORCE_STOP, + ACTION_CHECK, + ACTION_RELOAD +}; + +static int action; + +static struct option options[] = { + { "pid-file", required_argument, NULL, 'p' }, + { "status-file", required_argument, NULL, 's' }, + { "start", no_argument, &action, ACTION_START }, + { "stop", no_argument, &action, ACTION_STOP }, + { "force-stop", no_argument, &action, ACTION_FORCE_STOP }, + { "check", no_argument, &action, ACTION_CHECK }, + { "reload", no_argument, &action, ACTION_RELOAD }, + { NULL, no_argument, NULL, 0 } +}; + +static void NONRET +usage(void) +{ + fputs("\n\ +Usage: daemon-helper --start -- \n\ + or: daemon-helper --stop \n\ + or: daemon-helper --force-stop \n\ + or: daemon-helper --reload \n\ + or: daemon-helper --check \n\ +\n\ +Options:\n\ +--pid-file Name of PID file for this daemon (mandatory)\n\ +--status-file Status file used by the daemon (deleted just before starting)\n\ +", stderr); + exit(1); +} + +int +main(int argc, char **argv) +{ + int c, fd; + char *pidfile = NULL; + char *statfile = NULL; + struct flock fl; + char buf[64]; + + while ((c = getopt_long(argc, argv, "", options, NULL)) >= 0) + switch (c) + { + case 0: + break; + case 'p': + pidfile = optarg; + break; + case 's': + statfile = optarg; + break; + default: + usage(); + } + if (!pidfile) + usage(); + + bzero(&fl, sizeof(fl)); + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + + switch (action) + { + case ACTION_START: + if (optind >= argc) + usage(); + fd = open(pidfile, O_RDWR | O_CREAT, 0666); + if (fd < 0) + die("Unable to create %s: %m", pidfile); + if ((c = fcntl(fd, F_SETLK, &fl)) < 0) + { + if (errno == EAGAIN || errno == EACCES) + return 101; + else + die("fcntl lock on %s failed: %m", pidfile); + } + c = sprintf(buf, "%d\n", getpid()); + if (write(fd, buf, c) != c) + die("write on %s failed: %m", pidfile); + if (ftruncate(fd, c) < 0) + die("truncate on %s failed: %m", pidfile); + if (statfile && unlink(statfile) < 0 && errno != ENOENT) + die("unlink(%s) failed: %m", statfile); + setsid(); + /* Disconnect from stdin and stdout, leave stderr to the daemon. */ + close(0); + open("/dev/null", O_RDWR, 0); + dup2(0, 1); + argv += optind; + argc -= optind; + char **a = alloca(sizeof(char *) * (argc+1)); + memcpy(a, argv, sizeof(char *) * argc); + a[argc] = NULL; + execv(a[0], a); + die("Cannot execute %s: %m", a[0]); + case ACTION_STOP: + case ACTION_FORCE_STOP: + case ACTION_CHECK: + case ACTION_RELOAD: + if (optind < argc) + usage(); + fd = open(pidfile, O_RDWR); + if (fd < 0) + { + if (errno == ENOENT) + return 102; + else + die("Unable to open %s: %m", pidfile); + } + if ((c = fcntl(fd, F_SETLK, &fl)) >= 0) + { + nopid: + unlink(pidfile); + return 102; + } + if (errno != EAGAIN && errno != EACCES) + die("fcntl lock on %s failed: %m", pidfile); + if ((c = read(fd, buf, sizeof(buf))) < 0) + die("read on %s failed: %m", pidfile); + if (!c) + goto nopid; + if (c >= (int) sizeof(buf) || sscanf(buf, "%d", &c) != 1) + die("PID file syntax error"); + int sig = 0; + if (action == ACTION_CHECK || action == ACTION_RELOAD) + { + if (action == ACTION_RELOAD) + sig = SIGHUP; + if (kill(c, sig) < 0 && errno == ESRCH) + goto nopid; + return 0; + } + sig = (action == ACTION_STOP) ? SIGTERM : SIGQUIT; + if (kill(c, sig) < 0) + { + if (errno == ESRCH) + goto nopid; + die("Cannot kill process %d: %m", c); + } + if ((c = fcntl(fd, F_SETLKW, &fl)) < 0) + die("Cannot lock %s: %m", pidfile); + if (statfile) + unlink(statfile); + if (unlink(pidfile) < 0) + die("Cannot unlink %s: %m", pidfile); + return 0; + default: + usage(); + } +} diff --git a/ucw/utils/hex.c b/ucw/utils/hex.c new file mode 100644 index 00000000..4ddb96ab --- /dev/null +++ b/ucw/utils/hex.c @@ -0,0 +1,263 @@ +/* + * Hexadecimal dumper (CP/M style format) + * + * Original version (c) Eric S. Raymond + * Heavily modified by Martin Mares + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include "ucw/lib.h" +#include "ucw/lfs.h" + +#include +#include +#include +#include +#include +#include + +#define DEFWIDTH 16 /* Default # chars to show per line */ +#define MAXWIDTH 32 /* Maximum # of bytes per line */ + +typedef int bool; +#define TRUE 1 +#define FALSE 0 + +static long linesize = DEFWIDTH; /* # of bytes to print per line */ +static bool cflag = FALSE; /* show printables as ASCII if true */ +static bool gflag = FALSE; /* suppress mid-page gutter if true */ +static ucw_off_t start = 0; /* file offset to start dumping at */ +static ucw_off_t length = 0; /* if nz, how many chars to dump */ + +static void dumpfile(FILE *f) + /* dump a single, specified file -- stdin if filename is NULL */ +{ + int ch = '\0'; /* current character */ + char ascii[MAXWIDTH+3]; /* printable ascii data */ + int i = 0; /* counter: # bytes processed */ + int ai = 0; /* index into ascii[] */ + ucw_off_t offset = start; /* byte offset of line in file */ + int hpos = 0; /* horizontal position counter */ + ucw_off_t fstart = start; + ucw_off_t flength = length; + char *specials = "\b\f\n\r\t"; + char *escapes = "bfnrt"; + char *cp; + + if (fstart && ucw_seek(fileno(f), fstart, SEEK_SET) >= 0) + fstart = 0; + + do { + ch = getc(f); + + if (ch != EOF) + { + if (length && flength-- <= 0) + ch = EOF; + } + + if (ch != EOF) + { + if (i++ % linesize == 0) + { + (void) printf("%04Lx ", (long long) offset); + offset += linesize; + hpos = 5; + } + + /* output one space for the mid-page gutter */ + if (!gflag) + if ((i - 1) % (linesize / 2) == 0) + { + (void) putchar(' '); + hpos++; + ascii[ai++] = ' '; + } + + /* dump the indicated representation of a character */ + ascii[ai] = (isprint (ch) || ch == ' ') ? ch : '.'; + + if (cflag && (isprint(ch) || ch == ' ')) + (void) printf("%c ", ch); + else if (cflag && ch && (cp = strchr(specials, ch))) + (void) printf("\\%c ", escapes[cp - specials]); + else + (void) printf("%02x ", ch); + + /* update counters and things */ + ai++; + hpos += 3; + } + + /* At end-of-line or EOF, show ASCII version of data. */ + if (i && (ch == EOF || (i % linesize == 0))) + { + if (!cflag) + { + while (hpos < linesize * 3 + 7) + { + hpos++; + (void) putchar(' '); + } + + ascii[ai] = '\0'; + (void) printf("%s", ascii); + } + + if (ch != EOF || (i % linesize != 0)) + (void) putchar('\n'); + ai = 0; /* reset counters */ + } + } while + (ch != EOF); +} + +static ucw_off_t getoffs(char *cp) + /* fetch decimal or hex integer to be used as file start or offset */ +{ + ucw_off_t value = 0; + char *hexdigits = "0123456789abcdefABCDEF"; + +#if 0 + bool foundzero = FALSE; + int base = 0; + + for (; *cp; cp++) + if (*cp == '0') + foundzero = TRUE; + else if (isdigit(*cp)) + { + base = 10; + break; + } + else if (*cp = 'x' || *cp == 'X' || *cp == 'h' || *cp == 'H') + { + base = 16; + cp++; + break; + } + else + return(-1L); + + if (base == 0) + if (foundzero) + base = 10; + else + return(-1L); + + if (base == 10) + { + for (; *cp; cp++) + if (isdigit(*cp)) + value = value * 10 + (*cp - '0'); + else + return(-1L); + } + else +#endif + { + for (; *cp; cp++) + if (strchr(hexdigits, *cp)) + value = value*16 + (strchr(hexdigits, tolower(*cp))-hexdigits); + else + return -1; + } + + return(value); +} + +int main(int argc, char **argv) +{ + FILE *infile; /* file pointer input file */ + int dumpcount = 0; /* count of files dumped so far */ + char *cp; + int fd; + + for (argv++, argc--; argc > 0; argv++, argc--) + { + char s = **argv; + + if (s == '-' || s == '+') + { + int c = *++*argv; + + switch (c) + { + case 'c': cflag = (s == '-'); continue; + case 'g': gflag = (s == '-'); continue; + + case 's': + if ((*argv)[1]) + (*argv)++; + else + argc--, argv++; + if (s == '-' && argc >= 0) + { + if (cp = strchr(*argv, ',')) + *cp++ = '\0'; + if ((start = getoffs(*argv)) < 0) + { + (void) fputs("hex: start offset no good\n", stderr); + exit(1); + } + + if (cp) + if ((length = getoffs(cp)) < 0) + { + (void) fputs("hex: length no good\n", stderr); + exit(1); + } + } + else + start = length = 0L; + continue; + + case '\0': + infile = stdin; + break; + + case 'w': + if ((*argv)[1]) + (*argv)++; + else + argc--, argv++; + if ((linesize = getoffs(*argv)) == -1L || linesize > MAXWIDTH) + { + (void) fputs("hex: line width no good\n", stderr); + exit(1); + } + if (linesize % 2) + gflag = TRUE; + continue; + + default: + (void) fprintf(stderr, "hex: no such option as %s\n", *argv); + exit(1); + } + } + else + { + fd = ucw_open(*argv, O_RDONLY, 0); + if (fd < 0 || !(infile = fdopen(fd, "r"))) + { + (void) fprintf(stderr, "hex: cannot open %s: %m\n", *argv); + exit(1); + } + } + + if (dumpcount > 0 || argc > 1) + if (infile == stdin) + (void) printf("---- ----\n"); + else + (void) printf("---- %s ----\n", *argv); + dumpfile(infile); + dumpcount++; + if (infile != stdin) + (void) fclose(infile); + } + + if (dumpcount == 0) + dumpfile(stdin); + return(0); +} diff --git a/ucw/utils/rotate-log.pl b/ucw/utils/rotate-log.pl new file mode 100644 index 00000000..e4c9b109 --- /dev/null +++ b/ucw/utils/rotate-log.pl @@ -0,0 +1,27 @@ +#!/usr/bin/perl + +# Rotate Sherlock logs +# (c) 2001--2002 Martin Mares + +use File::stat; + +@ARGV >= 3 or die "Usage: rotate-log "; + +$now = time; +$cps = shift @ARGV; +$del = shift @ARGV; + +$compress_thr = $now - 86400 * $cps; +$delete_thr = $now - 86400 * $del; +foreach $f (@ARGV) { + -f $f or next; + $st = stat $f or next; + if ($del > 0 && $st->mtime < $delete_thr) { + print "Deleting $f\n"; + unlink $f || die "Delete FAILED: $!"; + } elsif ($cps > 0 && $st->mtime < $compress_thr && $f !~ /\.(gz|bz2)$/) { + print "Compressing $f\n"; + `gzip -f $f`; + $? && die "Compression FAILED: $!"; + } +} diff --git a/ucw/utils/urltool.c b/ucw/utils/urltool.c new file mode 100644 index 00000000..5bcb33ca --- /dev/null +++ b/ucw/utils/urltool.c @@ -0,0 +1,145 @@ +/* + * Sherlock Utilities -- URL Handling Tool + * + * (c) 2004 Martin Mares + */ + +#include "ucw/lib.h" +#include "ucw/getopt.h" +#include "ucw/url.h" +#include "ucw/fastbuf.h" + +#include +#include +#include + +static byte *base_url; +static struct url base; +static uns opt_split = 0, opt_normalize = 0, opt_forgive = 0; +static struct fastbuf *fout; +static uns err_count; + +static void +process_url(byte *url) +{ + byte buf1[MAX_URL_SIZE], buf2[MAX_URL_SIZE], buf3[MAX_URL_SIZE], buf4[MAX_URL_SIZE]; + int e; + struct url ur; + + if ((e = url_deescape(url, buf1)) || (e = url_split(buf1, &ur, buf2))) + goto error; + if ((base_url || opt_normalize) && (e = url_normalize(&ur, &base))) + goto error; + if (opt_normalize && (e = url_canonicalize(&ur))) + goto error; + if (opt_split) + { + if (ur.protocol) + bprintf(fout, "protocol=%s\n", ur.protocol); + if (ur.user) + bprintf(fout, "user=%s\n", ur.user); + if (ur.pass) + bprintf(fout, "pass=%s\n", ur.pass); + if (ur.host) + bprintf(fout, "host=%s\n", ur.host); + if (ur.port != ~0U) + bprintf(fout, "port=%d\n", ur.port); + if (ur.rest) + bprintf(fout, "rest=%s\n", ur.rest); + bputc(fout, '\n'); + } + else + { + if ((e = url_pack(&ur, buf3)) || (e = url_enescape(buf3, buf4))) + goto error; + bprintf(fout, "%s\n", buf4); + } + return; + + error: + msg(L_ERROR, "%s: %s", url, url_error(e)); + err_count++; +} + +static char *shortopts = CF_SHORT_OPTS "b:fns"; +static struct option longopts[] = +{ + CF_LONG_OPTS + { "base", 1, 0, 'b' }, + { "forgive", 0, 0, 'f' }, + { "normalize", 0, 0, 'n' }, + { "split", 0, 0, 's' }, + { NULL, 0, 0, 0 } +}; + +static char *help = "\ +Usage: urltool [] []\n\ +\n\ +Options:\n" +CF_USAGE "\ +-b, --base \tInput URL's are relative to this base\n\ +-f, --forgive\t\tReturn exit status 0 even if there were errors\n\ +\n\ +Operations:\n\ +-s, --split\t\tSplit a given URL to components\n\ +-n, --normalize\t\tNormalize given URL\n\ +"; + +static void NONRET +usage(byte *msg) +{ + if (msg) + { + fputs(msg, stderr); + fputc('\n', stderr); + } + fputs(help, stderr); + exit(1); +} + +int +main(int argc, char **argv) +{ + int opt, err; + byte *base_url = NULL; + byte basebuf1[MAX_URL_SIZE], basebuf2[MAX_URL_SIZE]; + + log_init(argv[0]); + while ((opt = cf_getopt(argc, argv, shortopts, longopts, NULL)) >= 0) + switch (opt) + { + case 'b': + base_url = optarg; + err = url_canon_split(base_url, basebuf1, basebuf2, &base); + if (err) + die("Invalid base URL: %s", url_error(err)); + break; + case 's': + opt_split = 1; + break; + case 'n': + opt_normalize = 1; + break; + case 'f': + opt_forgive = 1; + break; + default: + usage("Invalid option"); + } + + fout = bfdopen_shared(1, 4096); + if (optind >= argc) + { + struct fastbuf *fin = bfdopen_shared(0, 4096); + byte url[MAX_URL_SIZE]; + while (bgets(fin, url, sizeof(url))) + process_url(url); + bclose(fin); + } + else + while (optind < argc) + process_url(argv[optind++]); + bclose(fout); + + return (err_count && !opt_forgive); +}