Some MH Mail hooks for news

teklabs!tekmdp!azure!stevenm teklabs!tekmdp!azure!stevenm
Thu Apr 15 16:36:59 AEST 1982


Here are some modifications to readnews (module readr.c) which
allow use of the MHMAIL 'comp' program for replying to articles,
and the similar 'submit' program (just like comp) for submitting
new or followup articles. The 'submit' program itself is included.
The modifications enclosed are to 'readr.c', 'header.c', 'defs.h',
and 'Makefile.v7'. The source and manual page for 'submit' are
also enclosed.

Note that you will have to have the MH system already for 'submit'
to compile, because it depends heavily on routines in the MH
libraries. Also note that we run the Feb 1980 release of MH Mail,
and if any of the subroutine calls made by 'submit' have changed,
it may not work.

I would like to hear from anyone who actually uses this code,
or is working on integrating MH and News, so that we can share
our work.

S. McGeady

teklabs!stevenm



#############
# readr.c   #
#############

32c32
< 	char *ptr1, *ptr2, *ptr3;	/* for reply manipulation	*/
---
> 	char *ptr1, *ptr2, *ptr3, *ptr4;/* for reply manipulation	*/

[shortly after case 'r':]

393a394,396
> 			ptr2 = h.ident;
> 			ptr3 = h.title;
> 			ptr4 = h.subdate;
396c399
< 				if (*hbuf1.path)
---
> 				if (*hbuf1.path) {
397a401,404
> 					ptr2 = hbuf1.ident;
> 					ptr3 = hbuf1.title;
> 					ptr4 = hbuf1.subdate;
> 				}
428a436,467
> #ifdef MHMAIL
> 
> 			{
> 			char *tmpp;
> 			FILE *tfd;
> 			extern char *mktemp();
> 
> 			tmpp = mktemp("/tmp/newsXXXXXX");
> 			if ((tfd = fopen(tmpp, "w")) == NULL) {
> 				fprintf(ofp, "Can't create tmpfile\n");
> 				break;
> 			}
> 
> 			fprintf(tfd, "To: %s\n", rcbuf);
> 			fprintf(tfd, "Subject: ");
> 
> 			if (*bptr == '\0') {
> 				if (strncmp(ptr3, "Re: ", 4)) {
> 					fprintf(tfd, "Re: ");
> 				}
> 				fprintf(tfd, "%s\n", ptr3);
> 			} else {
> 				fprintf(tfd, "%s\n", bptr);
> 			}
> 			fprintf(tfd, "In-reply-to: Your news article %s of %s\n", ptr2, ptr4);
> 			fprintf(tfd, "-----------------\n");
> 			fclose(tfd);
> 			sprintf(bfr, "%s %s %s", COMP, DFLAG, tmpp);
> 			system(bfr);
> 			unlink(tmpp);
> 			}
> #else
438a478
> #endif
440d479
< 

[shortly after "case 'f':"]

547a587,592
> #ifdef MHMAIL
> 			{
> 			char *tmpp;
> 			FILE *tfd;
> 			extern char *mktemp();
> 
550a596
> 
558a605,645
> 			while (isspace(*bptr))
> 				bptr++;
> 
> 			launder(ptr2);
> 
> 			tmpp = mktemp("/tmp/newsXXXXXX");
> 			if ((tfd = fopen(tmpp, "w")) == NULL) {
> 				fprintf(ofp, "Can't create tmpfile\n");
> 				break;
> 			}
> 			fprintf(tfd, "Newsgroups: %s\n", ptr2);
> 			sprintf(bfr, "%s %s %s", SUBMIT, DFLAG, tmpp);
> 			fprintf(tfd, "Subject: ");
> 
> 			if (*bptr == '\0') {
> 				if (strncmp(tfilename, "Re: ", 4)) {
> 					fprintf(tfd, "Re: ");
> 				}
> 				fprintf(tfd, "%s\n", tfilename);
> 			} else {
> 				fprintf(tfd, "%s\n", bptr);
> 			}
> 			fprintf(tfd, "Followup-to: %s\n", ptr3);
> 			fprintf(tfd, "-----------------\n");
> 			fclose(tfd);
> 
> 			system(bfr);
> 			unlink(tmpp);
> 			}
> #else
> 			tfilename = h.title;
> 			ptr2 = h.nbuf;
> 			ptr3 = h.ident;
> 			if (*bptr == '-') {
> 				if (*hbuf1.title && *hbuf1.nbuf) {
> 					tfilename = hbuf1.title;
> 					ptr2 = hbuf1.nbuf;
> 					ptr3 = hbuf1.ident;
> 				}
> 				bptr++;
> 			}
617a705
> #endif
619d706
< 


