/* $Id: puf.c,v 1.10 2004/02/13 15:29:00 ossi Exp $ *
*
* puf 0.9 Copyright (C) 2000-2004 by Oswald Buddenhagen <puf@ossi.cjb.net>
* based on puf 0.1.x (C) 1999,2000 by Anders Gavare <gavare@hotmail.com>
*
* You may modify and distribute this code under the terms of the GPL.
* There is NO WARRANTY of any kind. See COPYING for details.
*
* puf.c - startup code and global functions
*
*/
#include "puf.h"
int verbose;
char *progname;
#ifdef DEBUG
int debug;
#endif
#ifndef HAVE_STRDUP
char *
strdup(const char *s)
{
int l = strlen(s) + 1;
char *rt = malloc(l);
if (rt)
memcpy(rt, s, l);
return rt;
}
#endif
#define FMTLEN 128
int
errm(url_t *u, const char *msg, ...)
{
char *pt;
va_list va;
int rtv, lv;
unsigned l, i, fl;
char tbuf[2 * SHORTSTR + FMTLEN], fmt[SHORTSTR];
num_errors++;
if (*msg == '!') {
msg++;
num_urls_fail++;
rtv = RT_GIVEUP;
lv = ERR;
} else if (++u->attempt >= (unsigned)u->parm->opt->max_attempts) {
num_urls_fail++;
rtv = RT_GIVEUP;
lv = ERR;
} else {
rtv = RT_RETRY;
lv = WRN;
}
if (lv <= verbose) {
snprintf(fmt, sizeof(fmt),
rtv == RT_RETRY ? "%s warning: %s (try %d)\n" : "%s: %s\n",
progname, msg, u->attempt);
if ((pt = strstr(fmt, "$u"))) {
if (u->port == 80)
l = snprintf(tbuf + SHORTSTR + FMTLEN, SHORTSTR,
"http://%s/%s", u->host->name, u->local_part);
else
l = snprintf(tbuf + SHORTSTR + FMTLEN, SHORTSTR,
"http://%s:%i/%s", u->host->name, u->port, u->local_part);
if (l >= SHORTSTR) {
memcpy(tbuf + 2 * SHORTSTR + FMTLEN - 4, "...", 4);
l = SHORTSTR - 1;
}
fl = (unsigned)(pt - fmt);
memcpy(tbuf, fmt, fl);
for (i = 0; i < l; i++) {
if (tbuf[i + SHORTSTR + FMTLEN] == '%')
tbuf[fl++] = '%';
tbuf[fl++] = tbuf[i + SHORTSTR + FMTLEN];
}
strcpy(tbuf + fl, pt + 2);
pt = tbuf;
} else
pt = fmt;
va_start(va, msg);
vfprintf(stderr, pt, va);
va_end(va);
}
return rtv;
}
void
dbp(const char *msg, ...)
{
char fmt[SHORTSTR];
va_list va;
snprintf(fmt, SHORTSTR, "%s debug: %s", progname, msg);
va_start(va, msg);
vfprintf(stderr, fmt, va);
va_end(va);
}
void
dbpe(const char *msg, ...)
{
va_list va;
va_start(va, msg);
vfprintf(stderr, msg, va);
va_end(va);
}
void
prx(int lev, const char *msg, ...)
{
char fmt[SHORTSTR];
static const char *prfs[] = {" fatal", "", " warning", " info", " debug"};
va_list va;
if (lev <= verbose) {
snprintf(fmt, SHORTSTR, "%s%s: %s", progname, prfs[lev], msg);
va_start(va, msg);
vfprintf(stderr, fmt, va);
va_end(va);
}
}
/* print an error message and terminate */
void
die(int ret, const char *msg, ...)
{
char fmt[SHORTSTR];
va_list va;
snprintf(fmt, SHORTSTR, "\n%s: %s\n", progname, msg);
va_start(va, msg);
vfprintf(stderr, fmt, va);
va_end(va);
exit(ret);
}
#ifndef __DMALLOC_H__
/* allocate memory or ask user what to do, if none available */
void *
mrealloc(void *ptr, size_t size)
{
void *t;
static int asked = 0;
if (size <= 0 || size > 100000)
ierr("Internal error: Invalid memory allocation request.");
if (!(t = realloc(ptr, size))) {
if (!asked && isatty(0) && isatty(2)) {
prx(0, "Out of memory. Strange things may happen. Continue [n]? ");
if (getchar() != 'y')
byebye("aborting");
asked++;
} else
prx(ERR, "Allocation of %d bytes failed!\n", size);
}
return t;
}
void *
mmalloc(size_t size)
{
return mrealloc(0, size);
}
#endif
static long crc32_tab[256];
static void
init_hash(void)
{
int i, b;
long by;
for (i = 0; i < 256; i++) {
for (by = i, b = 0; b < 8; b++)
by = (by >> 1) ^ (-(by & 1) & 0xedb88320);
crc32_tab[i] = by;
}
}
/* this is the normal crc32 algorithm. the generated numbers are quite
unique, but i don't know, if they are well dispersed, i.e., if they are
adequate for a real hash table. */
int
calc_hash(u_char * data, int len)
{
int i;
long crc = 0xc0debabe;
for (i = 0; i < len; i++, data++)
crc = (crc >> 8) ^ crc32_tab[(crc & 255) ^ *data];
return (int)crc;
}
#ifdef USE_MAGIC
void
magck(const char *msg)
{
url_t *u;
int i;
for (u = urllist, i=0; u; u = u->next, i++) {
if (!ichecken_url(u))
prx(ERR, "checksum error for url[%d] (%s/%s) in %s\n",
i, u->host->name, u->local_part, msg);
else if (!ichecken_gen(u->parm))
prx(ERR, "checksum error for url[%d]->parm (%s/%s) in %s\n",
i, u->host->name, u->local_part, msg);
else if (!ichecken_gen(u->parm->opt))
prx(ERR, "checksum error for url[%d]->parm->opt (%s/%s) in %s\n",
i, u->host->name, u->local_part, msg);
else
continue;
ierr("internal error");
}
}
#endif
int
main(int argc, char *argv[])
{
#ifdef __DMALLOC_H__
url_t *u, *nu;
host_t *h, *nh;
hinfo_t *hi;
#endif
if (!isatty(1))
show_stat = 0;
else
printf(PACKAGE " v" VERSION
" Copyright (C) 2000-2004 by Oswald Buddenhagen\n"
" based on puf v0.1.x "
"Copyright (C) 1999,2000 by Anders Gavare\n");
progname = strrchr(argv[0], '/');
if (progname)
progname++;
else
progname = argv[0];
bind_addr.sin_family = AF_INET; /* the rest is already 0 */
srand(time(0));
init_hash();
init_user_agent();
getopts(argc, argv);
setlocale(LC_TIME, "C"); /* some voodoo for strftime */
fetch_all();
#ifdef __DMALLOC_H__
for (u = urllist; u; u = nu) {
nu = u->next;
dbg(MEM, ("disposing http://%s/%s\n", u->host->name, u->local_part));
free(u);
}
for (hi = 0, h = hostlist; h; h = nh) {
if (h->info != hi) {
hi = h->info;
if (hi) {
dbg(MEM, ("disposing host info for '%s'\n", hi->name));
free(hi);
}
}
nh = h->next;
dbg(MEM, ("disposing host '%s'\n", h->name));
free(h);
}
#endif
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1