]> mj.ucw.cz Git - libucw.git/commitdiff
Move ucw utils to subdirectory
authorMichal Vaner <vorner@ucw.cz>
Wed, 10 Sep 2008 09:14:39 +0000 (11:14 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 10 Sep 2008 19:14:00 +0000 (21:14 +0200)
14 files changed:
ucw/Makefile
ucw/b224.c [deleted file]
ucw/basecode.c [deleted file]
ucw/daemon-helper.c [deleted file]
ucw/hex.c [deleted file]
ucw/rotate-log.pl [deleted file]
ucw/urltool.c [deleted file]
ucw/utils/Makefile [new file with mode: 0644]
ucw/utils/b224.c [new file with mode: 0644]
ucw/utils/basecode.c [new file with mode: 0644]
ucw/utils/daemon-helper.c [new file with mode: 0644]
ucw/utils/hex.c [new file with mode: 0644]
ucw/utils/rotate-log.pl [new file with mode: 0644]
ucw/utils/urltool.c [new file with mode: 0644]

index 0f2dc39eace705474d9c2a7babe9c22e72ec4ff3..36ab965c4d858d16ede949e484a8f4ac8bb077d1 100644 (file)
@@ -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 (file)
index 501bd14..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- *     A Program For Manipulation With Base224 Encoded Files
- *
- *     (c) 2002 Martin Mares <mj@ucw.cz>
- */
-
-#include "ucw/lib.h"
-#include "ucw/fastbuf.h"
-#include "ucw/base224.h"
-
-#include <stdio.h>
-
-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 (file)
index 892e883..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- *     UCW Library -- Line utility for encoding and decoding base64 & base224
- *
- *     (c) 2008, Michal Vaner <vorner@ucw.cz>
- *
- *     This software may be freely distributed and used according to the terms
- *     of the GNU Lesser General Public License.
- */
-
-#include <string.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#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 (file)
index 6146aab..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- *     A Simple Wrapper for Starting and Stopping of Daemons
- *
- *     (c) 2003 Martin Mares <mj@ucw.cz>
- *
- *     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 <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <signal.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <getopt.h>
-#include <errno.h>
-#include <alloca.h>
-
-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 <options> -- <daemon> <args>\n\
-   or: daemon-helper --stop <options>\n\
-   or: daemon-helper --force-stop <options>\n\
-   or: daemon-helper --reload <options>\n\
-   or: daemon-helper --check <options>\n\
-\n\
-Options:\n\
---pid-file <name>      Name of PID file for this daemon (mandatory)\n\
---status-file <name>   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 (file)
index 4ddb96a..0000000
--- a/ucw/hex.c
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- *  Hexadecimal dumper (CP/M style format)
- *
- *  Original version (c) Eric S. Raymond <esr@snark.thyrsus.com>
- *  Heavily modified by Martin Mares <mj@ucw.cz>
- *
- *  Can be freely distributed and used under the terms of the GNU GPL.
- */
-
-#include "ucw/lib.h"
-#include "ucw/lfs.h"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-#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("---- <Standard input> ----\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 (file)
index e4c9b10..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/usr/bin/perl
-
-#      Rotate Sherlock logs
-#      (c) 2001--2002 Martin Mares <mj@ucw.cz>
-
-use File::stat;
-
-@ARGV >= 3 or die "Usage: rotate-log <days-to-compress> <date-to-delete> <logs...>";
-
-$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 (file)
index 5bcb33c..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- *     Sherlock Utilities -- URL Handling Tool
- *
- *     (c) 2004 Martin Mares <mj@ucw.cz>
- */
-
-#include "ucw/lib.h"
-#include "ucw/getopt.h"
-#include "ucw/url.h"
-#include "ucw/fastbuf.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-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 [<options>] <operations> [<URL's>]\n\
-\n\
-Options:\n"
-CF_USAGE "\
--b, --base <URL>\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 (file)
index 0000000..e789272
--- /dev/null
@@ -0,0 +1,17 @@
+# Makefile for the UCW utilities (c) 2008 Michal Vaner <vorner@ucw.cz>
+
+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 (file)
index 0000000..501bd14
--- /dev/null
@@ -0,0 +1,66 @@
+/*
+ *     A Program For Manipulation With Base224 Encoded Files
+ *
+ *     (c) 2002 Martin Mares <mj@ucw.cz>
+ */
+
+#include "ucw/lib.h"
+#include "ucw/fastbuf.h"
+#include "ucw/base224.h"
+
+#include <stdio.h>
+
+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 (file)
index 0000000..892e883
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ *     UCW Library -- Line utility for encoding and decoding base64 & base224
+ *
+ *     (c) 2008, Michal Vaner <vorner@ucw.cz>
+ *
+ *     This software may be freely distributed and used according to the terms
+ *     of the GNU Lesser General Public License.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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 (file)
index 0000000..6146aab
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ *     A Simple Wrapper for Starting and Stopping of Daemons
+ *
+ *     (c) 2003 Martin Mares <mj@ucw.cz>
+ *
+ *     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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <errno.h>
+#include <alloca.h>
+
+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 <options> -- <daemon> <args>\n\
+   or: daemon-helper --stop <options>\n\
+   or: daemon-helper --force-stop <options>\n\
+   or: daemon-helper --reload <options>\n\
+   or: daemon-helper --check <options>\n\
+\n\
+Options:\n\
+--pid-file <name>      Name of PID file for this daemon (mandatory)\n\
+--status-file <name>   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 (file)
index 0000000..4ddb96a
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ *  Hexadecimal dumper (CP/M style format)
+ *
+ *  Original version (c) Eric S. Raymond <esr@snark.thyrsus.com>
+ *  Heavily modified by Martin Mares <mj@ucw.cz>
+ *
+ *  Can be freely distributed and used under the terms of the GNU GPL.
+ */
+
+#include "ucw/lib.h"
+#include "ucw/lfs.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#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("---- <Standard input> ----\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 (file)
index 0000000..e4c9b10
--- /dev/null
@@ -0,0 +1,27 @@
+#!/usr/bin/perl
+
+#      Rotate Sherlock logs
+#      (c) 2001--2002 Martin Mares <mj@ucw.cz>
+
+use File::stat;
+
+@ARGV >= 3 or die "Usage: rotate-log <days-to-compress> <date-to-delete> <logs...>";
+
+$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 (file)
index 0000000..5bcb33c
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ *     Sherlock Utilities -- URL Handling Tool
+ *
+ *     (c) 2004 Martin Mares <mj@ucw.cz>
+ */
+
+#include "ucw/lib.h"
+#include "ucw/getopt.h"
+#include "ucw/url.h"
+#include "ucw/fastbuf.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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 [<options>] <operations> [<URL's>]\n\
+\n\
+Options:\n"
+CF_USAGE "\
+-b, --base <URL>\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);
+}