SRI-NOSC/mh/prompter.c

Compare this file to the similar file:
Show the results in this format:

#include "mh.h"
#include "iobuf.h"
#include "errors.h"
#include "sgtty.h"
#include "signals.h"

/*#define CEDIT 01 */	/* use following editing chars */
#define CKILL   006     /* @ => <CLOSE>         */
#define CERASE  001      /* # => <CTRL A>        */

/*define EDIT   001*/	/* edit after filling in fields */
char    sysed[];

int     fout;
struct  iobuf in, out;
struct  sgtty sg;
struct swit switches[] {
	"editor editor",  0,      /* 0 */
	"erase chr",      2,      /* 1 */
	"kill chr",       0,      /* 2 */
	"help",           4,      /* 3 */
	0,                0
};


main(argc, argv)
char *argv[];
{
	char tmpfil[32], *drft, name[NAMESZ], field[512], *ed;
	int exitstat;
	char skill, serase;
	char *killp, *erasep;
	register int i, state;
	register char *cp;
	char *ap;
	char *arguments[50], **argp;
	int sig();
	int status, pid, wpid, intr;

	fout = dup(1);
	skill = exitstat = 0;
	ap = cp = argv[0];
	while(*cp)
		if(*cp++ == '/')
			ap = cp;
	if((cp = m_find(ap)) != -1) {
		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 badleave;
							/* unknown */
			case -1:printf("prompter: -%s unknown\n", cp);
				goto badleave;
			case 0: if(!(ed = *argp++)) {   /* -editor */
      missing:  printf("prompter: Missing argument for %s switch\n", argp[-2]);
					goto badleave;
				}
				continue;
			case 1: if(!(erasep = *argp++))     /* -erase */
					goto missing;
				continue;
			case 2: if(!(killp= *argp++))      /* -kill */
					goto missing;
				continue;
			case 3: help("prompter    [file]  [switches]",
				     switches);
				goto badleave;
			}
		else
			drft = cp;
	if(!drft) {
		printf("prompter: missing skeleton\n");
		goto badleave;
	}
	if(fopen(drft, &in) == -1) {
		printf("Can't open %s\n", drft);
		goto badleave;
	}
	copy(makename("prmt", ".tmp"), copy("/tmp/", tmpfil));
	if(fcreat(tmpfil, &out) == -1) {
		printf("Can't create %s\n", tmpfil);
		goto badleave;
	}
	chmod(tmpfil, 0700);
	signal(SIGINT, &sig);
	gtty(0, &sg);
	skill = sg.sg_kill;
	serase = sg.sg_erase;
#ifdef CEDIT
	sg.sg_kill =    killp ?  chrcnv(killp) : CKILL;
	sg.sg_erase =   erasep ? chrcnv(erasep) : CERASE;
#else
	sg.sg_kill =    killp ?  chrcnv(killp) : skill;
	sg.sg_erase =   erasep ? chrcnv(erasep) : serase;
#endif
	stty(0, &sg);
	if ( skill != sg.sg_kill || serase != sg.sg_erase ) {
		printf("Erase Char="); chrdisp(sg.sg_erase);
		printf("; Kill Line="); chrdisp(sg.sg_kill);
		printf(".\n"); flush();
	}

	state = FLD;
	for(;;) switch(state = m_getfld(state,name,field,sizeof field,&in)) {

	case FLD:
	case FLDEOF:
	case FLDPLUS:
		if(field[0] != '\n' || field[1] != 0) {
			printf("%s:%s", name, field);
			puts(name, &out);
			putc(':', &out);
			puts(field, &out);
			while(state == FLDPLUS) {
				state=m_getfld(state,name,field,sizeof field,&in);
				printf("%s", field);
				puts(field, &out);
			}
		} else {
			printf("%s: ", name);
			flush();
			i = getln(&field);
			if(i == -1)
				goto badleave;
			if(i == 0 && (field[0] == '\n' || !field[0]))
				continue;
			puts(name, &out); putc(':', &out);
			do {
				if(field[0] != ' ' && field[0] != '\t')
					putc(' ', &out);
				puts(field, &out);
			} while(i == 1 && (i = getln(&field)) >= 0);
			if(i == -1)
				goto badleave;
		}
		field[0] = 0;
		if(state == FLDEOF)
			goto body;
		continue;

	case BODY:
	case BODYEOF:
	case FILEEOF:
  body:         puts("--------\n", &out);
		printf("--------\n");
		if(field[0]) {
			do {
				puts(field, &out);
				/*printf("%s", field);*/
			} while(state == BODY &&
				(state=m_getfld(state,name,field,sizeof field,&in)));
		}
		flush();
		for(;;) {
			i = getln(&field);
			if (i == -1) goto badleave; /**/
			if(field[0] == 0)
				break;
			puts(field, &out);
		}
		goto done;

	default:
		printf("Bad format file!\n");
		goto badleave;
	}


done:
	printf("--------\n"); flush();
	fflush(&out);
	close(out.b_fildes);
	fopen(tmpfil, &out);
	close(in.b_fildes);
	fcreat(drft, &in);              /* Truncate prior to copy back */
	do
		if((i = read(out.b_fildes, field, sizeof field)) > 0)
			write(in.b_fildes, field, i);
	while(i == sizeof field);
	close(in.b_fildes);
	close(out.b_fildes);
	unlink(tmpfil);
again:
	if(skill) {
		sg.sg_kill = skill;
		sg.sg_erase = serase;
		stty(0, &sg);
		skill = 0;
	}

#ifdef EDIT
	printf("Edit? ");
	flush();
	getln(&field);
	if(field[0] == 0)
		goto badleave;
	field[length(field) - 1] = 0;   /* zap <lf> */
	if(field[0] == 0) {
		printf("Options are:\n  no\n  yes\n  show\n  <any editor>\n");
		goto again;
	}
	if(ssequal(field, "no"))
		goto leave;
	if(ssequal(field, "show")) {
		if(showfile(drft))
			goto badleave;
		goto again;
	}
	if(ssequal(field, "yes")) {
		if(!ed &&
		   ((ed = m_find("editor")) == -1 ||  equal(invo_name(), ed)))
			ed = sysed;
	} else
		ed = field;
	intr = signal(SIGINT, 1);
	if((pid = fork()) == 0) {
	    /*  m_update();  */
		flush();
		execlsrh(ed, drft, 0);
		exit(-1);               /* can't exec editor */
	} else if(pid == -1) {
		printf("prompter: no forks!\n");
		goto leave;
	} else
		while((wpid = waita(&status)) != -1 && wpid != pid) ;
	if((status & 0177400) == 0177400) goto again;   /* -1 */
	signal(SIGINT, intr);
#endif
	goto leave;

badleave:
	exitstat = 1;
leave:
	m_update();
	flush();
	if(skill) {
		sg.sg_kill = skill;
		sg.sg_erase = serase;
		stty(0, &sg);
	}
	exit(exitstat);
}




getln(buf)
char *buf;
{
	register char *cp;
	register int c;

	cp = buf;
	*cp = 0;
	for(;;) {
		c = getchar();
		if(c == 0)
			if(errno == EINTR)
				return(-1);
			else
				return(0);
		if(c == '\n') {
			if ( cp != buf ) /* if not first char in line */
				if(cp[-1] == '\\') {
					cp[-1] = c;
					return(1);
				}
				if((buf==&(cp[-1]))&&(cp[-1] == '.')) {
					buf[0] = 0;
					return(0);
				}
				*cp++ = c;
				*cp   = 0;
				return(0);
		}
		if(cp < buf + 500)
			*cp++ = c;
		*cp = 0;
	}
}


sig()
{
	signal(SIGINT, &sig);
	return;
}


chrcnv(str)
{
	register char *cp;
	register int c;

	cp = str;
	if((c = *cp++) != '\\')
		return(c);
	c = 0;
	while(*cp && *cp != '\n') {
		c =* 8;
		c =+ *cp++ - '0';
	}
	return c;
}


chrdisp(chr)
{
	register int c;

	c = chr;
	if(c < ' ')
		printf("<CTRL-%c>", c + '@');
	else
		printf("%c", c);
}