ftp.nice.ch/pub/next/unix/communication/xc.s.tar.gz#/xc/xcterm.c

This is xcterm.c in view mode; [Download] [Up]

/*	xcterm.c -- terminal mode module for XC
	This file uses 4-character tabstops
*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <signal.h>
#include <setjmp.h>
#if defined(NEXT)
#include <termios.h>
#else
#include <termio.h>
#endif
#include "xc.h"

char captfile[SM_BUFF] = CAPTFILE,	/* capture file's name */
	 phonefile[SM_BUFF] = PHFILE,	/* phone number file's name */
	 ddsname[SM_BUFF];
FILE	*cfp;				/* capture file pointer */
static FILE	*fp;			/* file to transmit */
static pid_t child_pid;		/* ID of child process */
static jmp_buf rtm, stop;
static RETSIGTYPE (*oldvec)();
short	s_flag, capture = FALSE;
extern short autoflag, nl2cr;
extern get_bound_char();

/*  start capturing */
static RETSIGTYPE 
capt_on(junk)
int junk;
{
	if (capture)
		sprintf(Msg, "Already capturing to \"%s\"", captfile);
	else {
		if (!(cfp = fopen(captfile, "a")))
			sprintf(Msg,"Can't open \"%s\" for capturing",captfile);
		else
			capture = TRUE,
			sprintf(Msg,"Capturing to \"%s\"",captfile),
			setbuf(cfp, NIL(char));
	}
	S2(Msg);

	signal(SIGUSR1, capt_on);	/* set signal for next capt_on */
}

/*  stop capturing */
static RETSIGTYPE 
capt_off(junk)
int junk;
{
	if (!capture)
		sprintf(Msg,"Sorry, we haven't been capturing lately");
	else
		fclose(cfp),
		capture = FALSE,
		sprintf(Msg,"\"%s\" closed for capturing",captfile);

	S2(Msg);

	signal(SIGUSR2, capt_off);	/* set signal for next capt_off */
}

/*	cleanup, flush and exit */
static RETSIGTYPE 
cleanup(junk)
int junk;
{
	if (capture)
		fclose(cfp),
		sprintf(Msg,"\"%s\" closed for capturing",captfile),
		S2(Msg);

	exit(0);
}

static RETSIGTYPE 
cisbmode(junk)
int junk;
{
	cismode = 2;
	signal(SIGCLD, SIG_IGN);
	longjmp(rtm,1);
}

static void 
end_divert(junk)
int junk;
{
	show_abort();
	fclose(fp);
	signal(SIGINT, oldvec);
	longjmp(stop,1);
}

/*	Divert file into input stream, with delay after each newline. */
void 
divert(script)
short script;
{
	int c;
	long i = 1;

	if (!script)
		fputc('\r',tfp),
		fputc('\n',tfp),
		show(-1,"File?"),
		getline(),
		getword();

	if (word[0] == '\0')
		return;

	if (!(fp = fopen(word, "r"))){
		sprintf(Msg,"Can't access '%s'",word);
		S2(Msg);
		return;
	}

	oldvec = signal(SIGINT,end_divert);
	if (setjmp(stop))
		return;

	while ((c = getc(fp)) != EOF){
		if (c != '\n')
			sendbyte(c),
			i++;
		else {
			sendbyte(nl2cr ? '\r' : '\n');
			/*i = (CBAUD-cbaud)*80 + 4*i + 50; /* season to taste... */
			i *= 3;
			if (script)
				k_waitfor(-i, "");
			else
				msecs(i);
			i = 1;
		}
	}
	fclose(fp);
	signal(SIGINT,oldvec);
}

/*	Select a script file. */
static 
get_script()
{
	fputc('\r',tfp),
	fputc('\n',tfp);
	show(-1,"Enter script file:");
	fputc(' ',tfp);
	getline();
	if (line[0] == '\0'){
		fputc('\r',tfp),
		fputc('\n',tfp);
		S1("Script file not specified");
		return FAILURE;
	}
	linkflag = FALSE;
	getword();
	sprintf(ddsname,"%s",word);
	return SUCCESS;
}

void 
terminal(todir)
short todir;
{
	register c;
	short doneyet_dd = FALSE;


Reterm:
	if (setjmp(rtm) || doneyet_dd)
		return;

	mode(NEWMODE);
	s_flag = FALSE;		/* reset scripting flag */

	if (!todir)
		sprintf(Msg, "Entering TERMINAL mode - Escape character is '%s'",
#if defined(NEXT)		
					   xc_unctrl(my_escape)),
#else
					   unctrl(my_escape)),
#endif
		S2(Msg);

	/* split into read and write processes */
	if ((child_pid = forkem()) == 0){
		/* child, read proc: read from port and write to tty */
		cfp = NIL(FILE);
		if (autoflag && !todir)
			capt_on(0);
		signal(SIGUSR1, capt_on);
		signal(SIGUSR2, capt_off);
		signal(SIGTERM, cleanup);

		while (1){
			while ((c = readbyte(0)) == -1)
				;
			if (cismode && c == ENQ)
				cleanup(0);

			fputc(c,tfp);

			if (capture && c != '\r')
				fputc(c,cfp);
		}
		/*NOTREACHED*/
	}
	/* parent, write proc: read from tty and write to port */
	if (cismode)
		signal(SIGCLD, cisbmode);

	if (todir)
		goto dialdir;
	do {
		switch (c = get_bound_char()){
		case CAPTYES:		/* signal child to open capture file */
			kill(child_pid, SIGUSR1);
			break;

		case CAPTEND:		/* signal child to close capture file */
			kill(child_pid, SIGUSR2);
			break;

		case DIVCHAR:		/* divert a file through modem port */
			mode(SIGMODE);
			divert(FALSE);
			mode(NEWMODE);
			break;
	
		case BRKCHAR:
			xmitbrk();
			break;

		case HLPCHAR:
			show_bindings();
			break;

		case SCRPCHR:		/* execute a script file */
			if (get_script()==FAILURE)
				break;

			/* fall through...  */

		case DOSCRPT:		/* named script file */
			s_flag = TRUE;
			goto filicide;

		case DIALCHR:		/* select and dial a phone number */
dialdir:
			doneyet_dd = TRUE;
			if ((dial_dir()==FAILURE && todir) || s_flag)
				goto filicide;
			break;

		case ENDCHAR:		/* signal child to cleanup and exit */
filicide:
			c = ENDCHAR;
			signal(SIGCLD, SIG_IGN);
			kill(child_pid, SIGTERM);
			break;
		
		case QUITCHR:
			signal(SIGCLD, SIG_IGN);
			kill(child_pid, SIGTERM);
			s_exit();
			break;

		case HUPCHAR:		/* Hangup */
			hangup();
			break;

		case '\n':		/* See if NL translation in effect */
			if (nl2cr)
				c = '\r';

		default:	/* just send the character to the port */
			sendbyte(c);
			break;
		}
		todir = FALSE;
	} while (c != ENDCHAR);

	while (wait(NIL(int)) >= 0)	/* wait for the read process to die */
		;

	if (s_flag){
		mode(SIGMODE);
		do_script(ddsname);
		goto Reterm;
	}

	reterm = FALSE;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.