[alt.sources] ecu - SCO XENIX V/{2,3}86 Extended CU part 03/47

wht@tridom.uucp (Warren Tucker) (10/09/89)

---- Cut Here and unpack ----
#!/bin/sh
# this is part 3 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file ecufkey.c continued
#
CurArch=3
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
echo "x - Continuing file ecufkey.c"
sed 's/^X//' << 'SHAR_EOF' >> ecufkey.c
Xint
Xxf_to_keyid(xf)
Xuchar xf;
X{
Xstruct XF_KDE_NAME *xkn = xf_kde_name;
X	while(xkn->xf != 0)
X	{
X		if(xkn->xf == xf)
X			return((int)xkn->kde & 0xFF);
X		xkn++;
X	}
X	return(-1);
X}	/* end of xf_to_keyid */
X
X/*+-------------------------------------------------------------------------
X	keyset_define_key(bufptr)
X--------------------------------------------------------------------------*/
Xint
Xkeyset_define_key(bufptr)
Xchar *bufptr;
X{
Xregister itmp;
Xregister token_number;
Xregister KDE *tkde;
Xint keyid;
Xchar token_separator[2];
Xchar *token;
Xchar *str_token();
X
X	if(itmp = strlen(bufptr))	/* itmp = len; if > 0 ... */
X		bufptr[--itmp] = 0;		/* ... strip trailing NL */
X	if(!itmp)
X		return(0);
X
X	if(bufptr[0] == '#')		/* comment? */
X		return(0);
X	if((*bufptr != 0x20) && (*bufptr != TAB))	/* if no leading space */
X		return(1);
X	if(*bufptr == 0)					/* if line all blank, break */
X		return(1);
X
X	while((*bufptr == 0x20) || (*bufptr == TAB))	/* strip lding sp/tab */
X		bufptr++;
X
X	token_number = 0;
X	strcpy(token_separator,":");
X	while( (token = str_token(bufptr,token_separator)) != NULL)
X	{
X		bufptr = NULL;	/* further calls to str_token need NULL */
X		switch(token_number)
X		{
X			case 0:		/* first field is key identifier */
X				if((keyid = keyset_idnum(token)) < 0)
X				{
X					ff(se,"  %s is not a legal key identifier\r\n",token);
X					return(0);
X				}
X				if(keyid == KDE_HOME)
X				{
X					ff(se,"  HOME cannot be redefined!\r\n");
X					return(0);
X				}
X				if(keyid == KDE_CU5)
X				{
X					ff(se,"  CUR5 cannot be redefined!\r\n");
X					return(0);
X				}
X				tkde = &keyset_table[keyid];
X				tkde->logical[0] = 0;
X				tkde->outcount = 0;
X				break;
X
X			case 1:		/* second field is logical key name */
X				strncpy(tkde->logical,token,sizeof(tkde->logical));
X				tkde->logical[sizeof(tkde->logical) - 1] = 0;
X				strcpy(token_separator," "); /* space is tok sep now */
X				break;
X
X			default:	/* third and subsequent to define key */
X				if(tkde->outcount == sizeof(tkde->outstr))
X				{
X					ff(se,"  %s: output count too long",
X						keyset_idstr(keyid));
X					return(0);
X				}
X				if((itmp = ascii_to_hex(token)) < 0)
X				{
X					ff(se,"  %s: '%s' invalid\r\n",
X						keyset_idstr(keyid),token);
X					return(0);
X				}
X				tkde->outstr[tkde->outcount] = itmp;
X				tkde->outcount++;
X				break;
X		}	/* end of switch(token_number) */
X		token_number++;
X	}		/* end while not end of record */
X
X}	/* end of keyset_define_key */
X
X/*+-------------------------------------------------------------------------
X	keyset_read(name)
Xreturns 0 on success, -1 if no .ecu/keys, -2 if no 'name'
X--------------------------------------------------------------------------*/
Xint
Xkeyset_read(name)
Xchar *name;
X{
Xregister itmp;
Xregister char *cptr;
Xstatic char ecukeys_name[128];
Xchar readkde_buf[128];
XFILE *fp_keys;
X
X	if(!ecukeys_name[0])
X	{
X		get_home_dir(ecukeys_name);
X		strcat(ecukeys_name,"/.ecu/keys");
X	}
X
X	if((fp_keys = fopen(ecukeys_name,"r")) == NULL)
X		return(-1);
X
X/* find keyset name */
X	while(fgets(readkde_buf,sizeof(readkde_buf),fp_keys) != NULL)
X	{
X		if(readkde_buf[0] == '#')		/* comment? */
X			continue;
X		if(itmp = strlen(readkde_buf))	/* itmp = len; if > 0 ... */
X			readkde_buf[--itmp] = 0;	/* ... strip trailing NL */
X		if(!itmp)
X			continue;
X		if(strcmp(readkde_buf,name) == 0)
X		{
X			itmp = 1;		/* indicate success */
X			break;
X		}
X		itmp = 0;			/* if loop terminates w/o find, failure */
X	}
X	if(!itmp)
X	{
X		fclose(fp_keys);
X		return(-2);
X	}
X
X	keyset_init();	/* clear any previous key defns */
X
X/* read past any other keyset names matching this set */
X	while(fgets(readkde_buf,sizeof(readkde_buf),fp_keys) != NULL)
X	{
X		cptr = readkde_buf;				/* first call to str_token, -> buff */
X		if((*cptr == 0x20) || (*cptr == TAB))	/* if leading space */
X		{
X			(void)keyset_define_key(cptr);
X			break;
X		}
X	}
X
X/* we found the definition ... read it */
X	while(fgets(readkde_buf,sizeof(readkde_buf),fp_keys) != NULL)
X	{
X		if(keyset_define_key(readkde_buf))
X			break;
X	}
X
X	strncpy(keyset_name,name,sizeof(keyset_name));
X	keyset_name[sizeof(keyset_name) - 1] = 0;
X	fclose(fp_keys);
X	return(0);
X}	/* end of keyset_read */
X
X/*+-------------------------------------------------------------------------
X	ffso(str)
X--------------------------------------------------------------------------*/
Xvoid
Xffso(str)
Xchar *str;
X{
X	stand_out();
X	fputs(str,se);
X	stand_end();
X}	/* end of ffso */
X
X/*+-------------------------------------------------------------------------
X	keyset_display()
X
X F1  xxxxx  F2   xxxxx   HOME xxxxx  PGUP xxxxx
X F3  xxxxx  F4   xxxxx   END  xxxxx  PGDN xxxxx
X F5  xxxxx  F6   xxxxx   INS  xxxxx  CUR5 xxxxx
X F7  xxxxx  F8   xxxxx
X F9  xxxxx  F10  xxxxx   CUR^ xxxxx  CUR> xxxxx
X F11 xxxxx  F12  xxxxx   CUR< xxxxx  CURv xxxxx
X--------------------------------------------------------------------------*/
Xvoid
Xkeyset_display()
X{
Xregister itmp;
Xregister itmp2;
Xchar *cptr;
Xint clen1 = 0;
Xchar cfmt1[32];
Xint clen2 = 0;
Xchar cfmt2[32];
Xint clen3 = 0;
Xchar cfmt3[32];
Xchar cfmt4[4];
X
X	if(!keyset_name[0])
X	{
X		keyset_init();
X		ff(se,"   no key definition active\r\n\r\n");
X		ff(se,"HOME - command prefix\r\n");
X		ff(se,"END  - send interrupt (%s)\r\n",make_char_graphic(kbdintr,0));
X		ff(se,"cursor down - local shell in %s\r\n",curr_dir);
X		fputs("\r\n",se);
X	}
X	else
X	{
X		for(itmp = 0; itmp < KDE_COUNT; itmp++)
X		{
X		register KDE *tkde = &keyset_table[itmp];
X			itmp2 = strlen(tkde->logical);
X			switch(itmp)
X			{
X				case KDE_F1: case KDE_F3: case KDE_F5: case KDE_F7:
X				case KDE_F9: case KDE_F11:
X					if(clen1 < itmp2)
X						clen1 = itmp2;
X					break;
X
X				case KDE_F2: case KDE_F4: case KDE_F6: case KDE_F8:
X				case KDE_F10: case KDE_F12:
X					if(clen2 < itmp2)
X						clen2 = itmp2;
X					break;
X
X				case KDE_HOME: case KDE_END: case KDE_INS:
X				case KDE_CUU: case KDE_CUL:
X					if(clen3 < itmp2)
X						clen3 = itmp2;
X					break;
X			}
X		}
X		sprintf(cfmt1," %%-%d.%ds",clen1,clen1);
X		sprintf(cfmt2," %%-%d.%ds",clen2,clen2);
X		sprintf(cfmt3," %%-%d.%ds",clen3,clen3);
X		strcpy(cfmt4," %s");
X		ff(se,"   key definition: %s\r\n\r\n",keyset_name);
X
X		ffso(" F1  ");ff(se,cfmt1,keyset_table[KDE_F1].logical);
X		fputs("  ",se);
X		ffso(" F2  ");ff(se,cfmt2,keyset_table[KDE_F2].logical);
X		fputs("  ",se);
X		ffso(" HOME ");ff(se,cfmt3,keyset_table[KDE_HOME].logical);
X		fputs("  ",se);
X		ffso(" PGUP ");ff(se,cfmt4,keyset_table[KDE_PGUP].logical);
X		fputs("\r\n",se);
X
X		ffso(" F3  ");ff(se,cfmt1,keyset_table[KDE_F3].logical);
X		fputs("  ",se);
X		ffso(" F4  ");ff(se,cfmt2,keyset_table[KDE_F4].logical);
X		fputs("  ",se);
X		ffso(" END  ");ff(se,cfmt3,keyset_table[KDE_END].logical);
X		fputs("  ",se);
X		ffso(" PGDN ");ff(se,cfmt4,keyset_table[KDE_PGDN].logical);
X		fputs("\r\n",se);
X
X		ffso(" F5  ");ff(se,cfmt1,keyset_table[KDE_F5].logical);
X		fputs("  ",se);
X		ffso(" F6  ");ff(se,cfmt2,keyset_table[KDE_F6].logical);
X		fputs("  ",se);
X		ffso(" INS  ");ff(se,cfmt3,keyset_table[KDE_INS].logical);
X		fputs("  ",se);
X		ffso(" CUR5 ");ff(se,cfmt4,keyset_table[KDE_CU5].logical);
X		fputs("\r\n",se);
X
X		ffso(" F7  ");ff(se,cfmt1,keyset_table[KDE_F7].logical);
X		fputs("  ",se);
X		ffso(" F8  ");ff(se,cfmt2,keyset_table[KDE_F8].logical);
X		fputs("\r\n",se);
X
X		ffso(" F9  ");ff(se,cfmt1,keyset_table[KDE_F9].logical);
X		fputs("  ",se);
X		ffso(" F10 ");ff(se,cfmt2,keyset_table[KDE_F10].logical);
X		fputs("  ",se);
X		ffso(" CUR^ ");ff(se,cfmt3,keyset_table[KDE_CUU].logical);
X		fputs("  ",se);
X		ffso(" CUR> ");ff(se,cfmt4,keyset_table[KDE_CUR].logical);
X		fputs("\r\n",se);
X
X		ffso(" F11 ");ff(se,cfmt1,keyset_table[KDE_F11].logical);
X		fputs("  ",se);
X		ffso(" F12 ");ff(se,cfmt2,keyset_table[KDE_F12].logical);
X		fputs("  ",se);
X		ffso(" CUR< ");ff(se,cfmt3,keyset_table[KDE_CUL].logical);
X		fputs("  ",se);
X		ffso(" CURv ");ff(se,cfmt4,keyset_table[KDE_CUD].logical);
X		fputs("\r\n\r\n",se);
X	}
X
X}	/* end of keyset_display */
X#endif
X
X/* end of ecufkey.c */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
echo "File ecufkey.c is complete"
chmod 0644 ecufkey.c || echo "restore of ecufkey.c fails"
echo "x - extracting ecufork.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ecufork.c &&
X/* CHK=0x1EC8 */
X/*+-------------------------------------------------------------------------
X	ecufork.c -- ecu spawning ground
X	Copyright 1986,1989 Warren H. Tucker, III. All Rights Reserved
X
X  Defined functions:
X	exec_cmd(cmdstr)
X	expand_cmd_with_wildlist(cmd,expcmd)
X	find_executable(progname)
X	is_executable(progname)
X	shell(shellcmd)
X	smart_fork()
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-03-1989-22:57-wht------------- ecu 2.00 ---------------- */
X/*:06-24-1989-16:52-wht-flush edits --- ecu 1.95 */
X
X#include "ecu.h"
X#include "ecufork.h"
X
Xextern int rcvr_pid;
X
X/*+-----------------------------------------------------------------------
X	smart_fork()
X------------------------------------------------------------------------*/
Xint
Xsmart_fork()
X{
Xregister erc;
Xregister count = 0;
X
X	while(++count < 6)
X	{
X		if((erc = fork()) >= 0)
X			return(erc);
X	}
X	perror("Could not fork");
X	ff(se,"\r\n");
X	return(erc);
X}
X
X/*+-----------------------------------------------------------------------
X	shell(shellcmd)
X
X  param 'shellcmd' is a shell command prefixed with either
X  a '!', '$', '>' character.
X
X  '!' causes the command to run as a normal subshell of a process.
X  '$' causes the communications line to be stdin and stdout
X      for the spawned shell
X  '>' causes spawned shell to receive exactly sames files as ecu
X------------------------------------------------------------------------*/
Xvoid
Xshell(shellcmd)
Xchar *shellcmd;
X{
Xregister shellpid;
Xregister itmp;
Xregister char *cptr;
Xchar s40[40];
X#if defined(M_XENIX)
Xvoid xmtr_xenix_SIGCLD_handler();
X#endif
X#if defined(pyr)
Xvoid xmtr_bsd4_SIGCHLD_handler();
X#endif
X
Xint rcvr_alive = (rcvr_pid > 0);
Xchar *getenv();
X
X	if(rcvr_alive)
X		kill_rcvr_process(SIGUSR1);		/* stop receiver process gracefully */
X
X	if((shellpid = smart_fork()) < 0)
X	{
X		ff(se,"Cannot fork\r\n");
X		if(rcvr_alive)
X			start_rcvr_process(1);
X		return;
X	}
X
X	ttymode(0);  	     		/* set canonical tty mode */
X	if(shellpid == 0)			/* we are the spawned (going to call shell) */
X	{
X		if(*shellcmd != '>')	/* '>' prefix means leave fd's alone! */
X		{
X			/* Hook-up our "standard output" to either the tty or
X			 * the line as appropriate for '!' or '$' */
X			close(TTYOUT);
X			fcntl(((*shellcmd == '$') ? Liofd : TTYERR),F_DUPFD,TTYOUT);
X			if(*shellcmd == '$')
X			{
X				close(TTYIN);
X				fcntl(Liofd,F_DUPFD,TTYIN);
X			}
X			close(Liofd);
X		}
X
X		child_signals();		/* signals for child */
X
X		if(*shellcmd == '!')
X		{
X			cptr = getenv("SHELL");
X			if(cptr == (char *)0)
X				cptr = "/bin/csh";
X		}
X		else
X			cptr = "/bin/sh";
X
X		shellcmd++;
X		if(ulindex(cptr,"csh") > -1)
X		{
X			if(*shellcmd == '\0')
X				execl(cptr,"csh",(char *)0);
X			else
X				execl(cptr,"csh","-c",shellcmd,(char *)0);
X		}
X		else
X		{
X			if(*shellcmd == '\0')
X				execl(cptr,"sh",(char *)0);
X			else
X				execl(cptr,"sh","-c",shellcmd,(char *)0);
X		}
X
X		ff(se,"cannot execute %s\r\n",cptr);	/* should not get here */
X		_exit(255);								/* end of spawned process */
X	}	/* end of if child process */
X
X#if defined(FORK_DEBUG)
X	sprintf(s40,"DEBUG fork shell pid %d",shellpid);
X	ecu_log_event(s40); /* shell */
X#endif
X
X/* this code executed by the father (forking) process */
X
X	signal(SIGINT,SIG_IGN);
X	signal(SIGTERM,SIG_IGN);
X	signal(SIGUSR1,SIG_IGN);
X	signal(SIGUSR2,SIG_IGN);
X#if defined(M_XENIX)
X	signal(SIGCLD,xmtr_xenix_SIGCLD_handler);
X#endif
X#if defined(pyr)
X	signal(SIGCHLD,xmtr_bsd4_SIGCHLD_handler);
X#endif
X
X/* this wait merely pends the transmitter process ... it always
Xreturns -1 'cause the SIGCLD/SIGCHLD handler catches the actual
Xsignal */
X
X	while(((itmp = wait((int *)0)) != shellpid)
X	    && (itmp != -1))
X		;
X
X	xmtr_signals();			/* restore standard xmtr signals */
X	ttymode(1);				/* control tty back to raw mode */
X
X/* any comm program will probably doodle with the line characteristics. */
X/* we want to make sure they are restored to normal */
X	lreset_ksr();			/* restore comm line params */
X
X	if(rcvr_alive)
X		start_rcvr_process(1);
X
X}	/* end of shell */
X
X/*+-------------------------------------------------------------------------
X	is_executable(progname)
X--------------------------------------------------------------------------*/
Xis_executable(progname)
Xchar *progname;
X{
Xstruct stat ss;
X
X	if(stat(progname,&ss) < 0)			/* if cannot stat, flunk */
X		return(0);
X	if((ss.st_mode & 0111) == 0)		/* if no --x--x--x, flunk */
X		return(0);
X	return(1);	/* whew, this OUGHT to work */
X
X}	/* end of is_executable */
X
X/*+-------------------------------------------------------------------------
X	find_executable(progname)
XPATH=':/usr/wht/bin:/bin:/usr/bin:/usr/wht/bin:/etc/tuckerware' len=56
X--------------------------------------------------------------------------*/
Xchar *
Xfind_executable(progname)
Xchar *progname;
X{
Xregister itmp;
Xstatic char *path_buf = (char *)0;
X#define PATHNAME_QUAN 32
Xstatic char *path_name[PATHNAME_QUAN + 1];
Xstatic char rtn_path[256];
Xstatic int path_count = 0;
Xchar *cptr;
Xchar *getenv();
Xchar *malloc();
Xchar *str_token();
X
X	if(path_buf == (char *)0)
X	{
X		if((cptr = getenv("PATH")) == (char *)0)
X			return(cptr);
X		if((path_buf = malloc(strlen(cptr) + 1)) == (char *)0)
X			return((char *)0);
X		strcpy(path_buf,cptr);
X		path_name[PATHNAME_QUAN + 1] = (char *)0;
X		cptr = path_buf;
X		for(path_count = 0; path_count < PATHNAME_QUAN; path_count++)
X		{
X			if(*cptr == 0)
X				break;
X			path_name[path_count] = cptr;
X			while((*cptr != ':') && (*cptr != 0))
X				cptr++;
X			if(*cptr == ':')
X				*cptr++ = 0;
X		}
X	}	/* end of get and process path env variable */
X
X/* look for executable */
X	for(itmp = 0; itmp < path_count; itmp++)
X	{
X		if(*path_name[itmp] == 0)	/* if null path (./) */
X			strcpy(rtn_path,"./");
X		else
X			sprintf(rtn_path,"%s/",path_name[itmp]);
X		strcat(rtn_path,progname);
X		if(is_executable(rtn_path))
X			return(rtn_path);
X	}
X	return((char *)0);
X}	/* end of find_executable */
X
X/*+-------------------------------------------------------------------------
X	exec_cmd(cmdstr) - execute an arbitrary program with arguments
Xkills rcvr process if alive and restarts it when done if was alive
X--------------------------------------------------------------------------*/
Xexec_cmd(cmdstr)
Xchar *cmdstr;
X{
Xchar *cmdpath;
X#define MAX_EXEC_ARG 512
Xchar *cmdargv[MAX_EXEC_ARG];
Xint itmp;
Xint execpid;
Xint rcvr_alive = (rcvr_pid > 0);
Xint old_ttymode = get_ttymode();
Xchar s80[80];
Xint wait_status = 0;
Xextern int last_child_wait_status;
Xextern int last_child_wait_pid;
Xextern int errno;
Xchar *strrchr();
X
X#if defined(FORK_DEBUG)
X	strcpy(s80,"DEBUG exec ");
X	strncat(s80,cmdstr,sizeof(s80)-12);
X	s80[sizeof(s80)-12] = 0;
X	ecu_log_event(s80);
X#endif
X
X	build_arg_array(cmdstr,cmdargv,MAX_EXEC_ARG,&itmp);
X	if(itmp == MAX_EXEC_ARG)
X	{
X		ff(se,"Too many arguments to command\r\n");
X		return(-1);
X	}
X
X	if(*cmdargv[0] == '/')
X	{
X		cmdpath = cmdargv[0];
X		cmdargv[0] = strrchr(cmdargv[0],'/') + 1;
X	}
X	else
X	{
X		if((cmdpath = find_executable(cmdargv[0])) == (char *)0)
X		{
X			ff(se,"Cannot find %s\r\n",cmdargv[0]);
X			return(-1);
X		}
X	}
X
X	if(rcvr_alive)
X		kill_rcvr_process(SIGUSR1);		/* stop receiver process gracefully */
X
X	if((execpid = smart_fork()) < 0)
X	{
X		ff(se,"Cannot fork\r\n");
X		if(rcvr_alive)
X			start_rcvr_process(1);
X		return(-1);
X	}
X
X	if(execpid == 0)			/* we are the spawned (going to call exec) */
X	{
X		ttymode(0);  	     	/* set canonical tty mode */
X		child_signals();
X		execv(cmdpath,cmdargv);
X		perror(cmdpath);
X		exit(255);				/* end of spawned process */
X	}	/* end of if child process */
X
X/* this code executed by the father (forking) process */
X/* wait on death of child (morbid in life, but ok here) */
X
X	signal(SIGINT,SIG_IGN);
X	signal(SIGTERM,SIG_IGN);
X	signal(SIGUSR1,SIG_IGN);
X	signal(SIGUSR2,SIG_IGN);
X#if defined(M_XENIX)
X	signal(SIGCLD,xmtr_xenix_SIGCLD_handler);
X#endif
X#if defined(pyr)
X	signal(SIGCHLD,xmtr_bsd4_SIGCHLD_handler);
X#endif
X
XWAIT:
X	wait_status = 0;
X	while(((itmp = wait(&wait_status)) != execpid) && (itmp != -1))
X		;
X
X#if defined(FORK_DEBUG)
X	nap(200L);
X	sprintf(s80,"DEBUG execw pid %04x,errno %d,w_s %04x,lcws %04x,lcwp %d",
X			itmp,errno,wait_status,last_child_wait_status,last_child_wait_pid);
X	ecu_log_event(s80);	/* exec_cmd wait */
X#endif
X
X	if(last_child_wait_pid != execpid)
X		goto WAIT;
X
X/* resume our normally scheduled program */
X	lreset_ksr();				/* restore comm line params */
X	ttymode(old_ttymode);		/* control tty back to original */
X	if(rcvr_alive)
X		start_rcvr_process(1);
X	xmtr_signals();
X	return(0);
X
X}	/* end of exec_cmd */
X
X/*+-------------------------------------------------------------------------
X	expand_cmd_with_wildlist(cmd,&expcmd)
Xif return -1, error, expcmd has error message (static message)
Xif return 0, cmd has been expanded, expcmd must be free()'d when done
X--------------------------------------------------------------------------*/
Xexpand_cmd_with_wildlist(cmd,expcmd)
Xchar *cmd;
Xchar **expcmd;
X{
Xregister char *cptr;
X#define P_READ 0
X#define P_WRITE 1
Xint pipe_pid;
Xint stdout_pipe[2];
Xint stderr_pipe[2];
Xint count;
Xint itmp;
Xint wait_status;
Xint rcvr_alive = (rcvr_pid > 0);
Xchar *echo_cmd;
Xchar *malloc();
Xstatic char s132[132];
Xextern int errno;
Xextern int last_child_wait_status;
Xextern int last_child_wait_pid;
Xextern char *sys_errlist[];
Xchar *strchr();
Xstatic char *pipe_err_msg = "system error: no pipe";
Xstatic char *mem_err_msg = "system error: no memory";
X
X	if(strchr(cmd,'<') || strchr(cmd,'>') || strchr(cmd,'&'))
X	{
X		*expcmd = "illegal characters: '<', '>' or '&'";
X		return(-1);
X	}
X
X	if(pipe(stdout_pipe) < 0)
X	{
X		*expcmd = pipe_err_msg;
X		return(-1);
X	}
X	if(pipe(stderr_pipe) < 0)
X	{
X		close(stdout_pipe[P_READ]);
X		close(stdout_pipe[P_WRITE]);
X		*expcmd = pipe_err_msg;
X		return(-1);
X	}
X	if((echo_cmd = malloc(strlen(cmd) + 10)) == NULL)
X	{
X		close(stdout_pipe[P_READ]);
X		close(stdout_pipe[P_WRITE]);
X		close(stderr_pipe[P_READ]);
X		close(stderr_pipe[P_WRITE]);
X		*expcmd = mem_err_msg;
X		return(-1);
X	}
X
X	strcpy(echo_cmd,"echo ");
X	strcat(echo_cmd,cmd);
X
X
X	if(rcvr_alive)
X		kill_rcvr_process(SIGUSR1);		/* stop receiver process gracefully */
X
X	if((pipe_pid = smart_fork()) == 0)
X	{
X	int null = open("/dev/null",O_WRONLY,0);
X
X		close(stdout_pipe[P_READ]);
X		close(TTYOUT);
X		dup(stdout_pipe[P_WRITE]);
X		close(stdout_pipe[P_WRITE]);
X		close(TTYERR);
X		dup(stderr_pipe[P_WRITE]);
X		close(stderr_pipe[P_WRITE]);
X		close(null);
X		execl("/bin/csh","csh","-e","-f","-c",echo_cmd,(char *)0);
X		_exit(255);
X	}
X
X#if defined(FORK_DEBUG)
X	sprintf(s132,"DEBUG expand pid %d",pipe_pid);
X	ecu_log_event(s132);		/* expand_cmd_with_wildlist */
X#endif
X
X	free(echo_cmd);
X
X	close(stdout_pipe[P_WRITE]);
X	close(stderr_pipe[P_WRITE]);
X	if(pipe_pid == -1)
X	{
X		close(stdout_pipe[P_READ]);
X		close(stderr_pipe[P_READ]);
X		*expcmd = "could not fork";
X		if(rcvr_alive)
X			start_rcvr_process(0);
X		return(-1);
X	}
X
X	if((*expcmd = malloc(5120)) == NULL)
X	{
X		close(stdout_pipe[P_READ]);
X		close(stderr_pipe[P_READ]);
X		kill(pipe_pid,SIGKILL);
X		*expcmd = mem_err_msg;
X		if(rcvr_alive)
X			start_rcvr_process(0);
X		return(-1);
X	}
X
X	cptr = *expcmd;
X	while((count = read(stdout_pipe[P_READ],cptr,64)) != 0)
X	{
X		if(count < 0)
X		{
X			if(errno == EINTR)
X			{
X				errno = 0;
X				continue;
X			}
X			free(*expcmd);
X			kill(pipe_pid,SIGKILL);
X			close(stdout_pipe[P_READ]);
X			close(stderr_pipe[P_READ]);
X			*expcmd = "error reading wild list expansion";
X			if(rcvr_alive)
X				start_rcvr_process(0);
X			return(-1);
X		}
X		cptr += count;
X		*cptr = 0;
X		if(*(cptr - 1) == '\n')
X		{
X			*(cptr - 1) = 0;
X			break;
X		}
X	}
X	close(stdout_pipe[P_READ]);
X	if(!strlen(*expcmd))
X	{
X		free(*expcmd);
X		count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1);
X		if(count < 0)
X			strcpy(s132,sys_errlist[errno]);
X		else
X			s132[count] = 0;
X		if(s132[count - 1] == '\n')
X			s132[count - 1] = 0;
X		close(stderr_pipe[P_READ]);
X		if(strncmp(s132,"echo: ",6))
X			*expcmd = s132;
X		else
X			*expcmd = s132 + 6;
X		if(rcvr_alive)
X			start_rcvr_process(0);
X		return(-1);
X	}
X
X	signal(SIGINT,SIG_IGN);
X	signal(SIGTERM,SIG_IGN);
X	signal(SIGUSR1,SIG_IGN);
X	signal(SIGUSR2,SIG_IGN);
X	signal(SIGCLD,xmtr_xenix_SIGCLD_handler);
X
X	wait_status = 0;
X	while(((itmp = wait(&wait_status)) != pipe_pid) && (itmp != -1) &&
X		(last_child_wait_pid != pipe_pid))
X		;
X
X	xmtr_signals();
X	if((last_child_wait_pid == pipe_pid) && (last_child_wait_status))
X	{
X		free(*expcmd);
X		count = read(stderr_pipe[P_READ],s132,sizeof(s132) - 1);
X		if(count < 0)
X			strcpy(s132,sys_errlist[errno]);
X		else
X			s132[count] = 0;
X		if(s132[count - 1] == '\n')
X			s132[count - 1] = 0;
X		close(stderr_pipe[P_READ]);
X		if(strncmp(s132,"echo: ",6))
X			*expcmd = s132;
X		else
X			*expcmd = s132 + 6;
X		if(rcvr_alive)
X			start_rcvr_process(0);
X		return(-1);
X	}
X	close(stderr_pipe[P_READ]);
X
X	if(rcvr_alive)
X		start_rcvr_process(0);
X	return(0);
X}	/* end of expand_cmd_with_wildlist */
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
chmod 0644 ecufork.c || echo "restore of ecufork.c fails"
echo "x - extracting ecuhayes.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > ecuhayes.c &&
X/* CHK=0xA850 */
X/* #define USE_S7 */
X/*+-------------------------------------------------------------------------
X	ecuhayes.c
X	Copyright 1986,1989 Warren H. Tucker, III. All Rights Reserved
X
X  Defined functions:
X	hayes_ATH()
X	hayes_autoanswer()
X	hayes_dial()
X	hayes_dial_pde(tpde)
X	hayes_get_result(msec_to_wait)
X	hayes_get_sreg_value(regnum)
X	hayes_modem_init()
X	hayes_modem_on_hook()
X	hayes_read_modem_init()
X	hayes_redial(arg,argc)
X	hayes_report_iv_set(varnum)
X	hayes_send_cmd(cmd)
X	hayes_set_sreg(regnum,value)
X	process_modem_init(str)
X	show_modem_init_error(erc,iesd)
X
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:07-03-1989-22:57-wht------------- ecu 2.00 ---------------- */
X/*:06-24-1989-16:52-wht-flush edits --- ecu 1.95 */
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
Xextern int rcvr_pid;
Xextern int interrupt;
Xextern int proc_interrupt;
Xextern int proctrace;
Xextern long xmit_chars_this_connect;
Xextern char modem_ctl_fname[];	/* .ecu/modem file name */
Xextern ulong current_colors;
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	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 **pdinit;
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(ulcmpb(typestr,"autoanswer") < 0)
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)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	hayes_read_modem_init()
X0123456789
X/dev/ttyxx
X------------------------------------------------------------------------*/
Xvoid
Xhayes_read_modem_init()
X{
Xregister itmp;
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	strcpy(mi_name,"/usr/lib/ecu/");
X	strcat(mi_name,Lline + 5);
X	strcat(mi_name,".mi");
X		
X/* read modem initialization */
X	if((fp_modem = fopen(mi_name,"r")) == NULL)
X		pperror(mi_name);
X	else
X	{
X		mi_line = 0;
X/*		while((!Lmodem_init[0] || !Lmodem_dial[0] || !Lmodem_autoans[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 hayes_read_modem_init */
X
X/*+-------------------------------------------------------------------------
X	hayes_get_result(msec_to_wait)
Xreturn pointer to static buf containing result code
X--------------------------------------------------------------------------*/
Xchar *
Xhayes_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 */
SHAR_EOF
echo "End of part 3"
echo "File ecuhayes.c is continued in part 4"
echo "4" > s2_seq_.tmp
exit 0
-- 
-------------------------------------------------------------------
Warren Tucker, Tridom Corporation       ...!gatech!emory!tridom!wht 
Ker-au'-lo-phon.  An 8-foot partial flue-stop, having metal pipes
surmounted by adjustable rings, and with a hole bored near the top
of each pipe, producing a soft and "reedy" tone.