#############
# header.c  #
#############

64c64
< #define SUBMIT		4
---
> #define SUBMT		4
104c104
< 			case SUBMIT:
---
> 			case SUBMT:
181c181
< 		return SUBMIT;
---
> 		return SUBMT;


#############
# defs.h    #
#############

[Add these lines]

> #define	MHMAIL	1
> 
> #ifdef MHMAIL
> #define	SUBMIT	"/usr/bin/submit"
> #define	COMP	"/usr/bin/comp"
> #define	DFLAG	"-form"
> #endif
> 

#############
# submit.c  #
#############

/*
 * this program uses the MH Mail system subroutine librarys
 * found in subs.a and strings.a in /usr1/src/cmd/mh
 * 'mh.h' is also there
 */

#include "mh.h"
#include <stdio.h>
#include <strings.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>

/*
 * submit - submit a note to the Duke NewsNet news service
 *
 *******************************************************************
 *
 * 27-aug-80 sdg	Written
 * 02-nov-80 sdg	fixed bug that inserted \n every 512 characters
 *
 *	6/24/81	mcg	hacked from the 'post' program
 *
 *	7/27/81 mcg	modified to take 'post' entrypoint, and to
 *			back the input file up in ',<infile>'
 *			changed all error messages to print argv[0]
 *			instead of 'submit'
 *
 *	12/29/81 mcg	modfied for B news
 *
 *	4/15/82  mcg	modified for 2.3 B News
 */

#define NONE 0
#define	DEFAULTGROUP	"general"
#define	NEWSCOMPS	"newscomps"
#define	STDNEWSCOMPS	LIBDIR/newscomps"
#define	NEWSDIR		SPOOLDIR"
#define	NEWSDRAFT	"ndraft"

#define MAXSUBJ	128

char	*newsproc	= "inews";
char	*myname;

char *anyul[] = {
	"no",   0,
	"yes",  0,
	"use",  0,
	"list", 0,
	0
};

char *any[] = {
	"no",	0,
	"yes",	0,
	0
};

char *alfeqs[] = {
	"list",              0,         /* 0 */
	"format",            0,         /* 1 */
	"edit [<editor>]",   0,         /* 2 */
	"quit [delete]",     0,         /* 3 */
	"submit",	     0,		/* 4 */
	"post",		     0,		/* same as submit */
	0
};


struct swit switches[] = {
	"editor editor",  0,      /* 0 */
	"form formfile",  0,      /* 1 */
	"use",            0,      /* 2 */
	"nouse",          0,      /* 3 */
	"dfile draftfile",0,      /* 4 */
	"debug",          0,      /* 5 */
	"help",           4,      /* 6 */
	0,                0
};

char *rindex();

int debug = 0;

