#define MD5_SIZE 16
#define MD5_HEX_SIZE 33
+
+/* fcopy.c */
+
+void fcopy(FILE *, FILE *, uns, byte *, uns);
+
+/* prime.c */
+
+int isprime(uns);
+uns nextprime(uns);
+
+/* timer.c */
+
+void init_timer(void);
+uns get_timer(void);
#define DO_FOR_ALL(n,list) for((n)=HEAD(list);(NODE (n))->next; \
n=(void *)((NODE (n))->next))
#define EMPTY_LIST(list) (!(list).head.next->next)
+#define OFFSETOF(s, i) ((unsigned int)&((s *)0)->i)
+#define SKIP_BACK(s, i, p) ((s *)((char *)p - OFFSETOF(s, i)))
void add_tail(list *, node *);
void add_head(list *, node *);
void
initlog(byte *argv0)
{
- progname = basename(argv0);
+ if (argv0)
+ progname = basename(argv0);
pid = getpid();
}
--- /dev/null
+/*
+ * Sherlock Library -- Memory Pools (One-Time Allocation)
+ *
+ * (c) 1997 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lib.h"
+#include "pools.h"
+
+struct memchunk {
+ struct memchunk *next;
+ byte data[0];
+};
+
+struct mempool *
+new_pool(uns size)
+{
+ struct mempool *p = xmalloc(sizeof(struct mempool));
+
+ size -= sizeof(struct memchunk);
+ p->chunks = NULL;
+ p->free = p->last = NULL;
+ p->chunk_size = size;
+ p->threshold = size / 3;
+ return p;
+}
+
+void
+free_pool(struct mempool *p)
+{
+ struct memchunk *c = p->chunks;
+
+ while (c)
+ {
+ struct memchunk *n = c->next;
+ free(c);
+ c = n;
+ }
+ free(p);
+}
+
+void *
+pool_alloc(struct mempool *p, uns s)
+{
+ if (s <= p->threshold)
+ {
+ byte *x = (byte *)(((uns) p->free + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
+ if (x + s > p->last)
+ {
+ struct memchunk *c = xmalloc(sizeof(struct memchunk) + p->chunk_size);
+ c->next = p->chunks;
+ p->chunks = c;
+ x = c->data;
+ p->last = x + p->chunk_size;
+ }
+ p->free = x + s;
+ return x;
+ }
+ else
+ {
+ struct memchunk *c = xmalloc(sizeof(struct memchunk) + s);
+ c->next = p->chunks;
+ p->chunks = c;
+ return c->data;
+ }
+}
--- /dev/null
+/*
+ * Sherlock Library -- Memory Pools
+ *
+ * (c) 1997 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#define POOL_ALIGN 4
+
+struct mempool {
+ struct memchunk *chunks;
+ byte *free, *last;
+ uns chunk_size, threshold;
+};
+
+struct mempool *new_pool(uns);
+void free_pool(struct mempool *);
+void *pool_alloc(struct mempool *, uns);
+
+extern inline void *fast_alloc(struct mempool *p, uns l)
+{
+ void *f = (void *) (((uns) p->free + POOL_ALIGN - 1) & ~(POOL_ALIGN - 1));
+ byte *ee = f + l;
+ if (ee > p->last)
+ return pool_alloc(p, l);
+ p->free = ee;
+ return f;
+}
+
+extern inline void *fast_alloc_noalign(struct mempool *p, uns l)
+{
+ void *f = p->free;
+ byte *ee = f + l;
+ if (ee > p->last)
+ return pool_alloc(p, l);
+ p->free = ee;
+ return f;
+}
--- /dev/null
+/*
+ * Sherlock Library -- Prime Number Tests
+ *
+ * (c) 1997 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "lib.h"
+
+static int /* Sequential search */
+__isprime(uns x) /* We know x != 2 && x != 3 */
+{
+ uns test = 5;
+
+ if (x == 5)
+ return 1;
+ for(;;)
+ {
+ if (!(x % test))
+ return 0;
+ if (x / test <= test)
+ return 1;
+ test += 2; /* 6k+1 */
+ if (!(x % test))
+ return 0;
+ if (x / test <= test)
+ return 1;
+ test += 4; /* 6k-1 */
+ }
+}
+
+int
+isprime(uns x)
+{
+ if (x < 5)
+ return (x == 2 || x == 3);
+ switch (x % 6)
+ {
+ case 1:
+ case 5:
+ return __isprime(x);
+ default:
+ return 0;
+ }
+}
+
+uns
+nextprime(uns x) /* Returns some prime greater than X, usually the next one or the second next one */
+{
+ x += 5 - (x % 6); /* x is 6k-1 */
+ for(;;)
+ {
+ if (__isprime(x))
+ return x;
+ x += 2; /* 6k+1 */
+ if (__isprime(x))
+ return x;
+ x += 4; /* 6k-1 */
+ }
+}
+
+#ifdef PRIME_DEBUG
+
+int
+main(int argc, char **argv)
+{
+ uns k = atol(argv[1]);
+ if (isprime(k))
+ printf("%d is prime\n");
+ else
+ printf("Next prime is %d\n", nextprime(k));
+}
+
+#endif
--- /dev/null
+/*
+ * Sherlock Library -- Prime Number Tests
+ *
+ * (c) 1997 Martin Mares, <mj@atrey.karlin.mff.cuni.cz>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+
+#include "lib.h"
+
+static struct timeval last_tv;
+
+uns
+get_timer(void)
+{
+ struct timeval tv;
+ uns diff;
+
+ gettimeofday(&tv, NULL);
+ if (tv.tv_sec < last_tv.tv_sec
+ || tv.tv_sec == last_tv.tv_sec && tv.tv_usec < last_tv.tv_usec)
+ diff = 0;
+ else
+ {
+ if (tv.tv_sec == last_tv.tv_sec)
+ diff = (tv.tv_usec - last_tv.tv_usec + 500) / 1000;
+ else
+ {
+ diff = 1000 * (tv.tv_sec - last_tv.tv_sec - 1);
+ diff += (1000500 - last_tv.tv_usec + tv.tv_usec) / 1000;
+ }
+ }
+ last_tv = tv;
+ return diff;
+}
+
+void
+init_timer(void)
+{
+ gettimeofday(&last_tv, NULL);
+}
*d++ = *s++;
else
{
- uns val = (*s < NCC_MAX) ? ";/?:@=&"[*s] : *s;
+ uns val = (*s < NCC_MAX) ? NCC_CHARS[*s] : *s;
*d++ = '%';
*d++ = enhex(val >> 4);
*d++ = enhex(val & 0x0f);
/* Split an URL (several parts may be copied to the destination buffer) */
+byte *url_proto_names[URL_PROTO_MAX] = URL_PNAMES;
+
uns
identify_protocol(byte *p)
{
- if (!strcasecmp(p, "http"))
- return URL_PROTO_HTTP;
- if (!strcasecmp(p, "ftp"))
- return URL_PROTO_FTP;
- return 0;
+ uns i;
+
+ for(i=1; i<URL_PROTO_MAX; i++)
+ if (!strcasecmp(p, url_proto_names[i]))
+ return i;
+ return URL_PROTO_UNKNOWN;
}
int
/* Normalization according to given base URL */
-static uns std_ports[] = { ~0, 80, 21 }; /* Default port numbers */
+static uns std_ports[] = URL_DEFPORTS; /* Default port numbers */
static int
relpath_merge(struct url *u, struct url *b)
#define NCC_AND 7
#define NCC_MAX 8
+#define NCC_CHARS " ;/?:@=&"
+
/* Remove/Introduce '%' escapes */
int url_deescape(byte *, byte *);
#define URL_PROTO_UNKNOWN 0
#define URL_PROTO_HTTP 1
#define URL_PROTO_FTP 2
-#define URL_PROTO_MAX 3
+#define URL_PROTO_FILE 3
+#define URL_PROTO_MAX 4
+
+#define URL_PNAMES { "unknown", "http", "ftp", "file" }
+#define URL_DEFPORTS { ~0, 80, 21, 0 }
-#define URL_PNAMES { "unknown", "http", "ftp" }
+extern byte *url_proto_names[];