/*	:ts=4
 *	checkgroups - this is a C implementation for the Amiga, in an attempt to
 *	reduce the dependency on shell scripts (they aren't capable enough).
 *
 *	Expects no command line arguments, but control article on stdin
 *
 *	$Id$
 */

#include <stdio.h>
#include <string.h>
#include <time.h>

#ifdef __STDC__
# include <stdarg.h>
#else
# include <varargs.h>
#endif /* __STDC__ */

#include "libc.h"
#include "news.h"
#include "config.h"
#include "system.h"

#define ADDGROUP	envparm("ADDGROUP")
#define DELGROUP	envparm("DELGROUP")

char *progname;
char **grps;
int count;
struct system *me;

int gngp(register char *pattern, register char *text)
{
	int returned;
	char savewhite;
	char *whitesp;
	extern char *strpbrk();

	whitesp = strpbrk(text, " \t\n");
	if (whitesp) {
		savewhite = *whitesp;
		*whitesp = '\0';
	}
	returned = ngmatch(pattern, text);
	if (whitesp)
		*whitesp = savewhite;
	return( returned );
}

int str_cmp(register void *a, register void *b)
{
	return( strcmp( *(char **)a, *(char **)b ) );
}

void mail(char *who, char *msg)
{
	FILE *fp;

	if (fp = fopen(ctlfile("errlog"), "a+")) {
		fprintf(fp, "\nTo: %s\nSubject: %s error\n\n%s\n", who, progname, msg);
		fclose(fp);
	}
}

void add_grp(register char *buf)
{
	register char *ptr;

	/*
	 *	This strips out JUNK, CONTROL, and GENERAL since they
	 *	don't have any periods in them.
	 */
#define INCR	128

	ptr = strtok(buf, " \t\n");
	if (*ptr != '#' && strchr(ptr, '.')) {
		if (gngp(me->sy_ngs, ptr)) {
			if ((count % INCR) == 0)
				grps = (char **) realloc(grps, (count+INCR) * sizeof(*grps));
			grps[count++] = strsave(ptr);
		}
	}
}

void writediffs(char **ngrp, int ncnt, char **ogrp, int ocnt)
{
	register int i = 0, j = 0, cmp;
	FILE *new = fopen(ctlfile("checkgroups.new"), "a+");
	FILE *del = fopen(ctlfile("checkgroups.del"), "a+");

	if (new && del) {
		time_t now;

		now = time(NULL);
		fprintf(new, "\n%s", ctime(&now));
		fprintf(del, "\n%s", ctime(&now));
		while (i < ncnt && j < ocnt) {
			if (cmp = strcmp(ngrp[i], ogrp[j])) {
				if (cmp < 0)
					fprintf(new, "%s %s\n", ADDGROUP, ngrp[i++]);
				else
					fprintf(del, "%s %s\n", DELGROUP, ogrp[j++]);
			} else
				i++, j++;
		}
		while (i < ncnt)
			fprintf(new, "%s <NIL: %s\n", ADDGROUP, ngrp[i++]);
		while (j < ocnt)
			fprintf(del, "%s %s\n", DELGROUP, ogrp[j++]);
	}
	fclose(new);
	fclose(del);
}

void readctl(char *name)
{
	FILE *fp;
	char buffer[BUFSIZ];

	if (name)
		fp = fopen(ctlfile(name), "r");
	else {
		fp = stdin;
		while (fgets(buffer, sizeof(buffer), fp))
			if (*buffer == '\n') break;
	}
	if (fp) {
		while (fgets(buffer, sizeof(buffer), fp))
			add_grp(skipsp(buffer));
		fclose(fp);
	}
}

int main(int argc, char **argv)
{
	char **newgrp;
	int newcount;

	if ((progname=strchr(*argv,'/')) || (progname=strchr(*argv,':')))
		progname++;
	else
		progname = *argv;

	if ((me = oursys()) == NULL) {
		mail(newsmaster(), "Couldn't find \"ME\" in sys file!");
		exit( 10 );
	}
	/*
	 *	Algorithm goes like this:
	 *		1)	obtain newsgroup subscription list
	 *		2)	read "localgroups" and call add_grp()
	 *		3)	read "newgroups" and call add_grp()
	 *		4)	read stdin (checkgroups article body) and call add_grp()
	 *		5)	add_grp() will strip out comments, lines without periods in
	 *			field 1, and lines which don't match subscription list
	 *		6)=	sort the results of (2) through (4)
	 *		7)=	strip field 1 from ACTIVE file via add_grp()
	 *
	 *	Compare (step7) to (step6)
	 *	If in (step6) and !(step7), add newsgroup
	 *	If in (step7) and !(step6), remove newsgroup
	 */

	count = 0;
	grps = NULL;
	readctl("newgroups");
	readctl("localgroups");
	readctl(NULL);				/* stdin */
	newcount = count;
	newgrp = grps;
	if (newcount > 1)
		qsort(newgrp, newcount, sizeof(*newgrp), str_cmp);

	/*	Now read the ACTIVE file.	*/
	count = 0;
	grps = NULL;
	readctl("active");
	if (count > 1)
		qsort(grps, count, sizeof(*grps), str_cmp);

	writediffs(newgrp, newcount, grps, count);
	return( 0 );
}