main(argc, argv)
char *argv[];
{
	register char	*cp;
	register int	in;
	register int	out;

	int	use;
	int	cnt;
	int	status;
	int	intr;

	char	buf[BUFSIZ];
	char	*newsgroup;
	char	*ed;
	char	*file;
	char	*form;

	static char	path[128];

	char	**ap;
	char	*arguments[50];
	char	**argp;

	myname = argv[0];

	form = 0; use = 0; file = 0; ed = 0;

	cp = r1bindex(argv[0], '/');

	if((cp = m_find(cp)) != NULL) {
		ap = brkstring(cp = getcpy(cp), " ", '\n');
		ap = copyip(ap, arguments);
	} else
		ap = arguments;

	copyip(argv+1, ap);

	argp = arguments;

	while(cp = *argp++) {
		if(*cp == '-') {
			switch(smatch(++cp, switches)) {

					case -2:
						ambigsw(cp, switches);  /* ambiguous */
						goto leave; /* unknown */

					case -1:
						fprintf(stderr, "%s: -%s unknown\n", myname, cp);
						goto leave;


					case 0:
						if(!(ed = *argp++)) {   /* -editor */
	  missing:	 			fprintf(stderr, "%s: Missing argument ", myname);
							fprintf(stderr, "for %s switch\n", argp[-2]);
							goto leave;
						}

						continue;

					case 1:
						if(!(form = *argp++))   /* -form */
							goto missing;
						continue;

					case 2:
						use = 1;
						continue;     /* -use */

					case 3:
						use = 0;
						continue;     /* -nouse */

					case 4:
						if(!(file = *argp++))	/* -dfile */
							goto missing;
						continue;

					case 5:
						debug++;
						continue;	/* -debug */

					case 6:
						help("submit/post [switches]", switches);
						goto leave;
			}

		}

	}

	if(form) {
		if((in = open(m_maildir(form), 0)) < 0) {
			fprintf(stderr, "%s: Can't open form file: %s\n", myname, form);
			goto leave;
		}
	} else if((in = open(m_maildir(NEWSCOMPS), 0)) < 0 &&
		   (in = open(STDNEWSCOMPS, 0)) < 0) {
			fprintf(stderr, "%s: Can't open default components file!!\n", myname);
			goto leave;
	}

	if(!file)
		file = NEWSDRAFT;

	copy(m_maildir(file), path);

	if((out = open(path, 0)) >= 0) {

		cp = concat("\n\"", path, "\" exists; delete? ", 0);

		if(use || fdcompare(in, out))
			goto editit;

		while((status = gans(cp, anyul)) == 3)
				showfile(path);

		if(status == 2) {
			use++;
			goto editit;
		}

		if(status == 0)
			goto leave;

		close(out);

	} else if(use) {
		fprintf(stderr, "%s: \"%s\" doesn't exist!\n", myname, path);
		goto leave;
	}

	if((out = creat(path, m_gmprot())) < 0) {
		fprintf(stderr, "%s: Can't create \"%s\"\n", myname, path);
		goto leave;
	}

	do {
		if(cnt = read(in, buf, sizeof buf))
			write(out, buf, cnt);
	} while(cnt == sizeof buf);

	close(in);


editit:

	close(out);

	if(m_edit(&ed, path, use, NONE) < 0)
		goto leave;

    for(;;) {
		if(!(argp = getans("\nWhat now? ", alfeqs)))
			goto leave;

		switch(smatch(*argp, alfeqs)) {

			case 0:
				showfile(path);                         /* list */
				break;

			case 1:
				if (m_format(path, use) == -1)		/* format */
					goto leave;
				break;

			case 2:
				if(*++argp)                             /* edit */
					ed = *argp;

				if(m_edit(&ed, path, use, NONE) == -1)
					goto leave;

				break;

			case 3:
				if(*++argp && *argp[0] == 'd')           /* quit */
					if(unlink(path) == -1)  {
						fprintf(stderr, "Can't unlink %s ", path);
						perror("");
					}
				goto leave;


			case 4: /* submit */
			case 5:	/* post   */

				if (!postit(path))
					goto leave;

				break;

			default:
				fprintf(stderr, "%s: illegal option\n", myname);       /*##*/
				break;
		}
    }

leave:

	m_update();
	done(0);
}

long convtime(tp)
register char *tp;
{

	if (tp == NULL) return(0L);

	while (*tp == ' ' || *tp == '\t' || *tp == '\n') tp++;

	if (*tp == '\0') return(0L);

	return(-1L);		/* error in processing */
}

char *mktemp();

