[comp.sources.misc] v16i026: ECU async comm package rev 3.0, Part02/35

wht@n4hgf.uucp (Warren Tucker) (01/06/91)

Submitted-by: wht@n4hgf.uucp (Warren Tucker)
Posting-number: Volume 16, Issue 26
Archive-name: ecu3/part02

---- Cut Here and feed the following to sh ----
#!/bin/sh
# This is part 02 of ecu3
if touch 2>&1 | fgrep 'amc' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= ecu.c ==============
echo 'x - extracting ecu.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ecu.c' &&
X/*+-----------------------------------------------------------------------
X	ecu.c - Extended Calling Unit/Call Utility/Call UNIX/whatever
X	wht@n4hgf.Mt-Park.GA.US
X
X  Defined functions:
X	main(argc,argv,envp)
X	xmtr()
X
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:11-30-1990-19:04-wht@n4hgf-new ttyinit parameter - see TTYINIT_... */
X/*:11-28-1990-15:58-wht@n4hgf-add non-ansi terminal support */
X/*:08-14-1990-20:39-wht@n4hgf-ecu3.00-flush old edit history */
X
X#define DECLARE_LINEVARS_PUBLIC
X#include "ecu.h"
X#include "esd.h"
X#include "proc.h"
X#include "ecukey.h"
X#include "ecuxkey.h"
X#include "ecuhangup.h"
X#include "patchlevel.h"
X#undef NULL
X#include <sys/param.h>
X
Xchar *getenv();
X
Xextern char *makedate;			/* temporary make date */
Xextern char *numeric_revision;	/* ecunumrev.c */
Xextern char *revision_modifier; /* ecunumrev.c */
Xextern ESD *icmd_prompt;
Xextern char kbdeof;			/* current input EOF */
Xextern char kbdeol2;		/* current secondary input EOL */
Xextern char kbdeol;			/* current input EOL */
Xextern char kbderase;		/* current input ERASE */
Xextern char kbdintr;		/* current input INTR */
Xextern char kbdkill;		/* current input KILL */
Xextern char kbdquit;		/* current input QUIT */
Xextern char kbd_is_7bit;	/* keyboard has parity */
Xextern uint tcap_LINES;
Xextern uint tcap_COLS;
Xextern ulong colors_current;
Xextern int there_is_hdb_on_this_machine;
Xextern int tty_not_char_special;
Xextern int tty_is_ansi;
Xextern int tty_is_multiscreen;
Xextern char lopen_err_str[];
X
Xchar curr_dir[258];		/* current working directory of process */
Xchar hello_str[80];		/* msg printed upon BOJ */
Xchar errmsg[128];
Xchar modem_ctl_fname[128];
Xchar initial_procedure[128] = "";
Xint init_proc_argc = 0;
Xchar *init_proc_argv[MAX_PARGV];
Xint quiet = 0;			/* don't shut up is default */
Xint rcvr_pid = -1;		/* pid for rcvr process (-1 == no proc active) */
X	/* ... -2 == special flag for modem control/timed-read procedures */
Xint xmtr_pid = 0;
Xint quit_on_init_proc_fail = 0;
Xint quit_on_init_proc_done = 0;
Xint hz;
Xstruct timeb starting_timeb;
X
X/*-----------------------*/
Xint nice_value = 3;		/* go for hi priority */
Xushort geteuid();
Xushort getuid();
Xushort euid;
Xushort uid;
X/*-----------------------*/
X
X/*+-----------------------------------------------------------------------
X	xmtr() --  copy stdin to comm line
X
X  THE INITIAL PROCESS EXECUTES THIS PROCESS UNTIL PROGRAM TERMINATION
X
X  TTY input lines beginning with % have special significance
X  (see ecuicmd.c)
X------------------------------------------------------------------------*/
Xint
Xxmtr()
X{
Xuchar xmtr_char;
Xuchar nlchar = NL;
Xvoid xmtr_SIGINT_handler();
X
X	ttymode(1);
X	xmtr_signals();
X	while(1)
X	{
X/* bug somewhere ... may be SIGINT too rapidly causing SIG_IGN ????? */
X		signal(SIGINT,xmtr_SIGINT_handler);	/* so make sure */
X		xmtr_char = ttygetc(1);
X
X		if(xmtr_char & 0x80)
X		{
X			kbd_escape(xmtr_char);
X			continue;
X		}
X
X		lputc(xmtr_char);
X		if(shm->Lfull_duplex == 0)		/* echo character if asked */
X			write(TTYERR,&xmtr_char,1);
X
X		if(xmtr_char == CR)
X		{
X			if(shm->Ladd_nl_outgoing)
X				lputc('\n');
X			if(shm->Lfull_duplex == 0)
X				write(TTYERR,&nlchar,1);
X		}
X	}		/* end of while we can read a character */
X	return(HANGUP_XMTR_LOGIC_ERROR);	/* should not have gotten here */
X
X}	/* end of xmtr */
X
X/*+-------------------------------------------------------------------------
X	main(argc,argv,envp)
X
X  main() program forks to create rcvr process; then main()
X  becomes the xmtr process
X------------------------------------------------------------------------*/
Xmain(argc,argv,envp)
Xint argc;
Xchar **argv;
Xchar **envp;
X{
Xint swchar;
Xint itmp;
Xulong colors_save;
Xchar *get_ttyname();
Xextern char *optarg;
Xextern int optind;
X
X	ftime(&starting_timeb);	/* get startup time */
X	xmtr_pid = getpid();
X
X#ifdef MALLOC_3X
X	(void)mallopt(M_MXFAST,256+4);
X	(void)mallopt(M_NLBLKS,64);
X	(void)mallopt(M_GRAIN,sizeof(ESD) + 8);
X#endif
X
X	if(!getenv("HZ"))
X		hz = atoi(getenv("HZ"));
X	else
X		hz = HZ;
X
X	setbuf(stderr,NULL);
X
X/* get this off quick, cause we'll be busy for a little while on 286 */
X	sprintf(hello_str,"ecu %s.%02d%s (pid %d) by wht@n4hgf",
X		numeric_revision,PATCHLEVEL,revision_modifier,xmtr_pid);
X	ff(se,"%s\n",hello_str);
X
X/* if we are root (as we should be on 286 versions), nice to very bad
X   and set uid to real uid */
X
X	uid = getuid();
X	euid = geteuid();
X	if((euid == 0) || (uid == 0))	/* if root running or prog text ... */
X	{								/* ... sets to root, then grab gusto */
X	int old_nice = nice(0) + 20;
X		nice(-old_nice + nice_value);
X		if(uid != euid)					/* but if user not really root ... */
X		{
X			if(setuid(uid))			/* ... take away the privilege */
X			{
X				ff(se,"\r\n");
X				perror("setuid");
X				ff(se,"\r\n");
X				exit(-1);
X			}
X		}
X	}
X
X	shm_init();				/* open shared segment */
X
X	keyset_init();			/* intialize keyset */
X
X	make_ecu_subdir();		/* needs to be very early before lots of init */
X
X	xmtr_signals();			/* catch xmtr signals */
X
X	get_curr_dir(curr_dir,sizeof(curr_dir));
X	cd_array_init();		/* read %cd directory list */
X
X	hdb_init();
X
X	var_init();				/* initialize procedure variables */
X	poutput_init();			/* initialize procedure output */
X
X	icmd_prompt = make_esd(64);
X	set_default_escape_prompt();
X
X/* init line variables */
X	shm->Lline[0] = 0;				/* no line chosen yet */
X	shm->Liofd = -1;				/* no line open now */
X	shm->Lbaud = DEFAULT_BAUD_RATE;	/* see ecu.h */
X	shm->Lparity = DEFAULT_PARITY;	/* see ecu.h */
X	shm->Ltelno[0] = 0;				/* no telephone number for remote yet */
X	shm->Llogical[0] = 0;			/* no logical name for remote yet */
X	shm->Lrname[0] = 0;				/* no logical name for remote yet */
X	shm->Ldescr[0] = 0;				/* no description for remote yet */
X	shm->Lmodem_off_hook = 0;		/* assume modem on hook */
X	shm->Ladd_nl_incoming = 0;		/* dont add nl to incoming cr */
X	shm->Ladd_nl_outgoing = 0;		/* dont add nl to outgoing cr */
X	shm->Lfull_duplex = 1;			/* assume full duplex */
X	shm->Lmodem_already_init = 0;	/* modem has not been initialized */
X	shm->Lxonxoff = IXON | IXOFF;	/* default to xon/xoff protocol */
X	shm->xmtr_pid = getpid();
X	shm->xmtr_ppid = getppid();
X	shm->xmtr_pgrp = getpgrp(0);
X	strcpy(shm->tty_name,get_ttyname());
X	shm->shm_revision = SHM_REV;
X	shm->ttyinit_param = TTYINIT_NORMAL;
X
X	while((swchar = getopt(argc,argv,"c:p:l:b:hfdDteoAN")) != -1)
X	{
X		switch(swchar)
X		{
X			case 'b':
X				if(valid_baud_rate(shm->Lbaud = atoi(optarg)) < 0)
X				{
X					ff(se,"invalid baud rate %u\n",shm->Lbaud);
X					usage();
X				}
X				break;
X			case 'c':
X				strcpy(modem_ctl_fname,optarg);
X				break;
X			case 'l':
X				shm->Lline[0] = 0;
X				if(strncmp(optarg,"/dev/tty",8))
X					strcpy(shm->Lline,"/dev/tty");
X				strcat(shm->Lline,optarg);
X				break;
X			case 'p':
X				strcpy(initial_procedure,optarg);
X				break;
X			case 'h': shm->Lfull_duplex = 0; break;
X			case 'f': shm->Lfull_duplex = 1; break;
X			case 'd': quit_on_init_proc_fail = 1; break;
X			case 'D': quit_on_init_proc_done = 1; break;
X			case 't': shm->Ladd_nl_incoming = 1;
X					  shm->Ladd_nl_outgoing = 1; break;
X			case 'e': shm->Lparity = 'e'; break;
X			case 'o': shm->Lparity = 'o'; break;
X			case 'A': shm->ttyinit_param = TTYINIT_FORCE_ANSI; break;
X			case 'N': shm->ttyinit_param = TTYINIT_FORCE_NONANSI; break;
X			case '?': usage();
X		}
X	}
X
X/* check a few options for validity */
X	if(!initial_procedure[0] &&
X		(quit_on_init_proc_done || quit_on_init_proc_fail))
X	{
X		ff(se,"no -D/-d without -p\n");
X		usage();
X	}
X
X	ttyinit(shm->ttyinit_param);	/* init console tty mode handler */
X	ttymode(1);						/* put user console in `raw' mode */
X	tcap_clear_screen();
X	ff(se,"%s\r\n",hello_str);
X	if(kbd_is_7bit && !tty_not_char_special)
X	{
X		tcap_cursor(tcap_LINES - 3,0);
X		ff(se,
X	"No problem, but just to warn you, the keyboard has parity enabled\r\n");
X		ring_bell();
X		nap(1000L);
X	}
X
X/* check out line */
X	if(!shm->Lline[0])
X	{
X		if(!there_is_hdb_on_this_machine)
X			strcpy(shm->Lline,"/dev/tty1a");
X		else
X		{
X			choose_line(shm->Lbaud);
X			if(!shm->Lline[0])
X			{
X				ff(se,"\r\n\n");
X				tcap_stand_out();
X				ff(se,"[no available Devices line at %u baud]",shm->Lbaud);
X				tcap_stand_end();
X				ff(se,"\r\n");
X				strcpy(shm->Lline,"/dev/tty1a");
X				nap(1000L);
X			}
X		}
X	}
X
X/* either present startup screen or run initial procedure or both */
X	if(initial_procedure[0])
X	{
X		init_proc_argv[0] = initial_procedure;
X		init_proc_argc = 1;
X		for(itmp = optind; itmp < argc; itmp++)
X		{
X			if(*argv[itmp] != '-')
X			{
X				if(init_proc_argc == MAX_PARGV)
X				{
X					ff(se,"too many arguments to initial procedure\r\n");
X					hangup(HANGUP_USAGE);
X				}
X				init_proc_argv[init_proc_argc++] = argv[itmp];
X			}
X		}
X
X		if(tty_not_char_special)
X			quit_on_init_proc_done = 1;
X		else	/* rattle curses once - fixes quirk/bug I can't find */
X		{
X			windows_start();
X			windows_end2();
X			fflush(so);
X		}
X
X		ttymode(2);
X		if(do_proc(init_proc_argc,init_proc_argv))
X		{
X			if(quit_on_init_proc_fail || quit_on_init_proc_done)
X				hangup(HANGUP_INIT_PROC_ERROR);
X		}
X		proc_file_reset();
X		colors_save = colors_current;
X		setcolor(colors_notify);
X		fputs("[procedure finished]",se);
X		setcolor(colors_save);
X		ff(se,"\r\n");
X		if(quit_on_init_proc_done)
X			hangup(0);
X		if(shm->Liofd < 0)
X		{
X			ttymode(1);	
X			ff(se,"\r\n\n");
X			tcap_stand_out();
X			ff(se, "[no line attached by initial procedure]");
X			tcap_stand_end();
X			ff(se,"\r\n");
X			if(quit_on_init_proc_fail)
X				hangup(HANGUP_INIT_PROC_ERROR);
X			tcap_stand_out();
X			ff(se, "[press ESC to exit or SPACE for setup menu]");
X			tcap_stand_end();
X			itmp = ttygetc(0);
X			ff(se,"\r\n");
X			if(itmp == ESC)
X				hangup(1);
X			setup_screen((char *)0);
X		}
X		else
X		{
X			ttymode(1);
X			start_rcvr_process(0);
X		}
X	}
X	else		/* no initial procedure */
X	{
X		ttymode(1);	
X		setup_screen((optind < argc) ? argv[optind] : (char *)0);
X	}
X
X	/* enter xmtr operation */
X	hangup(xmtr());
X
X	/*NOTREACHED*/
X
X}	/* end of main */
X
X/* end of ecu.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 1226044490 'ecu.c' &&
chmod 0644 ecu.c ||
echo 'restore of ecu.c failed'
Wc_c="`wc -c < 'ecu.c'`"
test 9953 -eq "$Wc_c" ||
	echo 'ecu.c: original size 9953, current size' "$Wc_c"
# ============= ecuDCE.c ==============
echo 'x - extracting ecuDCE.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ecuDCE.c' &&
X/* #define USE_S7 */
X/*+-------------------------------------------------------------------------
X	ecuDCE.c - ECU DCE dialing and management
X	wht@n4hgf.Mt-Park.GA.US
X
X  Defined functions:
X	DCE_hangup()
X	DCE_autoanswer()
X	DCE_dial()
X	DCE_dial_pde(tpde)
X	DCE_get_result(msec_to_wait)
X	DCE_get_sreg_value(regnum)
X	DCE_modem_init()
X	DCE_now_on_hook()
X	DCE_read_modem_init()
X	DCE_redial(arg,argc)
X	DCE_report_iv_set(varnum)
X	DCE_send_cmd(cmd)
X	DCE_set_sreg(regnum,value)
X	ck_for_interrupt()
X	process_modem_init(str)
X	show_modem_init_error(erc,iesd)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include "ecu.h"
X#include "ecukey.h"
X#include "esd.h"
X#include "var.h"
X#include "ecupde.h"
X#include "ecuerror.h"
X#include "relop.h"
X
Xlong time();
X
Xchar *make_char_graphic();
Xvoid DCE_hangup();
X
Xextern int rcvr_pid;
Xextern int interrupt;
Xextern int proc_interrupt;
Xextern int proctrace;
Xextern ulong colors_current;
Xextern char kbdintr;
X
Xint mi_line;
Xchar mi_name[64];
X
X#define MI_MAX_LEN 65
Xchar Lmodem_init[MI_MAX_LEN] = "";		/* modem init string w/o trailing CR */
Xchar Lmodem_dial[MI_MAX_LEN] = "";		/* modem dialing prefix */
Xchar Lmodem_autoans[MI_MAX_LEN] = "";	/* modem autoanswer */
X
Xchar *interrupted_string = "!Interrupted";
X
X/*+-------------------------------------------------------------------------
X	ck_for_interrupt()
X--------------------------------------------------------------------------*/
Xck_for_interrupt()
X{
Xuint key;
X
X	while(rdchk(0))
X	{
X		if((uchar)(key = ttygetc(1)) == (uchar)kbdintr)
X		{
X			interrupt = 1;
X			return(1);
X		}
X	}
X	return(0);
X}	/* end of ck_for_interrupt */
X
X/*+-------------------------------------------------------------------------
X	show_modem_init_error(erc,iesd)
X--------------------------------------------------------------------------*/
Xvoid
Xshow_modem_init_error(erc,iesd)
Xint erc;
XESD *iesd;
X{
Xregister itmp;
X
X	pputs(mi_name);
X	pprintf(" line %d: ",mi_line);
X	proc_error(erc);
X	pputs(iesd->pb);
X	pputc(NL);
X	itmp = iesd->old_index;
X	while(itmp--)
X		pputc(' ');
X	pputs("^\n\n");
X
X}	/* end of show_modem_init_error */
X
X/*+-----------------------------------------------------------------------
X	process_modem_init(str)
X
Xsample /usr/lib/ecu/tty??.mi lines:
Xinit_9600:ATS11=47X4S0=0S7=30\Q0\X0\N0
Xinit_>2400:ATS11=47X4S0=0S7=30\Q0\X0\N0
Xinit_<=2400:ATS11=47X4S0=0S7=30\Q1\X1\N3
XATDT
X
Xreturn 0 if entire list read, else 1 if error (error msg in errmsg)
X------------------------------------------------------------------------*/
Xvoid
Xprocess_modem_init(str)
Xchar *str;
X{
X#define MI_INIT		1
X#define MI_DIAL		2
X#define MI_AUTOANS	3
Xint erc;
XESD sesd;
Xchar typestr[32];
Xint relop;
Xint truth = 0;
Xint type;
Xlong test_baud;
X
X	sesd.pb = str;
X	sesd.cb = strlen(str);
X	sesd.maxcb = strlen(str);
X	sesd.index = 0;
X	sesd.old_index = 0;
X
X	if(get_alpha_zstr(&sesd,typestr,sizeof(typestr)))
X	{
X		erc = eSyntaxError;
X		goto SHOW_ERROR;
X		return;
X	}
X	if(ulindex(typestr,"init_") == 0)
X		type = MI_INIT;
X	else if(ulindex(typestr,"dial_") == 0)
X		type = MI_DIAL;
X	else if(!strcmpi(typestr,"autoanswer"))
X		type = MI_AUTOANS;
X	else
X	{
X		erc = eSyntaxError;
X		goto SHOW_ERROR;
X	}
X
X/* test for default ... if none, check baud rate */
X	if(type == MI_AUTOANS)
X		truth = 1;
X	else if(ulindex(typestr,"_default") > 0)
X	{
X		truth = !( ((type == MI_INIT) && Lmodem_init[0]) ||
X			((type == MI_DIAL) && Lmodem_dial[0]));
X	}
X	else
X	{
X		/* get optional operator */
X		if(get_relop(&sesd,&relop))
X			relop = OP_EQ;
X		if(erc = gint_constant(&sesd,&test_baud))
X			goto SHOW_ERROR;
X		truth = test_truth_int((long)shm->Lbaud,relop,test_baud);
X	}
X
X/* if no match, skip this one */
X	if(!truth)
X		return;
X
X/* skip over colon */
X	if(erc = skip_colon(&sesd))
X		goto SHOW_ERROR;
X
X/* make sure init or dial string not empty or too long */
X	if((erc = skip_cmd_break(&sesd)) && (type != MI_AUTOANS))
X		goto SHOW_ERROR;
X
X	if((sesd.cb - sesd.index) > (MI_MAX_LEN - 1))
X	{
X		erc = eBufferTooSmall;
X		goto SHOW_ERROR;
X	}
X
X	erc = eDuplicateMatch;		/* in case of show error in switch */
X	switch(type)
X	{
X		case MI_INIT:
X			if(Lmodem_init[0])
X				goto SHOW_ERROR;
X			strcpy(Lmodem_init,sesd.pb + sesd.index);
X			break;
X
X		case MI_DIAL:
X			if(Lmodem_dial[0])
X				goto SHOW_ERROR;
X			strcpy(Lmodem_dial,sesd.pb + sesd.index);
X			break;
X
X		case MI_AUTOANS:
X			if(Lmodem_autoans[0])
X				goto SHOW_ERROR;
X			if(!sesd.cb)
X				strcpy(Lmodem_autoans,"!null!");
X			else
X				strcpy(Lmodem_autoans,sesd.pb + sesd.index);
X			break;
X			
X	}
X	return;		/* <<<<====== done */
X
XSHOW_ERROR:
X	show_modem_init_error(erc,&sesd);
X
X}	/* end of process_modem_init */
X
X/*+-----------------------------------------------------------------------
X	DCE_read_modem_init()
X0123456789
X/dev/ttyxx
X------------------------------------------------------------------------*/
Xvoid
XDCE_read_modem_init()
X{
Xchar *cptr;
Xregister FILE *fp_modem;
Xchar *skip_ld_break();
Xchar buffer[128];
X
X/* zap init information */
X	Lmodem_init[0] = 0;
X	Lmodem_dial[0] = 0;
X
X/* build filename */
X	sprintf(mi_name,"%s/%s.mi",ECULIBDIR,shm->Lline + 5);
X
X/* read modem initialization */
X	if(!(fp_modem = fopen(mi_name,"r")))
X		pperror(mi_name);
X	else
X	{
X		mi_line = 0;
X		while((!Lmodem_init[0] || !Lmodem_dial[0]) &&
X			fgets(buffer,sizeof(buffer),fp_modem))
X		{
X			mi_line++;
X			buffer[strlen(buffer) - 1] = 0;
X			cptr = skip_ld_break(buffer);
X			/* skip comments and null lines */
X			if(!strlen(cptr) || (*cptr == '#'))
X				continue;
X			process_modem_init(cptr);
X		}
X		fclose(fp_modem);
X	}
X
X/* default */
X	if(!Lmodem_init[0])
X	{
X		strcpy(Lmodem_init,"ATE1Q0V1");
X		pputs("modem init string not found (using default '");
X		pputs(Lmodem_init);
X		pputs("')\n");
X	}
X	if(!Lmodem_dial[0])
X	{
X		strcpy(Lmodem_dial,"ATDT");
X		pputs("modem dial string not found (using default '");
X		pputs(Lmodem_dial);
X		pputs("')\n");
X	}
X
X	if(!Lmodem_autoans[0])
X	{
X		strcpy(Lmodem_autoans,"ATQ1S0=1");
X#ifdef INUSE
X		pputs("modem autoanswer string not found (using default '");
X		pputs(Lmodem_autoans);
X		pputs("')\n");
X#endif
X	}
X	else if(!strcmp(Lmodem_autoans,"!null!"))
X		Lmodem_autoans[0] = 0;
X
X	if(proctrace > 1)
X	{
X		pprintf("init:       '%s'\n",Lmodem_init);
X		pprintf("dial:       '%s'\n",Lmodem_dial);
X		pprintf("autoanswer: '%s'\n",Lmodem_autoans);
X	}
X}	/* end of DCE_read_modem_init */
X
X/*+-------------------------------------------------------------------------
X	DCE_get_result(msec_to_wait)
Xreturn pointer to static buf containing result code
X--------------------------------------------------------------------------*/
Xchar *
XDCE_get_result(msec_to_wait)
Xlong msec_to_wait;
X{
Xstatic char s32[32];
XLRWT	lr;
X
X	interrupt = 0;
X	s32[0] = 0;
X	lr.to1 = msec_to_wait;
X	lr.to2 = 200L;
X	lr.raw_flag = 0x80; /* allow interrupts */
X	lr.buffer = s32;
X	lr.bufsize = sizeof(s32);
X	lr.delim = (char *)0;
X	lr.echo = 0;
X	lgets_timeout(&lr);
X	return(lr.buffer);
X
X/* reset any interrupt indication since we look at string */
X	interrupt = 0;
X
X}	/* end of DCE_get_result */
X
X/*+-------------------------------------------------------------------------
X	DCE_modem_init()
X--------------------------------------------------------------------------*/
XDCE_modem_init()
X{
Xregister itmp;
Xint retries = 0;
Xchar *cmd;
Xchar *cptr;
Xint old_ttymode = get_ttymode();
X
X	if(shm->Lmodem_already_init)
X		return(0);
X
X	interrupt = 0;
X	DCE_read_modem_init();
X
X	lputs_paced(0,"\b\b\b\b\b\b\b\b\b\r");
X	nap(200L);
X	lflush(0);
X
X	while(!shm->Lmodem_already_init)
X	{
XINIT_LOOP:
X		if(retries > 3)
X			goto ERROR_RETURN;
X
X		if(interrupt)
X			goto ERROR_RETURN;
X
X		if(retries)
X		{
X			ltoggle_dtr();
X			lputs_paced(0,"AT\r");
X			nap(400L);
X			lputs_paced(0,"ATQ0V1E1\r");
X			nap(400L);
X		}
X
X		lflush(0);
X		cmd = Lmodem_init;
X		itmp = 0;
X#ifdef NEUROTIC
X		while(*cmd)
X		{
X			lputc_paced(0,*cmd++);
X			if(++itmp < 2)
X				nap(40L);
X			if((itmp = lgetc_timeout(500L)) < 0)
X			{
X				if(interrupt)
X					goto ERROR_RETURN;
X				retries++;
X				goto INIT_LOOP;
X			}
X			pputc(itmp);
X		}
X#else
X		lputs(cmd);
X		pputs(cmd);
X#endif
X
X		pputc(NL);
X		lputc_paced(0,CR);
X
X		itmp = 0;
X		while(itmp != CR)
X		{
X			if((itmp = lgetc_timeout(500L)) < 0)
X			{
X				if(interrupt)
X					goto ERROR_RETURN;
X				pputs("missed expected carriage return\n");
X				retries++;
X				goto INIT_LOOP;
X			}
X		}
X
X		if(strcmp(cptr = DCE_get_result(1200L),"OK"))
X		{
X			if(!strcmp(cptr,interrupted_string))
X			{
X				interrupt = 1;
X				goto ERROR_RETURN;
X			}
X			pprintf("unexpected result: '%s'\n",cptr);
X			retries++;
X			continue;
X		}
X		shm->Lmodem_already_init = 1;
X	}
X
X	ttymode(old_ttymode);
X	return(0);
X
XERROR_RETURN:
X	ttymode(old_ttymode);
X	return(-1);
X
X}	/* end of DCE_modem_init */
X
X/*+-------------------------------------------------------------------------
X	DCE_send_cmd(cmd)
X--------------------------------------------------------------------------*/
Xint
XDCE_send_cmd(cmd)
Xregister char *cmd;
X{
Xregister itmp;
X
X	DCE_modem_init();
X	nap(600L);
X
X	lflush(0);
X#ifdef NEUROTIC
X	while(*cmd)
X	{
X		lputc_paced(20,*cmd++);
X		if(++char_count < 2)
X			nap(40L);
X		if((itmp = lgetc_timeout(500L)) < 0)
X			return(-1);
X		pputc(itmp);
X	}
X#else
X	lputs(cmd);
X	pputs(cmd);
X#endif
X	pputc(NL);
X	lputc_paced(20,CR);
X	itmp = 0;
X	if(ck_for_interrupt())
X		return(-1);
X	while(itmp != CR)
X	{
X		if((itmp = lgetc_timeout(500L)) < 0)
X		{
X			pputs("missed expected carriage return\n");
X			return(-1);
X		}
X		if(ck_for_interrupt())
X			return(-1);
X	}
X	return(0);
X
X}	/* end of DCE_send_cmd */
X
X/*+-------------------------------------------------------------------------
X	DCE_report_iv_set(varnum)
X--------------------------------------------------------------------------*/
Xvoid
XDCE_report_iv_set(varnum)
Xint varnum;
X{
X
X	if(proctrace)
X		pprintf("modem handler set $i%02d = %ld\n",varnum,iv[varnum]);
X}	/* end of DCE_report_iv_set */
X
X/*+-----------------------------------------------------------------------
X	DCE_dial() - dial a remote or connect
X
X  returns 0 on success (CONNECT),
X          eConnectFailed if failure
X          eCONINT on interrupt
X
X  sets I0 to 0==connect,
X             1==failed to connect,
X             2==interrupted
X             3==modem error
X  sets S0 to modem result code or uucp status code string
X
X  This function has gotten quite NASTY and needs rewriting!
X------------------------------------------------------------------------*/
Xint
XDCE_dial()
X{
Xchar s128[128];
Xint rcvr_was_alive = (rcvr_pid > 0) || (rcvr_pid == -2);
Xint itmp;
Xint erc;
Xint s7;
Xchar *result = "";
Xulong colors_at_entry = colors_current;
Xchar s64[64];
X#ifdef WHT	/* hack for immediate need ... make a real feature later */
Xchar *cptr;
XFILE *fp;
Xchar credit_file[128];
X#endif
Xextern char kbdintr;		/* current input INTR */
X
X	if(rcvr_was_alive && (rcvr_pid != -2))
X	{
X		kill_rcvr_process(SIGUSR1);
X		nap(500L);
X	}
X
X	if(shm->Ldescr[0])
X	{
X		setcolor(colors_success);
X		get_tod(1,s64);
X		pprintf("%s %s on %s at %u baud (%s)\n",
X			(shm->Ltelno[0]) ? "Dialing" : "Connecting to",
X			shm->Ldescr,shm->Lline,shm->Lbaud,s64);
X	}
X
X	setcolor(colors_alert);
X	shm->Lmodem_off_hook = 0;
X
X	if(!shm->Ltelno[0])	/* if no phone number, direct connect */
X	{
X		sprintf(s128,"CONNECT %u",shm->Lbaud);
X		result = s128;
X		iv[0] = 0;
X		erc = 0;
X		goto START_RCVR_PROCESS;
X	}
X 	else
X	{
X		itmp = hdb_dial(&result);
X		lreset_ksr();	/* dialer may have changed parity */
X		switch(itmp)
X		{
X			case 0:		/* success */
X				goto CONNECTED;
X			case 1:		/* failure -- iv[0] set by hdb_dial */
X				DCE_report_iv_set(0);
X				erc = eConnectFailed;
X				goto START_RCVR_PROCESS;
X			case 2:		/* interrupted -- iv[0] set by hdb_dial */
X				DCE_report_iv_set(0);
X				erc = eCONINT;
X				goto START_RCVR_PROCESS;
X			case 3:		/* modem error */
X				setcolor(colors_error);
X				pprintf("%s\n",result);
X				goto CANNOT_TALK_TO_MODEM;
X			case 4:		/* try local */
X				break;
X		}
X
X		DCE_modem_init();
X
X#if defined(USE_S7)
X		if((s7 = DCE_get_sreg_value(7)) < 0)
X			s7 = 30;
X#else
X		s7 = 30;
X#endif
X
X		/* build and send dial command */
X		strcpy(s128,Lmodem_dial);
X		strcat(s128,shm->Ltelno);
X#ifdef WHT	/* hack for immediate need ... make a real feature later */
X		if(*(cptr = s128 + strlen(s128) - 1) == '$')
X		{
X			*cptr = 0;
X			get_home_dir(credit_file);
X			strcat(credit_file,"/.ecu/.credit");
X			if(fp = fopen(credit_file,"r"))
X			{
X				*cptr++ = ',';
X				*cptr++ = ',';
X				*cptr++ = ',';
X				*cptr++ = ',';
X				*cptr = 0;
X				fgets(cptr,30,fp);
X				fclose(fp);
X			}
X			if(!fp || !(*cptr))
X			{
X				result = "credit card error";
X				goto CONNECT_FAILED;
X			}
X			*(cptr + strlen(cptr) - 1) = 0; /* kill NL */
X		}
X#endif /* WHT */
X
X		if(ck_for_interrupt())
X			goto SEND_CMD_ERROR;
X
X		if(DCE_send_cmd(s128))
X			goto SEND_CMD_ERROR;
X
X		/* some modems (ahem, the Hayes 2400) do not accurately honor S7
X		so our timer is twice sreg 7 */
X 		pprintf("Type %s to abort ... ",make_char_graphic(kbdintr,1));
X		lflush(0);
X		result = DCE_get_result(s7 * 2 * 1000L);
X
X		if(!strcmp(result,interrupted_string))
X		{
X			setcolor(colors_error);
X			pprintf("%s\n",result);
X			lputc(0);				/* make modem go on hook */
X			nap(40L);
X			lputc(0);
X			interrupt = 0;
X			DCE_get_result(2000L);	/* wait for NO CARRIER */
X			erc = eCONINT;
X			iv[0] = 2;
X			DCE_report_iv_set(0);
X			goto START_RCVR_PROCESS;
X		}
X		if(!strncmp(result,"CONNECT",7))
X		{
X			if(strlen(result) > 7)
X			{
X				if(shm->Lbaud != (unsigned)atoi(result + 7))
X				{
X					setcolor(colors_error);
X					pprintf("%s (incorrect rate)\n",result);
X					iv[0] = 2;
X					DCE_report_iv_set(0);
X					goto START_RCVR_PROCESS;
X				}
X			}
XCONNECTED:
X			setcolor(colors_success);
X			pprintf("%s\n",result);
X			sprintf(s128,"CONNECT %s (%s) %u baud",
X				shm->Llogical,shm->Ltelno,shm->Lbaud);
X			strcpy(shm->Lrname,shm->Llogical);
X			ecu_log_event(getpid(),s128);
X			if(isalpha(shm->Llogical[0]))
X				if(keyset_read(shm->Llogical) != 0)
X					keyset_init();
X			shmx_connect();
X			shm->xmit_chars_this_connect = 0L;
X			shm->Loff_hook_time = time((long *)0);
X			iv[0] = 0;
X			DCE_report_iv_set(0);
X			erc = 0;
X			shm->Lmodem_off_hook = 1;
X			goto START_RCVR_PROCESS;
X		}
X		setcolor(colors_error);
XCONNECT_FAILED:
X		pprintf("%s\n",result);
X		iv[0] = 1;
X		DCE_report_iv_set(0);
X		erc = eConnectFailed;
X		goto START_RCVR_PROCESS;
X	}
X
X	shm->Lmodem_off_hook = 1;
X
XSTART_RCVR_PROCESS:	;
X	setcolor(colors_at_entry);
X	strcpy(sv[0]->pb,result);
X	sv[0]->cb = strlen(result);
X	if(rcvr_was_alive)
X		start_rcvr_process(1);
X	return(erc);
X
XSEND_CMD_ERROR: ;
X	if(interrupt || proc_interrupt)
X	{
X		result = interrupted_string;
X		iv[0] = 2;
X		DCE_report_iv_set(0);
X		erc = eCONINT;
X	}
X	else
X	{
XCANNOT_TALK_TO_MODEM:
X		setcolor(colors_error);
X		pprintf("Cannot talk to modem\n");
X		result = "!Modem Error";
X		iv[0] = 3;
X		DCE_report_iv_set(0);
X		erc = eConnectFailed;
X	}
X	goto START_RCVR_PROCESS;
X
X}	/* end of DCE_dial */
X
X/*+-------------------------------------------------------------------------
X	DCE_dial_pde(tpde) - curses access dial command
X--------------------------------------------------------------------------*/
Xint
XDCE_dial_pde(tpde)
Xregister PDE *tpde;
X{
X	copy_pde_to_lvar(tpde);
X	return(DCE_dial());
X}	/* end of DCE_dial_pde */
X
X/*+-------------------------------------------------------------------------
X	DCE_redial(arg,argc)
X--------------------------------------------------------------------------*/
XDCE_redial(arg,argc)
Xchar **arg;
Xint argc;
X{
Xint erc = 0;
Xint delay = 60;
Xint retries = 10;
Xint nap_decisec;
Xint ans;
X
X	if(shm->Ltelno[0] == 0)
X	{
X		pprintf("   no previous number\n");
X		return(-1);
X	}
X
X	if((argc > 1) && ((retries = atoi(arg[1])) == 0))
X	{
X		pprintf("  invalid retry count\n");
X		return(-1);
X	}
X
X	if((argc > 2) && ((delay = atoi(arg[2])) == 0))
X	{
X		pprintf("  invalid delay\n");
X		return(-1);
X	}
X
X	if(delay < 15)		/* try to be nice to telcos */
X		delay = 15;		/* (they are our friends :-) */
X
X	pprintf("  for %d retries, pause between: %d secs\n",
X				retries,delay);
X
X	kill_rcvr_process(SIGUSR1);		/* kill rcvr process */
X
X	DCE_hangup();
X	while(retries--)
X	{
X	register itmp;
X
X#ifdef AUTO_DIAL_PROC
X		if(!isdigit(shm->Llogical[0]) && find_procedure(shm->Llogical))
X		{
X		char *pargv[2];
X		ulong colors_at_entry = colors_current;
X			pargv[0] = shm->Llogical;
X			pargv[1] = "!REDIAL;";
X			ttymode(2);
X			erc = do_proc(2,pargv);
X			interrupt = 0;
X			proc_file_reset();
X			ttymode(1);
X			setcolor(colors_notify);
X			ff(se,"[procedure finished]");
X			setcolor(colors_at_entry);
X			ff(se,"\r\n");
X			if(!erc)
X			{
X				start_rcvr_process(0);
X				return(0);
X			}
X			if(erc >= e_FATAL)
X				break;
X		}
X		else if(!(erc = DCE_dial()))
X		{
X#ifdef WHT
X			bell_notify(XBELL_C);
X#endif
X			start_rcvr_process(1);
X			return(0);
X		}
X#else
X		if(!(erc = DCE_dial()))
X		{
X#ifdef WHT
X			bell_notify(XBELL_C);
X#endif
X			start_rcvr_process(1);
X			return(0);
X		}
X#endif
X
X		if((retries == 0) || (erc >= e_FATAL))
X			break;
X
X		pprintf("%d %s left ... ",retries,(retries == 1) ? "retry" : "retries");
X		nap_decisec = delay * 10;
X		ff(se,"waiting %d seconds ... 'c' to cycle, %s to abort\r\n",
X			delay,(kbdintr == DEL) ?"DEL":make_char_graphic(kbdintr,0));
X		while(nap_decisec--)
X		{
X			nap(100L);
X			while(rdchk(0))
X			{
X				ans = to_lower(ttygetc(1));
X				if(ans == 'c')
X					goto CONTINUE_CYCLE;
X				else if(ans == kbdintr)
X					goto ABORT_CYCLE;
X				else
X					ring_bell();
X			}
X			if(interrupt)
X				goto ABORT_CYCLE;
X		}
XCONTINUE_CYCLE:
X		;
X	}
X
XERROR_RETURN:
X	start_rcvr_process(1);
X	return(-1);
X
XABORT_CYCLE:
X	ff(se,"redial ABORTED\r\n");
X	interrupt = 0;
X	goto ERROR_RETURN;
X}	/* end of DCE_redial */
X
X/*+-------------------------------------------------------------------------
X	DCE_now_on_hook()
X--------------------------------------------------------------------------*/
Xvoid
XDCE_now_on_hook()
X{
Xchar s128[128];
Xlong connect_secs;
Xlong time();
Xchar *get_elapsed_time();
X
X	if(shm->Lmodem_off_hook)
X	{
X		connect_secs = time((long *)0) - shm->Loff_hook_time;
X		sprintf(s128,"DISCONNECT %s (%s) %ld %s",
X			shm->Llogical,shm->Ltelno,connect_secs,
X			get_elapsed_time(connect_secs));
X		ecu_log_event(getpid(),s128);
X		shm->Lmodem_off_hook = 0;
X	}
X	shm->Lrname[0] = 0;
X
X}	/* end of DCE_now_on_hook */
X
X/*+-------------------------------------------------------------------------
X	DCE_hangup()
X--------------------------------------------------------------------------*/
Xvoid
XDCE_hangup()
X{
Xint rcvr_was_alive = 0;
X
X	if(rcvr_pid > 0)
X	{
X		rcvr_was_alive = 1;
X		kill_rcvr_process(SIGUSR1);
X		nap(500L);
X	}
X
X	ltoggle_dtr();
X	DCE_now_on_hook();
X	set_default_escape_prompt();
X
X	if(rcvr_was_alive)
X		start_rcvr_process(0);
X
X}	/* end of DCE_hangup */
X
X/*+-------------------------------------------------------------------------
X	DCE_get_sreg_value(regnum)
X assumes rcvr process has been killed
X--------------------------------------------------------------------------*/
Xint
XDCE_get_sreg_value(regnum)
Xint regnum;
X{
Xchar s128[128];
XLRWT	lr;
X
X	sprintf(s128,"ATS%d?",regnum);
X	DCE_send_cmd(s128);
X	lflush(0);
X	lr.to1 = 2000L;
X	lr.to2 = 140L;
X	lr.raw_flag = 0;
X	lr.buffer = s128;
X	lr.bufsize = sizeof(s128);
X	lr.delim = (char *)0;
X	lr.echo = 0;
X	lgets_timeout(&lr);
X	if(lr.count != 3)
X		return(-1);
X	return(atoi(s128));
X
X}	/* end of DCE_get_sreg_value */
X
X/*+-------------------------------------------------------------------------
X	DCE_set_sreg(regnum,value)
X assumes rcvr process has been killed
X returns 0 if no error (reads back value set),
X else -1 and error message has been printed
X--------------------------------------------------------------------------*/
Xint
XDCE_set_sreg(regnum,value)
Xint regnum;
Xint value;
X{
Xchar s128[128];
Xint value2;
XLRWT	lr;
X
X	sprintf(s128,"ATS%d=%d",regnum,value);
X	DCE_send_cmd(s128);
X	lflush(0);
X	lr.to1 = 2000L;
X	lr.to2 = 140L;
X	lr.raw_flag = 0;
X	lr.buffer = s128;
X	lr.bufsize = sizeof(s128);
X	lr.delim = (char *)0;
X	lr.echo = 0;
X	lgets_timeout(&lr);
X	value2 = DCE_get_sreg_value(regnum);
X	if(value2 < 0)
X		pprintf("PROBLEM setting modem S%d=%d; cannot talk to modem\n",
X				regnum,value);
X	else if(value != value2)
X		pprintf("PROBLEM setting modem S%d=%d; got %d back\n",
X				regnum,value,value2);
X	return((value != value2) ? -1 : 0);
X
X}	/* end of DCE_set_sreg */
X
X/*+-------------------------------------------------------------------------
X	DCE_autoanswer()
X--------------------------------------------------------------------------*/
Xvoid
XDCE_autoanswer()
X{
X	if(!Lmodem_autoans[0])
X		return;
X	nap(200L);
X	lputs_paced(20,"AT\r");
X	nap(100L);
X	lputs_paced(20,Lmodem_autoans); /* quiet modem */
X	lputs_paced(20,"\r");
X	nap(200L);
X	lputs_paced(20,Lmodem_autoans); /* quiet modem */
X	lputs_paced(20,"\r");
X	nap(200L);
X	lflush(0);
X}	/* end of DCE_autoanswer */
X
X/* end of ecuDCE.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 1224222790 'ecuDCE.c' &&
chmod 0644 ecuDCE.c ||
echo 'restore of ecuDCE.c failed'
Wc_c="`wc -c < 'ecuDCE.c'`"
test 20605 -eq "$Wc_c" ||
	echo 'ecuDCE.c: original size 20605, current size' "$Wc_c"
# ============= ecuLCK.c ==============
echo 'x - extracting ecuLCK.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ecuLCK.c' &&
X#define HONEYDANBER /* means use ASCII pids in lock files */
X#if defined(SHARE_DEBUG)
X#define LOG_LOCKS
X#endif
X/*+-----------------------------------------------------------------------
X	ecuLCK.c -- ECU lock file management
X	wht@n4hgf.Mt-Park.GA.US
X
X  Defined functions:
X	is_active_lock(name)
X	line_locked(ttyname)
X	make_lock_name(ttyname,lock_file_name)
X
XLock files under XENIX are supposed to use the direct line name
X(lower-case last letter); we create only the lower-case case, but
Xcheck for both.
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:11-19-1990-01:05-wht@n4hgf-remove lock in is_active_lock if we locked */
X/*:10-16-1990-20:43-wht@n4hgf-add SHARE_DEBUG */
X/*:09-19-1990-19:36-wht@n4hgf-ecu_log_event now gets pid for log from caller */
X/*:08-14-1990-20:39-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include "ecu.h"
X#include "utmpstatus.h"
X
Xextern int errno;
Xextern char ungetty_ttyname[];
X
X/*+-------------------------------------------------------------------------
X	make_lock_name(ttyname,lock_file_name)
X--------------------------------------------------------------------------*/
Xmake_lock_name(ttyname,lock_file_name)
Xchar *ttyname;
Xchar *lock_file_name;
X{
X
X	if((ulindex(ttyname,"/dev/tty")) != 0)
X		return(LOPEN_INVALID);
X
X	strcpy(lock_file_name,"/usr/spool/uucp/LCK..");
X	strcat(lock_file_name,ttyname + 5);
X	return(0);
X
X}	/* end of make_lock_name */
X
X/*+-------------------------------------------------------------------------
X	is_active_lock(name) - check to see if lock still active
X
Xif not unlink any old lock name
X--------------------------------------------------------------------------*/
Xis_active_lock(name)
Xregister char *name;
X{
Xregister itmp;
Xint lockpid;
Xint fd;
Xint status = 0;
Xchar pidstr[12];
X
X	errno = 0;
X	if((fd = open(name,O_RDONLY,0)) < 0)
X	{
X		if(errno != ENOENT)
X			status = LOPEN_LCKERR;
X		goto RETURN_STATUS;
X	}
X
X#if defined(HONEYDANBER)
X	itmp = read(fd,(char *)pidstr,11);
X	pidstr[11] = 0;
X	close(fd);
X	if(itmp != 11)
X		goto UNLINK_OLD_LOCK;
X	lockpid = atoi(pidstr);
X#else
X	itmp = read(fd,(char *)&lockpid,sizeof(int));
X	close(fd);
X	if(itmp != sizeof(int))
X		goto UNLINK_OLD_LOCK;
X#endif
X
X/*
X * during certain error recovery conditions,
X * we could get hurt by our own lock file
X */
X	if(lockpid == getpid())		/* if we are the locker, kill it */
X		goto UNLINK_OLD_LOCK;
X
X	if((!(itmp = kill(lockpid,0))) || (errno != ESRCH))
X	{
X		errno = EACCES;		/* for hangup() */
X		status = lockpid;
X		goto RETURN_STATUS;
X	}
X
XUNLINK_OLD_LOCK:
X	if(unlink(name))
X		status = LOPEN_LCKERR;
X
XRETURN_STATUS:
X
X#if defined(LOG_LOCKS)
X{ char s128[128];
X  extern char *errno_text();
X	sprintf(s128,"ISLOCK %s status=%d errno=%s",
X		name,status,errno_text(errno));
X	ecu_log_event(getpid(),s128);
X}
X#endif
X
X	return(status);
X}	/* end of is_active_lock */
X
X/*+-----------------------------------------------------------------------
X	line_locked(ttyname) - boolean test for locked line
X
X  ttyname must be of style "/dev/ttyxx"
X  Returns locking pid if locked else LOPEN lock error code (< 0) else 0
X  Either modem or direct name might be locked, so check both
X------------------------------------------------------------------------*/
Xint
Xline_locked(ttyname)
Xchar *ttyname;
X{
Xregister itmp;
Xchar lock_file_name[64];
X	
X	make_lock_name(ttyname,lock_file_name);
X	if(itmp = is_active_lock(lock_file_name))
X		return(itmp);
X
X#if defined(M_XENIX) || defined(M_UNIX)
X	if(isalpha(lock_file_name[itmp = strlen(lock_file_name) - 1]))
X	{
X		lock_file_name[itmp] ^= 0x20;	/* lower->upper, upper->lower */
X		if(itmp = is_active_lock(lock_file_name))
X			return(itmp);
X	}
X#endif
X	return(0);
X
X}	/* end of line_locked */
X
X/* end of ecuLCK.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 1224222790 'ecuLCK.c' &&
chmod 0644 ecuLCK.c ||
echo 'restore of ecuLCK.c failed'
Wc_c="`wc -c < 'ecuLCK.c'`"
test 3727 -eq "$Wc_c" ||
	echo 'ecuLCK.c: original size 3727, current size' "$Wc_c"
# ============= ecuchdir.c ==============
echo 'x - extracting ecuchdir.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ecuchdir.c' &&
X/*+-------------------------------------------------------------------------
X	ecuchdir.c - ECU change directory command/history
X	wht@n4hgf.Mt-Park.GA.US
X
X  Defined functions:
X	cd_array_delete(arg,narg)
X	cd_array_delete_usage()
X	cd_array_init()
X	cd_array_read(arg,narg)
X	cd_array_save(arg,narg)
X	change_directory(cdarg,arg_present_flag)
X	expand_dirname(dirname)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include "ecu.h"
X#include "ecukey.h"
X#include <pwd.h>
X
X#define CD_QUAN		44
X#define CD_PATHLEN	130
Xchar *cd_array[CD_QUAN];
Xuint cd_in_use = 0;
X
Xextern char curr_dir[];		/* current working directory */
Xextern char errmsg[];
Xextern int errno;
X
X/*+-------------------------------------------------------------------------
X	cd_array_read(arg,narg)
X--------------------------------------------------------------------------*/
Xvoid
Xcd_array_read(arg,narg)
Xchar **arg;
Xint narg;
X{
Xchar dirpath[CD_PATHLEN];
XFILE *fpcd;
XFILE *fopen();
Xregister char *cptr;
Xchar *skip_ld_break();
X
X	get_home_dir(dirpath);
X	strcat(dirpath,"/.ecu/dir");
X	if((fpcd = fopen(dirpath,"r")) == (FILE *)0)
X		return;		/* none found */
X
X	for(cd_in_use = 0; cd_in_use < CD_QUAN; cd_in_use++)
X	{
X		if(fgets(dirpath,sizeof(dirpath),fpcd) == (char *)0)
X			break;
X		dirpath[strlen(dirpath) - 1] = 0;
X		cptr = skip_ld_break(dirpath);
X		if(strlen(cptr) == 0)
X		{
X			--cd_in_use;
X			continue;
X		}
X		strcpy(cd_array[cd_in_use],cptr);
X	}
X	fclose(fpcd);
X}	/* end of cd_array_read */
X
X/*+-------------------------------------------------------------------------
X	cd_array_save(arg,narg)
X--------------------------------------------------------------------------*/
Xvoid cd_array_save(arg,narg)
Xchar **arg;
Xint narg;
X{
Xregister icd;
Xchar savepath[256];
XFILE *fpcd;
XFILE *fopen();
X
X	get_home_dir(savepath);
X	strcat(savepath,"/.ecu/dir");
X
X	if(cd_in_use == 0)
X	{
X		ff(se,"No directory list to save in %s\r\n",savepath);
X		return;
X	}
X	if((fpcd = fopen(savepath,"w")) == (FILE *)0)
X	{
X		ff(se,"%s could not be opened\r\n",savepath);
X		return;
X	}
X
X	for(icd = 0; icd < cd_in_use; icd++)
X		fprintf(fpcd,"%s\n",cd_array[icd]);
X	fclose(fpcd);
X	ff(se,"%d entries saved in %s\r\n",cd_in_use,savepath);
X
X}	/* end of cd_array_save */
X
X/*+-------------------------------------------------------------------------
X	cd_array_delete_usage()
X--------------------------------------------------------------------------*/
Xvoid
Xcd_array_delete_usage()
X{
X	ff(se,"usage: d[elete] <1st> [<last>]\r\n");
X}	/* end of cd_array_delete_usage */
X
X/*+-------------------------------------------------------------------------
X	cd_array_delete(arg,narg)
X--------------------------------------------------------------------------*/
Xcd_array_delete(arg,narg)
Xchar **arg;
Xint narg;
X{
Xuint first;		/* 1st to delete */
Xuint last;		/* last to delete */
X
X	if((narg < 2) || (narg > 3))
X	{
X		cd_array_delete_usage();
X		return(-1);
X	}
X
X	first = atoi(arg[1]) - 1;
X	if(narg == 2)
X		last = first;
X	else
X		last = atoi(arg[2]) - 1;
X
X	if((first > (cd_in_use - 1)) || (last > (cd_in_use - 1)) || (last < first))
X	{
X		cd_array_delete_usage();
X		return(-1);
X	}
X
X	if(last == (cd_in_use - 1))
X	{
X		cd_in_use = first;
X	}
X	else
X	{
X	int count_less = last - first + 1;
X		last++;
X		while(last != cd_in_use)
X			strcpy(cd_array[first++],cd_array[last++]);
X		cd_in_use -= count_less;
X	}
X	return(0);
X}	/* end of cd_array_delete */
X
X/*+-------------------------------------------------------------------------
X	cd_array_init()
X--------------------------------------------------------------------------*/
Xvoid
Xcd_array_init()
X{
Xregister itmp;
X
X/*allocate change_directory stack */
X	for(itmp = 0; itmp < CD_QUAN; itmp++)
X	{
X		if(!(cd_array[itmp] = malloc(CD_PATHLEN + 1)))
X		{
X			ff(se,"Not enough memory for cd stack\r\n");
X			exit(1);
X		}
X		*cd_array[itmp] = 0;
X	}
X	(void)cd_array_read(cd_array,0);
X}	/* end of cd_array_init */
X
X/*+-------------------------------------------------------------------------
X	expand_dirname(dirname,maxlen) - convert dirnames with shell chars
X--------------------------------------------------------------------------*/
Xexpand_dirname(dirname,maxlen)
Xchar *dirname;
Xint maxlen;
X{
Xchar s256[256];
Xchar *expcmd;
X
X	if(!find_shell_chars(dirname))
X		return(0);
X
X	sprintf(s256,"`ls -d %s`",dirname);
X	if(expand_cmd_with_wildlist(s256,&expcmd))
X	{
X		strcpy(errmsg,"No files match");
X		return(-1);
X	}
X	strncpy(dirname,expcmd,maxlen);
X	dirname[maxlen - 1] = 0;
X	free(expcmd);
X	if(strchr(dirname,' '))
X	{
X		strcpy(errmsg,"Too many files");
X		return(-1);
X	}
X	return(0);
X
X}	/* end of expand_dirname */
X
X/*+-------------------------------------------------------------------------
X	change_directory(dirname,arg_present_flag)
X
X  Change directory to 'dirname' if arg_present_flag is true,
X  else if flag 0, ask for new directory name and change to it
X  This procedure maintains the global variable 'curr_dir' that
X  reflects the ecu transmitter and receiver process current
X  working directory.
X--------------------------------------------------------------------------*/
Xchange_directory(cdarg,arg_present_flag)
Xchar *cdarg;
Xint arg_present_flag;
X{
Xregister icd;
Xregister itmp;
Xchar s130[130];
X#define BLD_ARG_MAX	5
Xchar *arg[BLD_ARG_MAX];
Xint narg;
Xint longest;
X
X	if(cd_in_use == 0)
X		cd_array_read(arg,0);
X
X	fputs("  ",se);
X
X	if(arg_present_flag)		/* if there is an argument ... */
X	{
X		if(isdigit(*cdarg))		/* ... and first char is digit */
X		{
X			icd = atoi(cdarg) - 1;
X			if(icd >= cd_in_use)
X				goto DISPLAY_CD_ARRAY;
X			strncpy(s130,cd_array[icd],sizeof(s130) - 1);
X		}
X		else
X			strncpy(s130,cdarg,sizeof(s130) - 1);	/* literal dir spec */
X
X		s130[sizeof(s130) - 1] = 0;
X	}
X	else		/* no arg to cd command */
X	{
XDISPLAY_CD_ARRAY:
X		fputs("\r\n",se);
X		longest = 0;
X		for(icd = 0; icd < CD_QUAN/2; icd++)
X		{
X			if(icd >= cd_in_use)
X				break;
X			if(longest < (itmp = strlen(cd_array[icd])))
X				longest = itmp;
X		}
X		longest += 4;
X		if(longest < 36)
X			longest += 4;
X		for(icd = 0; icd < CD_QUAN/2; icd++)
X		{
X			if(icd >= cd_in_use)
X				break;
X			sprintf(s130,"%2d %s ",icd + 1,cd_array[icd]);
X			fputs(s130,se);
X			if(icd + CD_QUAN/2 >= cd_in_use)
X				fputs("\r\n",se);
X			else
X			{
X				itmp = longest - strlen(s130);
X				while(itmp-- > 0)
X					fputc(' ',se);
X				sprintf(s130,"%2d %s\r\n",
X					icd + 1 + CD_QUAN/2,cd_array[icd + CD_QUAN/2]);
X				fputs(s130,se);
X			
X			}
X		}
X		fputs("current dir: ",se);
X		tcap_stand_out();
X		ff(se," %s ",curr_dir);
X		tcap_stand_end();
X		tcap_eeol();
X		fputs("\r\n",se);
X
XGET_NEW_DIR:
X		fputs("New dir, <#>, %save, %read, %del, %xmitcd, <enter>:  ",se);
X		ttygets(s130,sizeof(s130),1);
X		if( (s130[0] == ESC) || (strlen(s130) == 0) )
X		{
X			ff(se,"no directory change\r\n");
X			return(0);
X		}
X		else if(s130[0] == '%')
X		{
X			build_str_array(s130,arg,BLD_ARG_MAX,&narg);
X
X			if(minunique("save",&s130[1],1))
X			{
X				cd_array_save(arg,narg);
X				goto GET_NEW_DIR;
X			}
X			else if(minunique("read",&s130[1],1))
X			{
X				cd_array_read(arg,narg);
X				goto DISPLAY_CD_ARRAY;
X			}
X			else if(minunique("delete",&s130[1],1))
X			{
X				if(cd_array_delete(arg,narg))
X					goto GET_NEW_DIR;
X				else
X					goto DISPLAY_CD_ARRAY;
X			}
X			else if(minunique("xmitcd",&s130[1],1))
X			{
X				lputs("cd ");
X				lputs(curr_dir);
X				lputc('\r');
X				return(0);
X			}
X			else
X			{
X				ff(se,"Invalid cd subcommand\r\n");
X				goto GET_NEW_DIR;
X			}
X		}
X		else if(icd = atoi(s130))
X		{
X			icd--;
X			if(icd >= cd_in_use)
X				goto GET_NEW_DIR;
X			strncpy(s130,cd_array[icd],sizeof(s130) - 1);
X			s130[sizeof(s130) - 1] = 0;
X		}
X	}
X	if(expand_dirname(s130,sizeof(s130)))
X	{
X		ff(se,"%s\r\n",errmsg);
X		return(-1);
X	}
X	if(chdir(s130) < 0)		/* now change to the new directory */
X	{
X		perror(s130);		/* print error if we get one */
X		ff(se,"\r\n");
X		return(-1);
X	}
X	get_curr_dir(curr_dir,256);
X
X	fputs("\r\nconfirmed: ",se);
X	tcap_stand_out();
X	ff(se," %s ",curr_dir);
X	tcap_stand_end();
X	fputs("\r\n",se);
X	fflush(se);
X
X	for(icd = 0; icd < cd_in_use; icd++)
X	{
X		if(strcmp(curr_dir,cd_array[icd]) == 0)
X			return(0);
X	}
X	if(cd_in_use == CD_QUAN)
X	{
X		for(icd = 1; icd < CD_QUAN; icd++)
X		{
X			strcpy(cd_array[icd - 1],cd_array[icd]);
X		}
X		strcpy(cd_array[CD_QUAN - 1],curr_dir);
X	}
X	else
X		strcpy(cd_array[cd_in_use++],curr_dir);
X
X	return(0);
X
X}	/* end of change_directory */
X/* end of ecuchdir.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 1224222790 'ecuchdir.c' &&
chmod 0644 ecuchdir.c ||
echo 'restore of ecuchdir.c failed'
Wc_c="`wc -c < 'ecuchdir.c'`"
test 8377 -eq "$Wc_c" ||
	echo 'ecuchdir.c: original size 8377, current size' "$Wc_c"
# ============= ecudump.c ==============
echo 'x - extracting ecudump.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'ecudump.c' &&
X/*+-----------------------------------------------------------------------
X	ecudump.c  -- very generic hex/graphics dump development aid
X	wht@n4hgf.Mt-Park.GA.US
X
X  Defined functions:
X	dump_putc(ch)
X	dump_puts(str)
X	hex_dump(str,len,title,terse_flag)
X	hex_dump_fp(fp,str,len,title,terse_flag)
X	hex_dump16(int16)
X	hex_dump32(int32)
X	hex_dump4(int4)
X	hex_dump8(int8)
X
X------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
X
X#include "ecu.h"
X
Xstatic FILE *dumpfp;
X
X/*+-------------------------------------------------------------------------
X	dump_putc(ch)
X--------------------------------------------------------------------------*/
Xvoid
Xdump_putc(ch)
Xchar ch;
X{
X	if(dumpfp == se)
X		pputc(ch);
X	else
X		fputc(ch,dumpfp);
X}	/* end of dump_putc */
X
X
X/*+-------------------------------------------------------------------------
X	dump_puts(str)
X--------------------------------------------------------------------------*/
Xvoid
Xdump_puts(str)
Xchar *str;
X{
X	if(dumpfp == se)
X		pputs(str);
X	else
X		fputs(str,dumpfp);
X}	/* end of dump_puts */
X
X
X/*+-----------------------------------------------------------------------
X	hex_dump#... subservient routines
X------------------------------------------------------------------------*/
Xvoid hex_dump4(int4)
Xuchar int4;
X{
X	int4 &= 15;
X	dump_putc((int4 >= 10) ? (int4 + 'A' - 10) : (int4 + '0'));
X}
X
Xvoid hex_dump8(int8)
Xuchar int8;
X{
X	hex_dump4(int8 >> 4);
X	hex_dump4(int8);
X}
X
Xvoid hex_dump16(int16)
Xushort int16;
X{
X	hex_dump8(int16 >> 8);
X	hex_dump8(int16);
X}
X
Xvoid hex_dump32(int32)
Xulong int32;
X{
X	hex_dump16(int32 >> 16);
X	hex_dump16(int32);
X}
X
X
X/*+-----------------------------------------------------------------
X	hex_dump_fp(fp,str,len,title,terse_flag)
X
X  if 'title' not NULL, title is printed... 'terse_flag'
X  controls whether or not the title is "conspicuous" with
X  hyphens before and after it making title line >70 chars long
X------------------------------------------------------------------*/
Xvoid
Xhex_dump_fp(fp,str,len,title,terse_flag)
XFILE *fp;
Xchar *str;
Xint len;
Xchar *title;
Xint terse_flag;
X{
Xint istr;
Xregister ipos;
Xregister itmp;
X
X	dumpfp = fp;
X
X	if(title && (istr = strlen(title)))
X	{
X		if(!terse_flag)
X		{
X			ipos = (73 - istr) / 2;
X			itmp = ipos;
X			while(itmp--)
X				dump_putc('-');
X			dump_putc(' ');
X			if(istr & 1)
X				ipos--;
X		}
X		dump_puts(title);
X		if(!terse_flag)
X		{
X			dump_putc(' ');
X			while(ipos--)
X				dump_putc('-');
X		}
X		if(dumpfp == se)
X			dump_puts("\r\n");
X		else
X			dump_puts("\n");
X
X	}
X
X	istr = 0;
X	while(istr < len)
X	{
X		hex_dump16(istr);
X		dump_putc(' ');
X		for(itmp = 0; itmp < 16; ++itmp)
X		{
X			ipos = istr + itmp;
X			if(ipos >= len)
X			{
X				if(!terse_flag)
X					dump_puts("   ");
X				continue;
X			}
X			dump_putc(' ');
X			hex_dump8(str[ipos]);
X		}
X		dump_puts(" | ");
X		for(itmp = 0; itmp < 16; ++itmp)
X		{
X			ipos = istr + itmp;
X			if( (ipos) >= len)
X			{
X				if(!terse_flag)
X					dump_putc(' ');
X			}
X			else
X			{
X				dump_putc((str[ipos] >= ' ' && str[ipos] < 0x7f)
X		 			? str[ipos] : '.' );
X			}
X		}
X		if(dumpfp == se)
X			dump_puts(" |\r\n");
X		else
X			dump_puts(" |\n");
X		istr += 16;
X	}   /* end of while(istr < len) */
X
X}	/* end of hex_dump_fp */
X
X/*+-------------------------------------------------------------------------
X	hex_dump(str,len,title,terse_flag)
X--------------------------------------------------------------------------*/
Xvoid
Xhex_dump(str,len,title,terse_flag)
Xchar *str;
Xint len;
Xchar *title;
Xint terse_flag;
X{
X	hex_dump_fp(se,str,len,title,terse_flag);
X}	/* end of hex_dump_fp */
X/* end of ecudump.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
$TOUCH -am 1224222890 'ecudump.c' &&
chmod 0644 ecudump.c ||
echo 'restore of ecudump.c failed'
Wc_c="`wc -c < 'ecudump.c'`"
test 3656 -eq "$Wc_c" ||
	echo 'ecudump.c: original size 3656, current size' "$Wc_c"
true || echo 'restore of ecufinsert.c failed'
echo End of part 2, continue with part 3
exit 0
--------------------------------------------------------------------
Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
Hacker Extraordinaire  d' async PADs,  pods,  proteins and protocols

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.