Hello: As there still seems to be problems with memory (and as a consequence, history) corruption in nntpcached, I've written some code to support the rebuilding of the history database. To run it, first remove cache.history*, then try nntpcached -h The patch also includes: 1. Fixed the "can't connect" problem after SIGHUP. 2. Do not set[ug]id if not execed as root. 3. Changed prototype of Sstrdup to use const char *. 4. Corrected typos in article.c This patch is also available at: ftp://greathan.apana.org.au/pub/nntpcache/nntpcache-1.0.1.patch or http://greathan.apana.org.au/pub/nntpcache/nntpcache-1.0.1.patch -- Debian GNU/Linux 1.2 is out! { http://www.debian.org/ } Email: Herbert Xu ~{PmV>HI~} <herbert@greathan.apana.org.au> { http://greathan.apana.org.au/~herbert/ } PGP Key: pgp-public-keys@pgp.mit.edu or any other key sites -- diff --new-file -ur nntpcache-1.0.1/article.c nntpcache-1.0.1.new/article.c --- nntpcache-1.0.1/article.c Tue Oct 15 18:43:05 1996 +++ nntpcache-1.0.1.new/article.c Fri Jan 31 11:12:08 1997 @@ -547,7 +547,7 @@ sprintf (args, "article %d", artno); } else /* replace 'article' with 'body' if we pulled in a _head */ - if (c_article && real_head_file) + if (type == c_article && real_head_file) { if (*msgid) sprintf (args, "body <%.127s>", msgid); @@ -735,7 +735,7 @@ close (fd); if (buf[len - 1] != '\n') /* truncated file */ goto err; - if (!real_head_file && (!*msgid || f_filt)) + if (!real_head_file) { body = strstr (buf, "\r\n\r\n"); if (!body) diff --new-file -ur nntpcache-1.0.1/build_history.c nntpcache-1.0.1.new/build_history.c --- nntpcache-1.0.1/build_history.c Thu Jan 1 10:00:00 1970 +++ nntpcache-1.0.1.new/build_history.c Fri Jan 31 17:20:00 1997 @@ -0,0 +1,144 @@ +#include "filesystem.h" +#include "nntpcache.h" + +/* Strip off the port numbers to get the directory name. */ +static char *getdirname(const char *host) +{ + char *p, *q; + + p = Sstrdup(host); + q = strchr(p, ':'); + if (q) *q = 0; + return p; +} + +/* Form the "full" pathname of a file. */ +static char *fullpath(const char *path, const char *d_name) +{ + char *p; + int path_len, d_name_len; + int len; + + path_len = strlen(path); + d_name_len = strlen(d_name); + len = path_len + d_name_len + 2; + p = Smalloc(len); + memcpy(p, path, path_len); + p[path_len] = '/'; + memcpy(p + path_len + 1, d_name, d_name_len); + p[len - 1] = 0; + return p; +} + +/* Get the message-id. */ +static char *getmsgid(const char *line) +{ + char *msgid; + int len; + + while (isblank(*line)) line++; + len = strlen(line) - 3; + if (line[0] != '<' || line[len] != '>') return 0; + + msgid = Smalloc(len); + memcpy(msgid, &line[1], len); + msgid[len - 1] = 0; + + return msgid; +} + +/* Scan one article and add it to the history if necessary. */ +static void scan_article(const char *path, const char *artno) +{ + FILE *fp; + char buf[MAX_HEADER]; + char *msgid = 0; + + if (!(fp = fopen(artno, "r"))) { + perror(artno); + return; + } + + while (!msgid && fgets(buf, sizeof(buf), fp)) { + switch(*buf) { + default: + break; + + case 'M': case 'm': + if (!strncasecmp(buf, "message-id:", 11)) + msgid = getmsgid(&buf[11]); + break; + } + + while (buf[strlen(buf) - 1] != '\n' && + fgets(buf, sizeof(buf), fp)); + } + + if (msgid) { + char *p = Sstrdup(path); + + if (!hisGetDbz(msgid)) hisAddDbz(msgid, p); + free (p); + free(msgid); + } + + if (fclose(fp)) perror(artno); +} + +/* Scan the current directory recursively for things to add to the history. */ +static void scan_directory(const char *path) +{ + DIR *dp; + struct dirent *ep; + char *p, *q; + int i; + struct stat st; + + if (!(dp = opendir(path))) { + perror(path); + return; + } + + while ((ep = readdir(dp))) { + q = ep->d_name; + p = fullpath(path, q); + if (stat(p, &st) < 0) { + perror(p); + free(p); + continue; + } + + if (*q == '.') + ; + else if (S_ISDIR(st.st_mode)) scan_directory(p); + else { + i = strspn(q, "0123456789"); + if (S_ISREG(st.st_mode) && isdigit(q[0]) && + (!q[i] || q[i] == '_')) { + if (q[i] == '_') q[i] = 0; + q = fullpath(path, q); + scan_article(q, p); + } + } + free(p); + } + + if (closedir(dp)) perror(path); +} + +/* Build the history file. */ +X (void build_history()) +{ + char *p; + struct server_cfg *scfg; + + for (scfg = ServerList; scfg; scfg = scfg->next) { + if (chdir(con.cacheDir)) { + perror(con.cacheDir); + return; + } + p = getdirname(scfg->host); + scan_directory(p); + free(p); + } +} diff --new-file -ur nntpcache-1.0.1/history.c nntpcache-1.0.1.new/history.c --- nntpcache-1.0.1/history.c Sat Oct 5 19:18:31 1996 +++ nntpcache-1.0.1.new/history.c Fri Jan 31 16:13:19 1997 @@ -71,7 +71,6 @@ { #define HIS_BLK_SIZE 512 static char *buf; - static char *ret; long offset; int cc; int len; @@ -126,10 +125,7 @@ return NULL; } *p2 = '\0'; - if (ret) - free (ret); - ret = Sstrdup (p + 1); - return ret; + return Sstrdup (p + 1); } X (char *hisGet (char *msgid)) diff --new-file -ur nntpcache-1.0.1/libproff/libproff.h nntpcache-1.0.1.new/libproff/libproff.h --- nntpcache-1.0.1/libproff/libproff.h Sat Nov 9 03:14:10 1996 +++ nntpcache-1.0.1.new/libproff/libproff.h Fri Jan 31 15:54:18 1997 @@ -95,7 +95,7 @@ extern void *Smalloc (int n) ; extern void *Scalloc (int n, int n2) ; extern void *Srealloc (void *p, int n) ; -extern char *Sstrdup (char *s) ; +extern char *Sstrdup (const char *s) ; extern char *Xstrdup (char *s) ; extern int strKToi(char *s, int *i) ; extern char *conv (float n) ; diff --new-file -ur nntpcache-1.0.1/libproff/utils.c nntpcache-1.0.1.new/libproff/utils.c --- nntpcache-1.0.1/libproff/utils.c Fri Oct 4 13:22:27 1996 +++ nntpcache-1.0.1.new/libproff/utils.c Fri Jan 31 15:53:34 1997 @@ -159,7 +159,7 @@ return p; } -X (char *Sstrdup (char *s)) +X (char *Sstrdup (const char *s)) { void *p; int t = 0; diff --new-file -ur nntpcache-1.0.1/nntpcache.c nntpcache-1.0.1.new/nntpcache.c --- nntpcache-1.0.1/nntpcache.c Sat Nov 9 07:47:38 1996 +++ nntpcache-1.0.1.new/nntpcache.c Fri Jan 31 16:49:38 1997 @@ -48,6 +48,8 @@ X (bool Daemon) = TRUE; X (bool InDaemon); +X (bool MakeHistory) + = FALSE; X (void *Mbase); static char PidFile[MAX_PATH] = ""; X(struct command commands[]) @@ -538,10 +540,31 @@ static void usage (char *argv0) { - fprintf (stderr, "usage: %s [einrs] [-b addr:port] [-c config_file]\n", argv0); + fprintf (stderr, "usage: %s [ehinrs] [-b addr:port] [-c config_file]\n", argv0); exit (1); } +static void drop_priv(int uid, int gid) +{ + /* Can't drop priviledges if we're not root. */ + if (geteuid() != 0) return; + + if (setgid (gid) == -1) + { + loge (("unable to set gid to %d", gid)); +#ifndef DEBUG + Exit (); +#endif + } + if (setuid (uid) == -1) + { + loge (("unable to set uid to %d", uid)); +#ifndef DEBUG + Exit (); +#endif + } +} + int main (int argc, char **argv) { int connected = 0; @@ -571,7 +594,7 @@ \n\ -nntpcache development team\n"); - while ((c = getopt (argc, argv, "einb:rc:s")) != -1) + while ((c = getopt (argc, argv, "ehinb:rc:s")) != -1) switch (c) { case 'a': @@ -611,6 +634,10 @@ case 's': f_swap_child = TRUE; break; + case 'h': + Daemon = FALSE; + MakeHistory = TRUE; + break; default: usage (argv[0]); } @@ -694,24 +721,7 @@ gid = gr->gr_gid; if (con.chroot) perform_chroot(); - if (!Daemon) - { - - if (setgid (gid) == -1) - { - loge (("unable to set gid to %d", gid)); -#ifndef DEBUG - Exit (); -#endif - } - if (setuid (uid) == -1) - { - loge (("unable to set uid to %d", uid)); -#ifndef DEBUG - Exit (); -#endif - } - } + if (!Daemon) drop_priv(uid, gid); if (!IPCloadStats (con.statsFile)) Stats->time_statistics_started = time (NULL); Stats->servers_run++; @@ -728,14 +738,19 @@ signal (SIGINT, sigterm); signal (SIGSEGV, sigsegv); signal (SIGFPE, SIG_IGN); + if (MakeHistory) + { + build_history(); + goto end; + } if (Daemon) { #ifdef CRASHES_UNDER_LINUX char *io_buf; #endif struct sockaddr_in *in; - int daemon_port = -1; /* keep -Wall happy */ - int high_fd = -1; + int daemon_port; + int high_fd; fd_set r_set, rt_set, et_set; FD_ZERO (&r_set); FD_ZERO (&rt_set); @@ -760,21 +775,7 @@ loge (("couldn't bind %s", con.bindAddr)); Exit (); } - if (setgid (gid) == -1) - { - loge (("unable to set gid to %d", gid)); -#ifndef DEBUG - Exit (); -#endif - } - if (setuid (uid) == -1) - { - loge (("unable to set gid to %d", gid)); - loge (("unable to set uid to %d", uid)); -#ifndef DEBUG - Exit (); -#endif - } + drop_priv(uid, gid); listen (daemon_port, 50); FD_SET (daemon_port, &r_set); high_fd = daemon_port; @@ -795,6 +796,7 @@ fclose (fh); } } + else FD_SET (daemon_port, &r_set); open_mmap(); sig_hup = FALSE; expire (FALSE); @@ -1126,6 +1128,7 @@ break; } } +end: flush (); if (!Daemon || InDaemon) {