postit(pathname)
char *pathname;
{
	FILE	*pfile;
	FILE	*tfile;
	char	*tmpname;
	extern int errno;

	int	state;
	int	compnum;
	int	firstbody;
	int	retcode;

	char	name[NAMESZ];
	char	buf[BUFSIZ];
	char	tmp[BUFSIZ];
	char	yatmp[BUFSIZ];

	char	*newsgroup;
	char	*p;
	char	*expdate;
	char	*subjp;
	char	*follow;

	struct stat statb;

	int	pid;
	int	wpid;
	int	status;
	int	i;

	retcode = 0;
	pfile = 0;
	tfile = 0;
	tmpname = 0;


	if ((pfile = fopen(pathname, "r")) == NULL) {
		fprintf(stderr, "%s: Can't open %s\n", myname, pathname);
		retcode = 1;
		goto leave;
	}

	if (!debug) {
		tmpname = mktemp("/tmp/postXXXXXX");

		if ((tfile = fopen(tmpname, "w")) == NULL) {
			fprintf(stderr, "%s: Can't create %s\n", myname, tmpname);
			retcode = 1;
			goto leave;
		}
		chmod(tmpname, 0644);
	} else  {
		tfile = stdout;
	}

	state = FLD, compnum = 0, firstbody = 0, expdate = 0, subjp = 0;
	follow = 0;

	for(;;) {

		state = m_getfld(state, name, buf, sizeof buf, pfile);

		switch(state) {
			case FLD:
			case FLDEOF:
			case FLDPLUS:
				if (uleq(name, "subject") || uleq(name, "title")) {
					subjp = add(buf, subjp);
				} else {
					if (uleq(name, "to") ||
						uleq(name, "newsgroup") ||
						uleq(name, "newsgroups")) {
							newsgroup = add(buf, newsgroup);
					} else {
						if (uleq(name, "followup-to")) {
							follow = add(buf, follow);
						} else {
							fprintf(stderr, "%s: unrecognized field %s\n",
								myname, name);
							retcode = 2;
							goto leave;
						}
					}
				}
				break;

			case BODY:
			case BODYEOF:

				if (!firstbody++) {
					if (subjp != 0 && strlen(subjp) > MAXSUBJ) {
						fprintf(stderr, "%s: subject field too long\n", myname);
						retcode = 4;
						goto leave;
					}
				}

				fputs(buf, tfile);
				break;

			case FILEEOF:
				goto process;

			case LENERR:
			case FMTERR:
				fprintf(stderr, "%s: ??Message Format Error ", myname);
				fprintf(stderr, "in component #%d.\n", compnum);
				retcode = 6;
				goto leave;
		}
	}

process:

	fclose(tfile);
	fclose(pfile);
	m_update();
	fflush(stdout);

	if (follow) {
		for (p = follow; *p; p++) {
			if (*p == '\n') *p = ' ';
		}
	}
	for (p=subjp; *p; p++) {
		if (*p == '\n') *p = ' ';
	}
 
	if (!newsgroup) {
		newsgroup = DEFAULTGROUP;
	}

	for(p=newsgroup; *p; p++) {
		if (*p == ' ' || *p == '\t' || *p == '\n') {
			*p = '\0';
		}
	}
	while (*newsgroup++ == '\0');
	--newsgroup;
 
/************
 *
 * This code no longer needed - mortals can't create newsgroups
 *
 *	sprintf(tmp, "%s/%s", NEWSDIR, newsgroup);
 *
 *	if (stat(tmp, &statb) < 0) {
 *		sprintf(yatmp, "Create new newsgroup '%s'? ", newsgroup);
 *		if(gans(yatmp, any) == 0) {
 *			goto leave;
 *		}
 *	}
 *	if (strlen(newsgroup) < 2) {
 *		fprintf(stderr, "%s: newsgroup name '%s' invalid\n",
 *			myname, newsgroup);
 *		goto leave;
 *	}
 */
	
	if (debug) {
		sprintf(tmp,"inews -F \"%s\" -t \"%s\" -n %s < %s\n\0",follow,subjp, newsgroup, tmpname);
		printf("command line: ");/*DBG*/
		printf("%s", tmp);/*DBG*/
	}


	if ((pid = fork()) == 0) {

		for (i = 3; i < 15; i++) close(i);	/* close spurious fd's */

		close(0);	/* tmpfile comes in on stdin */

		if(open(tmpname, 0) < 0) {
			fprintf(stderr, "%s: can't open tmp file\n", myname);
			done(-1);
		}

		if (follow) {
			execlp(newsproc, newsproc, "-F", follow, "-t", subjp, "-n", newsgroup, 0);
		} else {
				execlp(newsproc, newsproc, "-t", subjp, "-n", newsgroup, 0);
		}
		fprintf(stderr, "%s: can't exec %s\n", myname, newsproc);
		perror(newsproc);
		done(-1);

	} else if (pid == -1) {
		fprintf(stderr, "%s: Can't fork.\n", myname);
		retcode = 7;
		goto leave;
	} else {
		int (*istat)(), (*qstat)();

		istat = signal(SIGINT, SIG_IGN);
		qstat = signal(SIGQUIT, SIG_IGN);
		while ((wpid = wait(&status)) != -1 && wpid != pid) ;
		signal(SIGINT, istat);
		signal(SIGQUIT, qstat);
	}

	if (status == 0) {
		fprintf(stderr, "[%s to %s]\n",
				myname[0] == 's' ? "submitted" : "posted",
				newsgroup);
		retcode = 0;
	} else {
		retcode = 8;
		goto leave;
	}

suceess:
	retcode = 0;
	backup(pathname);
leave:
	if (pfile) fclose(pfile);
	if (tfile) fclose(tfile);
	if (tmpname) unlink(tmpname);

	return(retcode);
}



backup(file)
char *file;
{
	char buf[128];
	register char *cp;

	buf[0] = 0;
	if(cp = rindex(file, '/'))
		sprintf(buf, "%.*s", (++cp)-file, file);
	else
		cp = file;
	strcat(buf, ",");
	strcat(buf, cp);
	unlink(buf);
	if(link(file, buf) < 0 || unlink(file) < 0) {
		fprintf(stderr, "Send: Backup rename failure ");
		perror(buf);
		done(1);
	}
}


#########################
# additions to makefile #
#########################

[You will have to substitute the locations of your MH libraries]
[Submit also uses 'mh.h' out of the current directory - deal with that]

submit: submit.o
	$(CC) $(CFLAGS) -DSPOOLDIR=\"$(SPOOLDIR) -DLIBDIR=\"$(LIBDIR)\
	submit submit.o /usr1/src/cmd/mh/subs.a /usr1/src/cmd/mh/strings.a -lc \
	-o submit



More information about the Comp.sources.unix mailing list