/* This file (and only this file - not the entire nntp distribution) is
 * hereby placed in the public domain.  Use it as you see fit, but if you
 * manage to find some wonderful use for this code elsewhere, it would be
 * nice to receive mention for it.
 *
 * - Tim Iverson
 *   iverson@xstor.com -/- uunet!xstor!iverson
 *   3/28/91
 *   modified by Wayne Davison (davison@borland.com) to work with trn 2.0
 *   10/6/91
 */

#include "common.h"

#ifdef XTHREAD

# ifdef __GNUC__
#  define alloca __builtin_alloca
# endif


/* Usage: XTHREAD [DBINIT|THREAD]
 *
 * DBINIT	dump the contents of the db.init file to stdout
 * THREAD	dump the contents of the thread file for the current
 *		newsgroup to stdout (default if no argument).
 *
 * N.B. These two files are not ascii and no attempt is made at converting
 *	native byte size to any type of standard whatsoever.  This'll have
 *	to be fixed if this command is to be integrated into the protocol.
 *
 * This command is not documented in rfc977.
 */

void
xthread(argc, argv)
int	argc;
char	*argv[];
{
	register FILE	*fp;
	struct stat	s;
	char		*buf, *file, *what;

	/* can't transfer threads, only read 'em */
	if (!canread)
	{
		printf("%d You only have permission to transfer, sorry.\r\n",
			ERR_ACCESS);
		(void) fflush(stdout);
		return;
	}

	/* "parse" the argument */
	if (argc == 2 && !strcasecmp(argv[1], "dbinit"))
	{
		char *cp, *thread_name();

		file = thread_name("*******");
		what = "db.init";
		for (cp = file; *cp != '*'; cp++)
			;
		strcpy(cp, what);
	}
	else if (argc == 1 || argc == 2 && !strcasecmp(argv[1], "thread"))
	{
		if (!threadfile)
		{
			printf("%d You are not currently in a newsgroup.\r\n",
				ERR_NCING);
			(void) fflush(stdout);
			return;
		}
		file = threadfile;
		what = "thread";
	}
	else
	{
		printf("%d Usage: XTHREAD [DBINIT|THREAD]\r\n", ERR_CMDSYN);
		(void) fflush(stdout);
		return;
	}

	/* try to open the file to be transfered */
	if (!(fp = fopen(file, "r")))
	{
		printf("%d %s file is not available.\r\n", ERR_FAULT, what);
		(void) fflush(stdout);
#ifdef SYSLOG
		if (!strcmp(what, "db.init"))
		    syslog(LOG_ERR, "xthread: fopen %s: %m", file);
#endif
		return;
	}

	/* tell 'em how much binary data is coming down the pike */
	fstat(fileno(fp), &s);
	printf("%d %u bytes of %s file follows verbatim (binary!)\r\n",
		OK_BIN, s.st_size, what);

	/* copy the file verbatim to stdout */
#ifdef __GNUC__
	if (buf = alloca(s.st_size))
	{
		/* ah-so! got lotsa memoree */
		read(fileno(fp), buf, s.st_size);
		fwrite(buf, s.st_size, 1, stdout);
	}
	else
#endif
	{
		int		bytes;
		char		buf[BUFSIZ];

		while (bytes = fread(buf, 1, sizeof buf, fp))
			fwrite(buf, bytes, 1, stdout);
	}

	fputs("\r\n.\r\n", stdout);
	fflush(stdout);
	fclose(fp);
}

/* Change a newsgroup name into the name of the thread data file.  We
** subsitute any '.'s in the group name into '/'s (unless LONG_THREAD_NAMES
** is defined), prepend the path, and append the '/.thread' (or '.th') on to
** the end.
*/
char *
thread_name(group)
char *group;
{
	static char name_buff[MAXPATHLEN];
#ifndef LONG_THREAD_NAMES
	char group_buff[512];
	register char *ptr;

	strcpy(group_buff, group);
	ptr = group = group_buff;
	while ((ptr = index(ptr, '.'))) {
		*ptr = '/';
	}
#endif
#ifdef SUFFIX
	sprintf(name_buff, "%s/%s%s", threaddir, group, SUFFIX);
#else
	sprintf(name_buff, "%s/%s", threaddir, group);
#endif

	return name_buff;
}

#endif /* not XTHREAD */
