NNTPC: makehistory for nntpcache

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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)
 	{


[Index of Archives]     [Yosemite]     [Yosemite Campsites]     [Bugtraq]     [Linux]     [Trn]

Powered by Linux